BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / quipu / entry_load.c
/* entry_load.c - load bits of the database */
#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/entry_load.c,v 7.6 91/03/09 11:56:52 mrose Exp $";
#endif
/*
* $Header: /f/osi/quipu/RCS/entry_load.c,v 7.6 91/03/09 11:56:52 mrose Exp $
*
*
* $Log: entry_load.c,v $
* Revision 7.6 91/03/09 11:56:52 mrose
* update
*
* Revision 7.5 91/02/22 09:39:20 mrose
* Interim 6.8
*
* Revision 7.4 90/10/17 11:54:17 mrose
* sync
*
* Revision 7.3 90/07/09 14:46:10 mrose
* sync
*
* Revision 7.2 90/04/18 08:49:54 mrose
* 6.2
*
* Revision 7.1 89/12/19 16:20:34 mrose
* sync
*
* Revision 7.0 89/11/23 22:17:39 mrose
* Release 6.0
*
*/
/*
* NOTICE
*
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
* this agreement.
*
*/
#include "config.h"
#include "quipu/util.h"
#include "quipu/entry.h"
#include "quipu/ds_error.h"
#include "tailor.h"
#include <sys/stat.h>
#include <errno.h>
#ifdef TURBO_AVL
#include "quipu/turbo.h"
#endif
extern char * treedir;
extern LLog * log_dsap;
extern int errno;
extern int parse_status;
struct acl_info * acl_dflt ();
#ifdef TURBO_INDEX
extern AttributeType *turbo_index_types;
#endif
static char filename [LINESIZE];
static PS ps;
#define EDBLEN 3 /* length of string "EDB" */
fileexists (fname)
char * fname;
{
struct stat buf;
if (stat (fname,&buf) != 0) {
if (errno != ENOENT)
DLOG (log_dsap,LLOG_DEBUG,("File %s will not stat - %d",fname,errno));
return FALSE;
}
return TRUE;
}
static read_mapped_rdn (aps,name,file)
PS aps;
char * name;
char * file;
{
FILE * mapfp;
char *ptr, *newname, *tmp, *getline();
extern int parse_line;
register int i;
if ((mapfp = fopen (file,"r")) == (FILE *)NULL) {
LLOG(log_dsap,LLOG_EXCEPTIONS,("Can read \"%s\" (%d)",file,errno));
return FALSE;
}
parse_line = 0;
while ( (ptr = getline(mapfp)) != NULLCP) {
if ((newname = rindex(ptr,'#')) == NULLCP) {
LLOG(log_dsap,LLOG_EXCEPTIONS,("Seperator missing in map file \"%s\", line %d",file,parse_line));
(void) fclose (mapfp);
return FALSE;
}
tmp = newname;
*newname++ = 0;
while (isspace(*--tmp))
*tmp = 0;
if (lexequ (name,ptr) == 0) {
/* got it - replace in ps*/
i = strlen (name);
aps->ps_ptr -= i;
aps->ps_cnt += i;
ps_print (aps,SkipSpace(newname));
(void) fclose (mapfp);
return TRUE;
}
}
DLOG (log_dsap, LLOG_DEBUG,("%s not found in map file %s",name,file));
(void) fclose (mapfp);
return FALSE;
}
static write_mapped_rdn (aps,name,file)
PS aps;
char * name;
char * file;
{
FILE * mapfp;
char mapname[LINESIZE];
char sname[LINESIZE];
char *mptr, *nptr;
register int i;
if (strlen(name) < MAXFILENAMELEN)
return FALSE;
/* Make unique name for it */
mptr = mapname;
if ((nptr = index (name,'=')) == NULLCP)
return FALSE;
for (i=0 ; (*nptr!=0) && (i < MAXFILENAMELEN-6) ; nptr++)
if (isalpha(*nptr))
*mptr++ = *nptr, i++;
(void) strcpy (sname,name);
(void) strcpy (mptr,"XXXXXX");
i = strlen (name);
nptr = (aps->ps_ptr -= i);
aps->ps_cnt += i;
ps_print (aps,mapname);
*aps->ps_ptr = 0;
if ((aps->ps_base = mktemp (aps->ps_base)) == NULLCP)
return FALSE;
DLOG(log_dsap,LLOG_DEBUG,("mapped name %s",aps->ps_base));
if (mkdir (aps->ps_base,0700) != 0) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("map rdn mkdir failure \"%s\" (%d)",aps->ps_base,errno));
return FALSE;
}
/* write it to map file */
if (fileexists(file))
mapfp = fopen (file,"a");
else {
int um;
um = umask (0177);
mapfp = fopen (file,"w");
(void) umask (um);
}
if (mapfp == (FILE *)NULL) {
LLOG(log_dsap,LLOG_EXCEPTIONS,("Can't write to \"%s\" (%d)",file,errno));
return FALSE;
}
if (fprintf (mapfp,"%s#%s\n",sname,nptr) == EOF) {
LLOG(log_dsap,LLOG_EXCEPTIONS,("Can't write to \"%s\" (%d)",file,errno));
return FALSE;
}
if (fclose (mapfp) != 0) {
LLOG(log_dsap,LLOG_EXCEPTIONS,("Can't close \"%s\" (%d)",file,errno));
return FALSE;
}
return TRUE;
}
static rdn2filename (aps,rdn,make)
PS aps;
RDN rdn;
char make;
{
char *start = aps->ps_ptr;
char mapbuf [LINESIZE];
/* look for EDB.map file */
*aps->ps_ptr = 0;
(void) sprintf (mapbuf, "%sEDB.map",aps->ps_base);
rdn_print (aps,rdn,DIROUT);
*aps->ps_ptr = 0;
if (fileexists (mapbuf) && read_mapped_rdn (aps,start,mapbuf)) {
*aps->ps_ptr = 0;
if (fileexists(aps->ps_base))
return OK;
if (make) {
if (mkdir (aps->ps_base,0700) != 0) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("dn2file mkdir (mapped) failure \"%s\" (%d)",aps->ps_base,errno));
return NOTOK;
}
LLOG (log_dsap,LLOG_NOTICE,("WARNING: Needed to make mapped directory \"%s\"",aps->ps_base));
return OK;
}
LLOG (log_dsap,LLOG_EXCEPTIONS,("mapped file missing \"%s\"",aps->ps_base));
return NOTOK;
}
#ifdef SYS5
else if ( strlen(start) > MAXFILENAMELEN )
LLOG (log_dsap,LLOG_EXCEPTIONS,("Potential problem with \"%s\" (name too long)",start));
#endif
if (fileexists(aps->ps_base))
return OK;
if (make) {
if (write_mapped_rdn (aps,start,mapbuf))
return OK;
if (mkdir (aps->ps_base,0700) != 0) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("dn2file mkdir failure \"%s\" (%d)",aps->ps_base,errno));
return NOTOK;
}
return OK;
}
return NOTOK;
}
static dn2filename (aps,dn,make)
PS aps;
DN dn;
char make;
{
if (treedir != NULLCP) {
ps_print (aps,isodefile(treedir,0));
if (make) {
*aps->ps_ptr = 0;
if ((! fileexists (aps->ps_base)) &&
(mkdir (aps->ps_base,0700) != 0)) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("dn2file mkdir failure \"%s\" (%d)",aps->ps_base,errno));
return NOTOK;
}
}
if (*(aps->ps_ptr - 1) != '/')
ps_print (aps,"/");
} else
ps_print (aps,"./");
if (dn != NULLDN) {
if (rdn2filename (aps,dn->dn_rdn,make) == NOTOK)
return NOTOK;
if (dn->dn_parent != NULLDN) {
DN eptr;
for (eptr = dn->dn_parent; eptr != NULLDN; eptr = eptr->dn_parent) {
ps_print (aps,"/");
if (rdn2filename (aps,eptr->dn_rdn,make) == NOTOK)
return NOTOK;
}
}
}
return OK;
}
char * dn2edbfile (dn)
DN dn;
{
PS aps;
static char result [LINESIZE];
if ((aps = ps_alloc (str_open)) == NULLPS) {
LLOG (log_dsap, LLOG_EXCEPTIONS, ("dn2dir ps_alloc failed"));
return NULLCP;
}
if (str_setup (aps,result,LINESIZE,1) == NOTOK) {
LLOG (log_dsap, LLOG_EXCEPTIONS, ("dn2dir ps_alloc failed"));
return NULLCP;
}
if (dn2filename (aps,dn,TRUE) != OK)
return NULLCP;
if (*(aps->ps_ptr - 1) != '/')
ps_print (aps,"/EDB");
else
ps_print (aps,"EDB");
*aps->ps_ptr = 0;
ps_free (aps);
return result;
}
static file_check (offset,entryptr)
register int offset;
register Entry entryptr;
{
ps->ps_ptr = filename + offset;
ps->ps_cnt = LINESIZE - offset;
if (rdn2filename (ps,entryptr->e_name,FALSE) == OK) {
if (*(ps->ps_ptr - 1) != '/')
ps_print (ps,"/EDB");
else
ps_print (ps,"EDB");
*ps->ps_ptr = 0;
return (OK);
}
return (NOTOK);
}
#ifdef TURBO_AVL
static char got_all = TRUE;
static load_a_kid(e, offset)
Entry e;
int offset;
{
static int entry_load_kids();
if ((!e->e_external) &&
(e->e_master == NULLAV) &&
(e->e_slave == NULLAV)) {
e->e_leaf = TRUE;
e->e_allchildrenpresent = 2;
return(OK);
}
if (file_check(offset, e) == OK) {
if ((e->e_children = getentry_block(e, filename)) == NULLAVL) {
if (e->e_allchildrenpresent != FALSE &&
e->e_leaf == FALSE)
return(OK);
else
return(NOTOK) ;
}
if (parse_status != 0)
return(NOTOK);
e->e_leaf = FALSE;
if (entry_load_kids(e->e_children, strlen( filename ) - EDBLEN)
== NOTOK)
return (NOTOK);
if (e->e_allchildrenpresent != 2)
got_all = FALSE;
} else {
LLOG (log_dsap, LLOG_TRACE, ("Sibling file %s/EDB NOT found", filename));
e->e_allchildrenpresent = FALSE;
got_all = FALSE;
}
return(OK);
}
#endif /* TURBO_AVL */
static entry_load_kids (entryptr,offset)
#ifdef TURBO_AVL
Avlnode *entryptr; /* in this case, entryptr is really a tree of kids */
#else
register Entry entryptr;
#endif
register int offset;
{
#ifdef TURBO_AVL
Entry akid, parent;
#else
register Entry ptr;
char got_all = TRUE;
#endif
ps->ps_ptr = filename + offset;
ps->ps_cnt = LINESIZE - offset;
*ps->ps_ptr = 0;
#ifdef TURBO_AVL
if (entryptr == NULLAVL)
return(OK);
got_all = TRUE;
if (avl_apply(entryptr, load_a_kid, (caddr_t) offset, NOTOK, AVL_PREORDER)
== NOTOK)
return(NOTOK);
akid = (Entry) avl_getone(entryptr);
if (akid && (parent = akid->e_parent)) {
if (got_all) {
if (parent->e_allchildrenpresent == 1)
parent->e_allchildrenpresent = 2;
} else if (parent->e_allchildrenpresent == 2)
parent->e_allchildrenpresent = 1;
}
#else
if (entryptr == NULLENTRY)
return OK;
for ( ptr = entryptr; ptr != NULLENTRY; ptr = ptr->e_sibling) {
if ((!ptr->e_external) &&
(ptr->e_master == NULLAV) &&
(ptr->e_slave == NULLAV)) {
ptr->e_leaf = TRUE;
ptr->e_allchildrenpresent = 2;
continue;
}
if (file_check (offset,ptr) == OK) {
if ((ptr->e_child = getentry_block (ptr,filename)) == NULLENTRY)
{
if (ptr->e_allchildrenpresent != FALSE &&
ptr->e_leaf == FALSE)
continue;
else
return (NOTOK) ;
}
if (parse_status != 0)
return NOTOK;
ptr->e_leaf = FALSE;
if (entry_load_kids (ptr->e_child,strlen(filename) - EDBLEN) == NOTOK)
return (NOTOK);
if (ptr->e_allchildrenpresent != 2)
got_all = FALSE;
} else {
LLOG (log_dsap,LLOG_TRACE,("WARNING, sibling file %s/EDB NOT found", filename));
ptr->e_allchildrenpresent = FALSE;
got_all = FALSE;
}
}
if (entryptr->e_parent) {
if (got_all) {
if (entryptr->e_parent->e_allchildrenpresent == 1)
entryptr->e_parent->e_allchildrenpresent = 2;
} else if (entryptr->e_parent->e_allchildrenpresent == 2)
entryptr->e_parent->e_allchildrenpresent = 1;
}
#endif /* TURBO_AVL */
return (OK);
}
#ifdef TURBO_AVL
static char got_subtree;
static check_entry_free (e)
Entry e;
{
if (e->e_allchildrenpresent < 2)
got_subtree = FALSE;
entry_free(e);
}
parent_link(e, parent)
Entry e;
Entry parent;
{
struct DSError error;
int res;
e->e_parent = parent;
set_inheritance (e);
return(OK);
}
static merge_entry(newentry, oldtree)
Entry newentry;
Avlnode *oldtree;
{
Entry p;
int entry_cmp();
newentry->e_parent = ((Entry) avl_getone(oldtree))->e_parent;
if ((p = (Entry) avl_find(oldtree, (caddr_t) newentry, entry_cmp))
!= NULLENTRY ) {
newentry->e_leaf = FALSE;
newentry->e_allchildrenpresent = p->e_allchildrenpresent;
newentry->e_children = p->e_children;
(void) avl_apply(newentry->e_children, parent_link, (caddr_t) newentry,
NOTOK, AVL_PREORDER);
if (p->e_edbversion != NULLCP)
newentry->e_edbversion = strdup(p->e_edbversion);
} else {
got_subtree = FALSE;
newentry->e_allchildrenpresent = FALSE;
}
return(OK);
}
#endif /* TURBO_AVL */
Entry subtree_load (parent,dn)
Entry parent;
DN dn;
{
char failed = FALSE;
#ifdef TURBO_AVL
Avlnode *treetop;
Entry akid;
int entry_free();
#else
Entry temp, old_entry;
char got_subtree = TRUE;
Entry treetop, sibl, find_sibling();
#endif
#ifdef TURBO_AVL
got_subtree = TRUE;
if ((parent != NULLENTRY) && (parent->e_children != NULLAVL)) {
akid = (Entry) avl_getone(parent->e_children);
if (akid->e_data != E_TYPE_CONSTRUCTOR)
return (parent);
}
#else
if ((parent != NULLENTRY) && (parent->e_child != NULLENTRY))
if (parent->e_child->e_data != E_TYPE_CONSTRUCTOR)
return (parent->e_child);
#endif
if ((ps = ps_alloc (str_open)) == NULLPS) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("file open ps_alloc failed"));
return (NULLENTRY);
}
if (str_setup (ps,filename,LINESIZE,1) == NOTOK) {
LLOG (log_dsap,LLOG_EXCEPTIONS,("file open ps_alloc failed"));
return (NULLENTRY);
}
(void) dn2filename (ps,dn,FALSE);
if (*(ps->ps_ptr - 1) != '/')
ps_print (ps,"/EDB");
else
ps_print (ps,"EDB");
*ps->ps_ptr = 0;
#ifdef TURBO_AVL
if (parent != NULLENTRY && parent->e_children != NULLAVL) {
#else
if ((parent != NULLENTRY) && (parent->e_child != NULLENTRY)) {
#endif
/* yuk - already got an edb lower in the DIT ... */
treetop = getentry_block (parent,filename);
if (parse_status != 0)
return NULLENTRY;
#ifdef TURBO_AVL
/*
* go through the tree we just loaded, merging it with the
* tree previously loaded.
*/
(void) avl_apply(treetop, merge_entry, (caddr_t) parent->e_children,
NOTOK, AVL_PREORDER);
if (got_subtree && (parent->e_allchildrenpresent == 1))
parent->e_allchildrenpresent = 2;
got_subtree = TRUE;
/* free the old tree and set got_subtree */
(void) avl_free(parent->e_children, check_entry_free);
if (got_subtree && (parent->e_allchildrenpresent == 1))
parent->e_allchildrenpresent = 2;
parent->e_children = treetop;
#else
for (temp = treetop; temp != NULLENTRY; temp=temp->e_sibling) {
temp->e_parent = parent;
if ((old_entry = find_sibling (temp->e_name,parent->e_child)) != NULLENTRY) {
temp->e_leaf = FALSE;
if ((temp->e_allchildrenpresent = old_entry->e_allchildrenpresent) < 2 )
got_subtree = FALSE;
temp->e_child = old_entry->e_child;
for (sibl = temp->e_child; sibl != NULLENTRY; sibl=sibl->e_sibling) {
sibl->e_parent = temp;
set_inheritance (sibl);
}
if (old_entry->e_edbversion != NULLCP)
temp->e_edbversion = strdup (old_entry->e_edbversion);
} else if ( ! temp->e_leaf) {
got_subtree = FALSE;
temp->e_allchildrenpresent = FALSE;
}
}
if (got_subtree && (treetop->e_allchildrenpresent == 1))
treetop->e_allchildrenpresent = 2;
got_subtree = TRUE;
for (temp = parent->e_child; temp != NULLENTRY; temp=old_entry) {
old_entry = temp->e_sibling;
if (temp->e_allchildrenpresent < 2)
got_subtree = FALSE;
entry_free (temp);
}
if (got_subtree && (parent->e_allchildrenpresent == 1))
parent->e_allchildrenpresent = 2;
/* do we need to ripple e_allchildrenpresent higher ? */
#endif
ps_free (ps);
#ifdef TURBO_AVL
parent->e_children = treetop;
return(parent);
#else
parent->e_child = treetop;
return (treetop);
#endif
}
if (dn == NULLDN) {
parent = get_default_entry (NULLENTRY);
parent->e_leaf = FALSE;
parent->e_acl = acl_alloc();
parent->e_acl->ac_child = acl_dflt ();
parent->e_acl->ac_entry = acl_dflt ();
parent->e_acl->ac_default = acl_dflt ();
#ifdef TURBO_AVL
if ((treetop = getentry_block (parent,filename)) == NULLAVL)
#else
if ((treetop = getentry_block (parent,filename)) == NULLENTRY)
#endif
return (NULLENTRY);
} else
treetop = getentry_block (parent,filename);
if (parse_status != 0)
failed = TRUE;
#ifdef TURBO_AVL
parent->e_children = treetop;
#else
parent->e_child = treetop;
#endif
if (entry_load_kids (treetop,strlen (filename) - EDBLEN) == NOTOK) {
parse_status++;
return (NULLENTRY);
}
ps_free (ps);
if (failed) {
parse_status++;
return (NULLENTRY);
}
#ifdef TURBO_AVL
return(parent);
#else
if (dn == NULLDN)
return (parent); /* be wary of this when calling subtree load... */
/* if DN == NULL - you may want the child !!! */
else
return (treetop);
#endif
}
int refreshing;
refresh_from_disk(dn)
DN dn;
{
Entry child;
Entry parent;
Entry tmp;
extern Entry database_root;
if ((parent = local_find_entry (dn,FALSE)) == NULLENTRY)
return (NOTOK);
if (parent->e_data != E_DATA_MASTER)
LLOG (log_dsap,LLOG_EXCEPTIONS, ("WARNING: refreshing SLAVE EDB file -- should not be needed"));
#ifdef TURBO_AVL
child = (Entry) entry_cpy(parent);
child->e_parent = parent->e_parent;
child->e_children = parent->e_children;
parent->e_children = NULLAVL;
#else
child = parent->e_child;
parent->e_child = NULLENTRY;
#endif
refreshing = TRUE;
if (dn == NULLDN)
tmp = subtree_load (NULLENTRY,NULLDN);
else
tmp = subtree_load (parent,dn);
refreshing = FALSE;
if (tmp == NULLENTRY)
return (NOTOK);
if (dn == NULLDN) {
database_root = child;
directory_free (child);
database_root = tmp;
} else
directory_free(child);
return (OK);
}