예제 #1
0
/*====================================================
 * 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];
}
예제 #2
0
파일: hashtab.c 프로젝트: MarcNo/lifelines
/*================================
 * 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;
}
예제 #3
0
/*=========================================================
 * 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;
}
예제 #4
0
/*=============================================+
 * 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;
}
예제 #5
0
/*=============================================+
 * 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;
}
예제 #6
0
/*========================================
 * 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;
}
예제 #7
0
파일: stralloc.c 프로젝트: MarcNo/lifelines
/*===============================
 * 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);
}
예제 #8
0
파일: stralloc.c 프로젝트: MarcNo/lifelines
/*==============================
 * 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;
}
예제 #9
0
파일: hashtab.c 프로젝트: MarcNo/lifelines
/*================================
 * 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;
}
예제 #10
0
파일: dbverify.c 프로젝트: MarcNo/lifelines
/*===============================================
 * 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;
}
예제 #11
0
파일: pedigree.c 프로젝트: MarcNo/lifelines
/*=================================================
 * 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;
}
예제 #12
0
파일: nodeio.c 프로젝트: MarcNo/lifelines
/*=========================================
 * 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;
}
예제 #13
0
/*====================================================
 * 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;
}
예제 #14
0
파일: table.c 프로젝트: MarcNo/lifelines
/*======================================
 * 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);
}
예제 #15
0
파일: table.c 프로젝트: MarcNo/lifelines
/*=================================================
 * 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;
}
예제 #16
0
파일: proptbls.c 프로젝트: MarcNo/lifelines
/*===================================================
 * 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;
}
예제 #17
0
파일: hashtab.c 프로젝트: MarcNo/lifelines
/*================================
 * 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;
}
예제 #18
0
/*=============================================
 * 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;
}
예제 #19
0
파일: pedigree.c 프로젝트: MarcNo/lifelines
/*=================================================
 * 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;
		}
	}
}
예제 #20
0
파일: stralloc.c 프로젝트: MarcNo/lifelines
/*==================================
 * 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;
}
예제 #21
0
파일: generic.c 프로젝트: MarcNo/lifelines
/*=================================================
 * 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;
}
예제 #22
0
파일: table.c 프로젝트: MarcNo/lifelines
/*=============================
 * 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;
}
예제 #23
0
/*====================================================
 * 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;
}
예제 #24
0
/*=========================================================
 * 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;
}
예제 #25
0
파일: xreffile.c 프로젝트: MarcNo/lifelines
/*==========================================
 * 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;
}
예제 #26
0
/*=========================================
 * 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;
}
예제 #27
0
파일: rassa.c 프로젝트: MarcNo/lifelines
/*========================================+
 * 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;
}
예제 #28
0
파일: place.c 프로젝트: MarcNo/lifelines
/*=============================================
 * 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;
}
예제 #29
0
파일: opnbtree.c 프로젝트: MarcNo/lifelines
/*============================================
 * 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;
}
예제 #30
0
파일: opnbtree.c 프로젝트: MarcNo/lifelines
/*==================================
 * 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;
}