/*==================================================== * parserefnrec -- Store refn rec in file buffers *==================================================*/ static void parserefnrec (RKEY rkey, CNSTRING p) { INT i; RRkey = rkey; /* Store refn record in data structures */ memcpy (&RRcount, p, sizeof(INT)); p += sizeof(INT); if (RRcount >= RRmax - 1) { if (RRmax != 0) { stdfree(RRkeys); stdfree(RRoffs); stdfree((STRING)RRrefns); } RRmax = RRcount + 10; RRkeys = (RKEY *) stdalloc((RRmax)*sizeof(RKEY)); RRoffs = (INT *) stdalloc((RRmax)*sizeof(INT)); RRrefns = (CNSTRING *) stdalloc((RRmax)*sizeof(STRING)); } for (i = 0; i < RRcount; i++) { memcpy(&RRkeys[i], p, sizeof(RKEY)); p += sizeof(RKEY); } for (i = 0; i < RRcount; i++) { memcpy(&RRoffs[i], p, sizeof(INT)); p += sizeof(INT); } for (i = 0; i < RRcount; i++) RRrefns[i] = p + RRoffs[i]; }
/*================================ * create_hashtab -- Create & return new hash table *==============================*/ HASHTAB create_hashtab (void) { HASHTAB tab = (HASHTAB)stdalloc(sizeof(*tab)); tab->magic = hashtab_magic; tab->maxhash = MAXHASH_DEF; tab->entries = (HASHENT *)stdalloc(tab->maxhash * sizeof(HASHENT)); return tab; }
/*========================================================= * create_array_objval -- Create array (which holds objects) *=======================================================*/ ARRAY create_array_objval (INT size) { ARRAY array = 0; if (!size) size=20; ASSERT(size >= 1); array = (ARRAY)stdalloc(sizeof(*array)); memset(array, 0, sizeof(*array)); array->vtable = &vtable_for_array; ASize(array) = 0; AMax(array) = size; AData(array) = (void **)stdalloc(size * sizeof(AData(array)[0])); return array; }
/*=============================================+ * make_empty_string_table -- Create table of strings * allocate table and initialize all strings to NULL * nels: [IN] number of elements in table * Returns dynamically allocated array *============================================*/ static STRING * make_empty_string_table (INT nels) { STRING * arrd = (STRING *)stdalloc(nels * sizeof(arrd[0])); memset(arrd, 0, nels * sizeof(arrd[0])); return arrd; }
/*=============================================+ * make_empty_pvalue_table -- Create table of pvalue pointers * allocate table and initialize all pointers to NULL * nels: [IN] number of elements in table * Returns dynamically allocated array *============================================*/ static PVALUE * make_empty_pvalue_table (INT nels) { PVALUE * arrd = (PVALUE*)stdalloc(nels * sizeof(arrd[0])); memset(arrd, 0, nels * sizeof(arrd[0])); return arrd; }
/*======================================== * lldb_alloc -- Create lldb structure * This does not actually create or open a database. * It only creates this structure to hold the errors * and point to the database when it is opened (or * created) later. *======================================*/ LLDATABASE lldb_alloc (void) { LLDATABASE lldb = (LLDATABASE)stdalloc(sizeof(*lldb)); memset(lldb, 0, sizeof(*lldb)); return lldb; }
/*=============================== * strsave -- Save copy of string * returns stdalloc'd memory *=============================*/ STRING strsave (CNSTRING str) { /* some OSs (made in Redmond) do not handle strdup(0) very well */ ASSERT(str); return strcpy(stdalloc(strlen(str) + 1), str); }
/*============================== * allocsubbytes -- Return substring (by byte counts) * assumes valid inputs * returns alloc'd memory * start is 0-based start byte, len is # bytes * strictly at the byte level * client is responsible for codeset * Created: 2001/08/02 (Perry Rapp) *============================*/ STRING allocsubbytes (STRING s, INT start, INT num) { STRING substr; substr = stdalloc(num+1); strncpy(substr, &s[start], num); substr[num] = 0; return substr; }
/*================================ * create_entry -- Create and return new hash entry *==============================*/ static HASHENT create_entry (CNSTRING key, HVALUE val) { HASHENT entry = (HASHENT)stdalloc(sizeof(*entry)); entry->magic = hashent_magic; entry->ekey = strsave(key); entry->val = val; return entry; }
/*=============================================== * alloc_namerefn -- allocates a new NAMEREFN_REC * Created: 2001/01/01, Perry Rapp *=============================================*/ static NAMEREFN_REC * alloc_namerefn (CNSTRING namerefn, CNSTRING key, INT err) { NAMEREFN_REC * rec = (NAMEREFN_REC *)stdalloc(sizeof(*rec)); rec->namerefn = strsave(namerefn); rec->key = strsave(key); rec->err = err; return rec; }
/*================================================= * alloc_displaynode -- get new displaynode * In preparation for using a block allocator *===============================================*/ static DISPNODE alloc_displaynode (void) { DISPNODE tn = (DISPNODE)stdalloc(sizeof(*tn)); tn->firstchild = NULL; tn->nextsib = NULL; tn->keynum = 0; tn->str = NULL; return tn; }
/*========================================= * node_to_string -- Convert tree to string *=======================================*/ STRING node_to_string (NODE node) /* root */ { INT len = tree_strlen(0, node) + 1; STRING str; if (len <= 0) return NULL; str = (STRING) stdalloc(len); (void) swrite_nodes(0, node, str); return str; }
/*==================================================== * getrefnrec -- Read refn record and store in globals *==================================================*/ BOOLEAN getrefnrec (CNSTRING refn) { STRING p; /* Convert refn to key and read refn record */ RRkey = refn2rkey(refn); if (RRrec) stdfree(RRrec); p = RRrec = bt_getrecord(BTR, &RRkey, &RRsize); if (!RRrec) { RRcount = 0; if (RRmax == 0) { RRmax = 10; RRkeys = (RKEY *) stdalloc(10*sizeof(RKEY)); RRoffs = (INT *) stdalloc(10*sizeof(INT)); RRrefns = (CNSTRING *) stdalloc(10*sizeof(STRING)); } return FALSE; } parserefnrec(RRkey, p); return TRUE; }
/*====================================== * insert_table_int -- Insert key & INT value into table *====================================*/ void insert_table_int (TABLE tab, CNSTRING key, INT ival) { INT * newval = stdalloc(sizeof(*newval)); *newval = ival; ASSERT(tab); ASSERT(tab->valtype == TB_INT); insert_table_ptr(tab, key, newval); }
/*================================================= * begin_table_iter -- Begin iteration of table * returns addref'd iterator object *===============================================*/ TABLE_ITER begin_table_iter (TABLE tab) { TABLE_ITER tabit = (TABLE_ITER)stdalloc(sizeof(*tabit)); ++tabit->refcnt; if (tab->rbtree) { tabit->rbit = RbBeginIter(tab->rbtree, 0, 0); } else { tabit->hashtab_iter = begin_hashtab(tab->hashtab); } return tabit; }
/*=================================================== * add_path_files_to_proplist -- Add all files on path to list of property tables * Created: 2002/10/19, Perry Rapp *=================================================*/ INT add_path_files_to_proplist (CNSTRING path, SELECT_FNC selectfnc, LIST list) { STRING dirs, p; INT ct=0; if (!path || !path[0]) return 0; dirs = (STRING)stdalloc(strlen(path)+2); chop_path(path, dirs); for (p=dirs; *p; p+=strlen(p)+1) { add_dir_files_to_proplist(p, selectfnc, list); } return ct; }
/*================================ * begin_hashtab -- Create new iterator for hash table *==============================*/ HASHTAB_ITER begin_hashtab (HASHTAB tab) { HASHTAB_ITER tabit=0; ASSERT(tab); ASSERT(tab->magic == hashtab_magic); tabit = (HASHTAB_ITER)stdalloc(sizeof(*tabit)); tabit->magic = hashtab_iter_magic; tabit->hashtab = tab; /* table iterator starts at index=0, enext=0 */ /* stdalloc gave us all zero memory */ return tabit; }
/*============================================= * remove_refn -- Remove entry from refn record *===========================================*/ BOOLEAN remove_refn (CNSTRING refn, /* record's refn */ CNSTRING key) /* record's GEDCOM key */ { STRING rec, p; INT i, len, off; BOOLEAN found; RKEY rkey; rkey = str2rkey(key); (void) getrefnrec(refn); found = FALSE; for (i = 0; i < RRcount; i++) { if (!ll_strncmp(rkey.r_rkey, RRkeys[i].r_rkey, 8) && eqstr(refn, RRrefns[i])) { found = TRUE; break; } } if (!found) return FALSE; RRcount--; for ( ; i < RRcount; i++) { RRkeys[i] = RRkeys[i+1]; RRrefns[i] = RRrefns[i+1]; } p = rec = (STRING) stdalloc(RRsize); len = 0; memcpy(p, &RRcount, sizeof(INT)); p += sizeof(INT); len += sizeof(INT); for (i = 0; i < RRcount; i++) { memcpy(p, &RRkeys[i], sizeof(RKEY)); p += sizeof(RKEY); len += sizeof(RKEY); } off = 0; for (i = 0; i < RRcount; i++) { memcpy(p, &off, sizeof(INT)); p += sizeof(INT); len += sizeof(INT); off += strlen(RRrefns[i]) + 1; } for (i = 0; i < RRcount; i++) { memcpy(p, RRrefns[i], strlen(RRrefns[i]) + 1); p += strlen(RRrefns[i]) + 1; len += strlen(RRrefns[i]) + 1; } bt_addrecord(BTR, RRkey, rec, len); stdfree(rec); return TRUE; }
/*================================================= * append_to_text_list - add onto fixed width string list * newline: flag to not append to last element of list * we build each line in current, and add it to list as done * ptr points to the undone part of text * curptr points to the end (insertion point) of current * NB: We also build list from last to first, so client can use * FORLIST traversal (which is backwards) * TO DO: Break at whitespace *=================================================*/ static void append_to_text_list (LIST list, STRING text, INT width, BOOLEAN newline) { STRING ptr = text; STRING temp, current, curptr; INT len, curlen; if (!text || !text[0]) return; /* pull off last line into temp, to append to */ if (newline) { temp = NULL; } else { temp = pop_list(list); if (temp && (INT)strlen(temp) >= width) { enqueue_list(list, temp); temp = NULL; } } current=stdalloc((width+1)*sizeof(char)); current[0] = 0; curptr = current; curlen = width; if (temp) { llstrcatn(&curptr, temp, &curlen); } while (1) { len = strlen(ptr); if (!len) { /* done */ if (current[0]) { enqueue_list(list, strsave(current)); } stdfree(current); return; } if (len > curlen) len = curlen; temp = curptr; llstrcatn(&curptr, ptr, &curlen); ptr += (curptr - temp); if (!curlen) { /* filled up an item */ enqueue_list(list, strsave(current)); current[0] = 0; curptr = current; curlen = width; } } }
/*================================== * strconcat -- Catenate two strings * Either (but not both) args may be null * returns stdalloc'd memory *================================*/ STRING strconcat (STRING s1, STRING s2) { INT len; STRING s3; s1 = s1 ? s1 : ""; s2 = s2 ? s2 : ""; if (!s1[0]) return strsave(s2); if (!s2[0]) return strsave(s1); len = strlen(s1)+strlen(s2); s3 = (STRING) stdalloc(len+1); strcpy(s3, s1); strcat(s3, s2); return s3; }
/*================================================= * set_generic_float -- populate gen with float generic *===============================================*/ void set_generic_float (GENERIC *gen, FLOAT fval) { /* check for self-assignment */ if (gen->selector == GENERIC_FLOAT) { *gen->data.fval = fval; return; } /* clear old value, freeing any associated memory as appropriate */ clear_generic(gen); /* set new value */ gen->selector = GENERIC_FLOAT; gen->data.fval = stdalloc(sizeof(fval)); *gen->data.fval = fval; }
/*============================= * create_table_impl -- Create table * All tables are created in this function * returns addref'd table *===========================*/ static TABLE create_table_impl (enum TB_VALTYPE valtype, DELFUNC delfunc) { TABLE tab = (TABLE) stdalloc(sizeof(*tab)); tab->vtable = &vtable_for_table; tab->refcnt = 1; tab->valtype = valtype; if (getlloptstr("rbtree", 0)) tab->rbtree = RbTreeCreate(tab, rbcompare, rbdestroy); else tab->hashtab = create_hashtab(); tab->destroyfunc = delfunc; return tab; }
/*==================================================== * get_refns -- Find all records who match refn or key *==================================================*/ void get_refns (STRING refn, INT *pnum, STRING **pkeys, INT letr) { INT i, n; *pnum = 0; if (!refn) return; /* Clean up allocated memory from last call */ if (RMcount) { for (i = 0; i < RMcount; i++) stdfree(RMkeys[i]); } RMcount = 0; /* Load static refn buffers; return if no match */ if (!getrefnrec(refn)) return; /* Compare user's refn with all refns in record; the refn record data structures are modified */ n = 0; for (i = 0; i < RRcount; i++) { if (eqstr(refn, RRrefns[i])) { if (letr == 0 || *(rkey2str(RRkeys[i])) == letr) { if (i != n) { RRrefns[n] = RRrefns[i]; RRkeys[n] = RRkeys[i]; } n++; } } } *pnum = RRcount = n; if (RRcount > RMmax) { if (RMmax) stdfree(RMkeys); RMkeys = (STRING *) stdalloc(RRcount*sizeof(STRING)); RMmax = RRcount; } for (i = 0; i < RRcount; i++) RMkeys[i] = strsave(rkey2str(RRkeys[i])); *pkeys = RMkeys; }
/*========================================================= * enlarge_array -- Make array large enough for [space] elements *=======================================================*/ void enlarge_array (ARRAY array, INT space) { int newsize = AMax(array); void ** ptr; int i; while (newsize <= space) newsize <<= 2; if (newsize<AMax(array)) return; ptr = (void **)stdalloc(newsize * sizeof(AData(array)[0])); for (i = 0; i < ASize(array); i++) ptr[i] = AData(array)[i]; stdfree(AData(array)); AData(array) = ptr; AMax(array) = newsize; }
/*========================================== * growxrefs -- Grow memory for xrefs array. * generic for all types *========================================*/ static void growxrefs (DELETESET set) { INT i, m = set->max, *newp; if (set->max == 0) set->max = 64; while (set->max <= set->n) set->max = set->max << 1; newp = (INT *) stdalloc((set->max)*sizeof(INT)); if (m) { for (i = 0; i < set->n; i++) newp[i] = set->recs[i]; stdfree(set->recs); } set->recs = newp; }
/*========================================= * add_refn -- Add new entry to refn record * refn: [IN] record's user refn key * key: [IN] record's GEDCOM key *=======================================*/ BOOLEAN add_refn (CNSTRING refn, CNSTRING key) { STRING rec, p; INT i, len, off; RKEY rkey; rkey = str2rkey(key); (void) getrefnrec(refn); for (i = 0; i < RRcount; i++) { if (!ll_strncmp(rkey.r_rkey, RRkeys[i].r_rkey, 8) && eqstr(refn, RRrefns[i])) return TRUE; } RRkeys[RRcount] = rkey; RRrefns[RRcount] = refn; RRcount++; p = rec = (STRING) stdalloc(RRsize + sizeof(RKEY) + sizeof(INT) + strlen(refn) + 10); len = 0; memcpy(p, &RRcount, sizeof(INT)); p += sizeof(INT); len += sizeof(INT); for (i = 0; i < RRcount; i++) { memcpy(p, &RRkeys[i], sizeof(RKEY)); p += sizeof(RKEY); len += sizeof(RKEY); } off = 0; for (i = 0; i < RRcount; i++) { memcpy(p, &off, sizeof(INT)); p += sizeof(INT); len += sizeof(INT); off += strlen(RRrefns[i]) + 1; } for (i = 0; i < RRcount; i++) { memcpy(p, RRrefns[i], strlen(RRrefns[i]) + 1); p += strlen(RRrefns[i]) + 1; len += strlen(RRrefns[i]) + 1; } bt_addrecord(BTR, RRkey, rec, len); stdfree(rec); return TRUE; }
/*========================================+ * llrpt_pagemode -- Switch output to page mode * usage: pagemode(INT, INT) -> VOID *======================================*/ PVALUE llrpt_pagemode (PNODE node, SYMTAB stab, BOOLEAN *eflg) { INT cols=0, rows=0; PNODE argvar = builtin_args(node); PVALUE val = eval_and_coerce(PINT, argvar, stab, eflg); if (*eflg) { prog_var_error(node, stab, argvar, val, nonintx, "pagemode", "1"); delete_pvalue_ptr(&val); return NULL; } rows = pvalue_to_int(val); delete_pvalue_ptr(&val); val = eval_and_coerce(PINT, argvar=inext(argvar), stab, eflg); if (*eflg) { prog_var_error(node, stab, argvar, val, nonintx, "pagemode", "2"); delete_pvalue_ptr(&val); return NULL; } cols = pvalue_to_int(val); delete_pvalue_ptr(&val); *eflg = TRUE; if (!(cols >= 1 && cols <= MAXCOLS)) { *eflg = TRUE; prog_var_error(node, stab, argvar, val, badargx, "pagemode", "1"); return NULL; } if (!(rows >= 1 && rows <= MAXROWS)) { *eflg = TRUE; prog_var_error(node, stab, argvar, val, badargx, "pagemode", "2"); return NULL; } *eflg = FALSE; outputmode = PAGEMODE; __rows = rows; __cols = cols; if (pagebuffer) stdfree(pagebuffer); pagebuffer = (STRING) stdalloc(__rows*__cols); memset(pagebuffer, ' ', __rows*__cols); return NULL; }
/*============================================= * value_to_list -- Convert string to word list * str: [IN] input string to split up * list: [OUT] list of strings in name * plen: [OUT] #entries in list * dlm: [IN] delimiter upon which to split str *===========================================*/ LIST value_to_list (STRING str, INT *plen, STRING dlm) { static STRING buf = NULL; static INT len0 = 0; STRING p, q, n; INT len, c, i, j; LIST list = create_list2(LISTDOFREE); if (!str || *str == 0) return list; if ((len = strlen(str)) > len0 - 2) { if (buf) stdfree(buf); buf = (STRING) stdalloc(len0 = len + 80); } strcpy(buf, str); buf[len + 1] = 0; p = buf; j = 1; while ((c = *p++)) { if (in_string(c, dlm)) { *(p - 1) = 0; j++; } } p = buf; for (i = 1; i <= j; i++) { n = p + strlen(p) + 1; while (chartype(c = *p++) == WHITE) ; p--; q = p + strlen(p) - 1; while (q > p && chartype(*q) == WHITE) *q-- = 0; set_list_element(list, i, strsave(p), NULL); p = n; } *plen = j; return list; }
/*============================================ * bt_openbtree -- Alloc and init BTREE structure * If it fails, it returns NULL and sets the *lldberr * dir: [IN] btree base dir * cflag: [IN] create btree if no exist? * writ: [IN] requesting write access? 1=yes, 2=requiring * immut: [I/O] user can/will not change anything including keyfile * lldberr: [OUT] error code (if returns NULL) * If this succeeds, it sets readonly & immutable flags in btree structure * as appropriate (eg, if keyfile couldn't be opened in readwrite mode) *==========================================*/ BTREE bt_openbtree (STRING dir, BOOLEAN cflag, INT writ, BOOLEAN immut, INT *lldberr) { BTREE btree; char scratch[200]; FILE *fk=NULL; struct stat sbuf; KEYFILE1 kfile1; KEYFILE2 kfile2; BOOLEAN keyed2 = FALSE; STRING dbmode; /* we only allow 150 characters in base directory name */ *lldberr = 0; if (strlen(dir) > 150) { *lldberr = BTERR_LNGDIR; goto failopenbtree; } /* See if base directory exists */ if (stat(dir, &sbuf)) { /* db directory not found */ if (!cflag || !writ || immut) { *lldberr = BTERR_NODB; goto failopenbtree; } /* create flag set, so try to create it & stat again */ sprintf(scratch, "%s/", dir); if (!mkalldirs(scratch) || stat(dir, &sbuf)) { *lldberr = BTERR_DBCREATEFAILED; goto failopenbtree; } } else if (!S_ISDIR(sbuf.st_mode)) { /* found but not directory */ *lldberr = BTERR_DBBLOCKEDBYFILE; goto failopenbtree; } /* db dir was found, or created & then found */ if (access(dir, 0)) { *lldberr = BTERR_DBACCESS; goto failopenbtree; } /* See if key file exists */ sprintf(scratch, "%s/key", dir); if (stat(scratch, &sbuf)) { /* no keyfile */ if (!cflag) { *lldberr = BTERR_NOKEY; goto failopenbtree; } /* create flag set, so try to create it & stat again */ if (!initbtree(dir, lldberr) || stat(scratch, &sbuf)) { /* initbtree actually set *lldberr, but we ignore it */ *lldberr = BTERR_DBCREATEFAILED; goto failopenbtree; } } else { if (cflag) { /* keyfile found - don't create on top of it */ *lldberr = BTERR_EXISTS; goto failopenbtree; } } if (!S_ISREG(sbuf.st_mode)) { /* keyfile is a directory! */ *lldberr = BTERR_KFILE; goto failopenbtree; } /* Open and read key file (KEYFILE1) */ immutretry: dbmode = immut ? LLREADBINARY : LLREADBINARYUPDATE; if (!(fk = fopen(scratch, dbmode))) { if (!immut && writ<2) { /* maybe it is read-only media */ immut = TRUE; goto immutretry; } *lldberr = BTERR_KFILE; goto failopenbtree; } if (fread(&kfile1, sizeof(kfile1), 1, fk) != 1) { *lldberr = BTERR_KFILE; goto failopenbtree; } /* Read & validate KEYFILE2 - if not present, we'll add it below */ /* see btree.h for explanation of KEYFILE2 */ if (fread(&kfile2, sizeof(kfile2), 1, fk) == 1) { if (!validate_keyfile2(&kfile2, lldberr)) goto failopenbtree; /* validate set *lldberr */ keyed2=TRUE; } if (writ < 2 && kfile1.k_ostat == -2) immut = TRUE; /* keyfile contains the flag for immutable access only */ /* if not immutable, handle reader/writer protection update */ if (!immut) { if (kfile1.k_ostat == -1) { *lldberr = BTERR_WRITER; goto failopenbtree; } if (kfile1.k_ostat == -2) { *lldberr = BTERR_LOCKED; goto failopenbtree; } /* Update key file for this new opening */ if (writ>0 && (kfile1.k_ostat == 0)) kfile1.k_ostat = -1; else kfile1.k_ostat++; rewind(fk); if (fwrite(&kfile1, sizeof(kfile1), 1, fk) != 1) { *lldberr = BTERR_KFILE; goto failopenbtree; } if (!keyed2) { /* add KEYFILE2 structure */ init_keyfile2(&kfile2); if (fwrite(&kfile2, sizeof(kfile2), 1, fk) != 1) { *lldberr = BTERR_KFILE; goto failopenbtree; } } if (fflush(fk) != 0) { *lldberr = BTERR_KFILE; goto failopenbtree; } } /* Create BTREE structure */ btree = (BTREE) stdalloc(sizeof *btree); bbasedir(btree) = dir; bmaster(btree) = readindex(btree, kfile1.k_mkey, TRUE); if (!(bmaster(btree))) { stdfree(btree); *lldberr = BTERR_MASTER_INDEX; goto failopenbtree; } bwrite(btree) = !immut && writ && (kfile1.k_ostat == -1); bimmut(btree) = immut; /* includes case that ostat is -2 */ bkfp(btree) = fk; btree->b_kfile.k_mkey = kfile1.k_mkey; btree->b_kfile.k_fkey = kfile1.k_fkey; btree->b_kfile.k_ostat = kfile1.k_ostat; initcache(btree, 20); return btree; failopenbtree: if (fk) fclose(fk); return NULL; }
/*================================== * initbtree -- Initialize new BTREE *================================*/ static BOOLEAN initbtree (STRING basedir, INT *lldberr) { KEYFILE1 kfile1; KEYFILE2 kfile2; INDEX master=0; BLOCK block=0; FILE *fk=NULL, *fi=NULL, *fd=NULL; char scratch[200]; BOOLEAN result=FALSE; /* only set to good at end */ INT rtn=0; /* Open file for writing keyfile */ sprintf(scratch, "%s/key", basedir); if ((fk = fopen(scratch, LLWRITEBINARY)) == NULL) { *lldberr = BTERR_KFILE; goto initbtree_exit; } /* Open file for writing master index */ sprintf(scratch, "%s/aa/aa", basedir); if (!mkalldirs(scratch) || (fi = fopen(scratch, LLWRITEBINARY)) == NULL) { *lldberr = BTERR_INDEX; goto initbtree_exit; } /* Open file for writing first data block */ sprintf(scratch, "%s/ab/aa", basedir); if (!mkalldirs(scratch) || (fd = fopen(scratch, LLWRITEBINARY)) == NULL) { *lldberr = BTERR_BLOCK; goto initbtree_exit; } /* Write key file */ init_keyfile1(&kfile1); init_keyfile2(&kfile2); if (fwrite(&kfile1, sizeof(kfile1), 1, fk) != 1 || fwrite(&kfile2, sizeof(kfile2), 1, fk) != 1) { *lldberr = BTERR_KFILE; goto initbtree_exit; } if (fclose(fk) != 0) { fk = NULL; *lldberr = BTERR_KFILE; goto initbtree_exit; } fk=NULL; /* Write master index */ master = (INDEX) stdalloc(BUFLEN); ixtype(master) = BTINDEXTYPE; ixself(master) = path2fkey("aa/aa"); ixparent(master) = 0; master->ix_nkeys = 0; master->ix_fkeys[0] = path2fkey("ab/aa"); rtn = fwrite(master, BUFLEN, 1, fi); stdfree(master); master = 0; if (rtn != 1) { *lldberr = BTERR_INDEX; goto initbtree_exit; } if (fclose(fi) != 0) { fi = NULL; *lldberr = BTERR_INDEX; goto initbtree_exit; } fi=NULL; /* Write first data block */ block = (BLOCK) stdalloc(BUFLEN); ixtype(block) = BTBLOCKTYPE; ixself(block) = path2fkey("ab/aa"); ixparent(block) = 0; block->ix_nkeys = 0; rtn = fwrite(block, BUFLEN, 1, fd); stdfree(block); block = 0; if (rtn != 1) { *lldberr = BTERR_BLOCK; goto initbtree_exit; } if (fclose(fd) != 0) { fd = NULL; *lldberr = BTERR_BLOCK; goto initbtree_exit; } fd = NULL; /* we can finally say everything is ok */ result=TRUE; initbtree_exit: /* close any open files */ if (fd) fclose(fd); if (fi) fclose(fi); if (fk) fclose(fk); return result; }