/*
- * $Id: enumerate.c,v 1.9.2.3 2002-02-07 23:56:04 srittau Exp $
+ * $Id: enumerate.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
/* add to cnid db */
cdir->d_did = cnid_add(vol->v_db, st, dir->d_did, upath,
upathlen, cdir->d_did);
+ /* Fail out if things go bad with CNID. */
+ if (cdir->d_did == CNID_INVALID) {
+ switch (errno) {
+ case CNID_ERR_PARAM:
+ syslog(LOG_ERR, "adddir: Incorrect parameters passed to cnid_add");
+ return NULL;
+ case CNID_ERR_PATH:
+ case CNID_ERR_DB:
+ case CNID_ERR_MAX:
+ return NULL;
+ }
+ }
#endif /* CNID_DB */
if (cdir->d_did == 0) {
/*
- * $Id: file.c,v 1.29.2.4 2002-02-07 23:56:33 srittau Exp $
+ * $Id: file.c,v 1.29.2.5 2002-02-09 20:29:02 jmarcus Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#ifdef CNID_DB
aint = cnid_add(vol->v_db, st, dir->d_did, upath,
strlen(upath), aint);
+ /* Throw errors if cnid_add fails. */
+ if (aint == CNID_INVALID) {
+ switch (errno) {
+ case CNID_ERR_PARAM:
+ syslog(LOG_ERR, "getfilparams: Incorrect parameters passed to cnid_add");
+ return(AFPERR_PARAM);
+ case CNID_ERR_PATH:
+ return(AFPERR_PARAM);
+ case CNID_ERR_DB:
+ case CNID_ERR_MAX:
+ return(AFPERR_MISC);
+ }
+ }
#endif /* CNID_DB */
if (aint == 0) {
}
#endif /* AD_VERSION > AD_VERSION1 */
- if (id = cnid_add(vol->v_db, &st, did, upath, len, id)) {
+ if (id = cnid_add(vol->v_db, &st, did, upath, len, id) != CNID_INVALID) {
memcpy(rbuf, &id, sizeof(id));
*rbuflen = sizeof(id);
return AFP_OK;
/*
- * $Id: fork.c,v 1.11.2.3 2002-02-07 23:56:58 srittau Exp $
+ * $Id: fork.c,v 1.11.2.4 2002-02-09 20:29:02 jmarcus Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
aint = cnid_add(ofork->of_vol->v_db, &st,
ofork->of_dir->d_did,
upath, strlen(upath), aint);
+ if (aint == CNID_INVALID) {
+ switch (errno) {
+ case CNID_ERR_PARAM:
+ syslog(LOG_ERR, "getforkparams: Incorrect parameters passed to cnid_add");
+ return(AFPERR_PARAM);
+ case CNID_ERR_PATH:
+ return(AFPERR_PARAM);
+ case CNID_ERR_DB:
+ case CNID_ERR_MAX:
+ return(AFPERR_MISC);
+ }
+ }
#endif /* CNID_DB */
if (aint == 0) {
#include <netatalk/endian.h>
+#define CNID_INVALID 0
+
+#define CNID_ERR_PARAM 0x80000001
+#define CNID_ERR_PATH 0x80000002
+#define CNID_ERR_DB 0x80000003
+#define CNID_ERR_MAX 0x80000004
+
typedef u_int32_t cnid_t;
/* cnid_open.c */
/*
- * $Id: cnid_add.c,v 1.14.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_add.c,v 1.14.2.4 2002-02-09 20:29:02 jmarcus Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
#include "cnid_private.h"
-#define MAX_ABORTS 255
-
/* add an entry to the CNID databases. we do this as a transaction
* to prevent messiness. */
-static int add_cnid(CNID_private *db, DB_TXN *ptid, DBT *key, DBT *data) {
+static int add_cnid(CNID_private *db, DBT *key, DBT *data) {
DBT altkey, altdata;
DB_TXN *tid;
- /* We create rc here because using errno is bad. Why? Well, if you
- * use errno once, then call another function which resets it, you're
- * screwed. */
- int rc, ret, aborts = 0;
+ int rc, ret;
memset(&altkey, 0, sizeof(altkey));
memset(&altdata, 0, sizeof(altdata));
- if (0) {
retry:
- if ((rc = txn_abort(tid)) != 0) {
- return rc;
- }
- if (++aborts > MAX_ABORTS) {
- return DB_LOCK_DEADLOCK;
- }
- }
-
- if ((rc = txn_begin(db->dbenv, ptid, &tid, 0)) != 0) {
+ if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) {
return rc;
}
/* main database */
if ((rc = db->db_cnid->put(db->db_cnid, tid, key, data, DB_NOOVERWRITE))) {
if (rc == DB_LOCK_DEADLOCK) {
+ if ((ret = txn_abort(tid)) != 0) {
+ return ret;
+ }
goto retry;
}
-
goto abort;
}
-
/* dev/ino database */
altkey.data = data->data;
altkey.size = CNID_DEVINO_LEN;
altdata.size = key->size;
if ((rc = db->db_devino->put(db->db_devino, tid, &altkey, &altdata, 0))) {
if (rc == DB_LOCK_DEADLOCK) {
+ if ((ret = txn_abort(tid)) != 0) {
+ return ret;
+ }
goto retry;
}
-
goto abort;
}
-
/* did/name database */
altkey.data = (char *) data->data + CNID_DEVINO_LEN;
altkey.size = data->size - CNID_DEVINO_LEN;
if ((rc = db->db_didname->put(db->db_didname, tid, &altkey, &altdata, 0))) {
if (rc == DB_LOCK_DEADLOCK) {
+ if ((ret = txn_abort(tid)) != 0) {
+ return ret;
+ }
goto retry;
}
-
goto abort;
}
if ((rc = txn_commit(tid, 0)) != 0) {
- syslog(LOG_ERR, "add_cnid: Failed to commit transaction: %s",
- db_strerror(rc));
+ syslog(LOG_ERR, "add_cnid: Failed to commit transaction: %s", db_strerror(rc));
return rc;
}
+
return 0;
abort:
return ret;
}
return rc;
-
}
cnid_t cnid_add(void *CNID, const struct stat *st,
int rc;
if (!(db = CNID) || !st || !name) {
- return 0;
+ errno = CNID_ERR_PARAM;
+ return CNID_INVALID;
}
/* Do a lookup. */
/* ... Return id if it is valid, or if Rootinfo is read-only. */
if (id || (db->flags & CNIDFLAG_DB_RO)) {
#ifdef DEBUG
- syslog(LOG_INFO, "cnid_add: Looked up did %u, name %s as %u",
- ntohl(did), name, ntohl(id));
+ syslog(LOG_INFO, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id));
#endif
return id;
}
if ((data.data = make_cnid_data(st, did, name, len)) == NULL) {
syslog(LOG_ERR, "cnid_add: Path name is too long");
- goto cleanup_err;
+ errno = CNID_ERR_PATH;
+ return CNID_INVALID;
}
data.size = CNID_HEADER_LEN + len + 1;
* cnid's to the database. */
if (ntohl(hint) >= CNID_START) {
/* If the key doesn't exist, add it in. Don't fiddle with nextID. */
- rc = add_cnid(db, NULL, &key, &data);
+ rc = add_cnid(db, &key, &data);
switch (rc) {
case DB_KEYEXIST: /* Need to use RootInfo after all. */
break;
default:
- syslog(LOG_ERR, "cnid_add: Unable to add CNID %u: %s",
- ntohl(hint), db_strerror(rc));
- goto cleanup_err;
+ syslog(LOG_ERR, "cnid_add: Unable to add CNID %u: %s", ntohl(hint), db_strerror(rc));
+ errno = CNID_ERR_DB;
+ return CNID_INVALID;
case 0:
#ifdef DEBUG
- syslog(LOG_INFO, "cnid_add: Used hint for did %u, name %s as %u",
- ntohl(did), name, ntohl(hint));
+ syslog(LOG_INFO, "cnid_add: Used hint for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
#endif
return hint;
}
}
- /* We need to create a random sleep interval to prevent deadlocks. */
- (void)srand(getpid() ^ time(NULL));
- t.tv_sec = 0;
-
memset(&rootinfo_key, 0, sizeof(rootinfo_key));
memset(&rootinfo_data, 0, sizeof(rootinfo_data));
rootinfo_key.data = ROOTINFO_KEY;
rootinfo_key.size = ROOTINFO_KEYLEN;
+retry:
+ if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) {
+ syslog(LOG_ERR, "cnid_add: Failed to begin transaction: %s", db_strerror(rc));
+ errno = CNID_ERR_DB;
+ return CNID_INVALID;
+ }
+
/* Get the key. */
-retry_get:
- switch (rc = db->db_didname->get(db->db_didname, NULL, &rootinfo_key,
- &rootinfo_data, 0)) {
+ switch (rc = db->db_didname->get(db->db_didname, tid, &rootinfo_key,
+ &rootinfo_data, DB_RMW)) {
case DB_LOCK_DEADLOCK:
if ((rc = txn_abort(tid)) != 0) {
syslog(LOG_ERR, "cnid_add: txn_abort: %s", db_strerror(rc));
- goto cleanup_err;
+ errno = CNID_ERR_DB;
+ return CNID_INVALID;
}
- goto retry_get;
+ goto retry;
case 0:
memcpy(&hint, rootinfo_data.data, sizeof(hint));
+ id = ntohl(hint);
+ /* If we've hit the max CNID allowed, we return a fatal error. CNID
+ * needs to be recycled before proceding. */
+ if (++id == CNID_INVALID) {
+ txn_abort(tid);
+ syslog(LOG_ERR, "cnid_add: FATAL: Cannot add CNID for %s. CNID database has reached its limit.", name);
+ errno = CNID_ERR_MAX;
+ return CNID_INVALID;
+ }
+ hint = htonl(id);
#ifdef DEBUG
syslog(LOG_INFO, "cnid_add: Found rootinfo for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
#endif
case DB_NOTFOUND:
hint = htonl(CNID_START);
#ifdef DEBUG
- syslog(LOG_INFO, "cnid_add: Using CNID_START for did %u, name %s",
- ntohl(did), name);
+ syslog(LOG_INFO, "cnid_add: Using CNID_START for did %u, name %s", ntohl(did), name);
#endif
break;
default:
- syslog(LOG_ERR, "cnid_add: Unable to lookup rootinfo: %s",
- db_strerror(rc));
- goto cleanup_err;
- }
-
-
- if (0) {
-retry:
- t.tv_usec = rand() % 1000000;
-#ifdef DEBUG
- syslog(LOG_INFO, "cnid_add: Hitting MAX_ABORTS, sleeping");
-#endif
- (void)select(0, NULL, NULL, NULL, &t);
- }
- if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) {
- syslog(LOG_ERR, "cnid_add: Failed to begin transaction: %s",
- db_strerror(rc));
- goto cleanup_err;
- }
-
- /* Search for a new id. We keep the first id around to check for
- * wrap-around. NOTE: I do it this way so that we can go back and
- * fill in holes. */
- save = id = ntohl(hint);
- while ((rc = add_cnid(db, tid, &key, &data)) != 0) {
- /* Don't use any special CNIDs. */
- if (++id < CNID_START) {
- id = CNID_START;
- }
- if (rc == DB_LOCK_DEADLOCK) {
- if ((rc = txn_abort(tid)) != 0) {
- syslog(LOG_ERR, "cnid_add: txn_abort: %s", db_strerror(rc));
- goto cleanup_err;
- }
- goto retry;
- }
-
- if ((rc != DB_KEYEXIST) || (save == id)) {
- syslog(LOG_ERR, "cnid_add: Unable to add CNID %u: %s",
- ntohl(hint), db_strerror(rc));
- goto cleanup_abort;
- }
- hint = htonl(id);
+ syslog(LOG_ERR, "cnid_add: Unable to lookup rootinfo: %s", db_strerror(rc));
+ goto cleanup_abort;
}
rootinfo_data.data = &hint;
case DB_LOCK_DEADLOCK:
if ((rc = txn_abort(tid)) != 0) {
syslog(LOG_ERR, "cnid_add: txn_abort: %s", db_strerror(rc));
- goto cleanup_err;
+ errno = CNID_ERR_DB;
+ return CNID_INVALID;
}
goto retry;
case 0:
+ /* The transaction finished, commit it. */
+ if ((rc = txn_commit(tid, 0)) != 0) {
+ syslog(LOG_ERR, "cnid_add: Unable to commit transaction: %s", db_strerror(rc));
+ errno = CNID_ERR_DB;
+ return CNID_INVALID;
+ }
break;
default:
- syslog(LOG_ERR, "cnid_add: Unable to update rootinfo: %s",
- db_strerror(rc));
+ syslog(LOG_ERR, "cnid_add: Unable to update rootinfo: %s", db_strerror(rc));
goto cleanup_abort;
}
-cleanup_commit:
- /* The transaction finished, commit it. */
- if ((rc = txn_commit(tid, 0)) != 0) {
- syslog(LOG_ERR, "cnid_add: Unable to commit transaction: %s",
- db_strerror(rc));
- goto cleanup_err;
+ /* Now we need to add the CNID data to the databases. */
+ rc = add_cnid(db, &key, &data);
+ if (rc) {
+ syslog(LOG_ERR, "cnid_add: Failed to add CNID for %s to database using hint %u: %s", name, ntohl(hint), db_strerror(rc));
+ errno = CNID_ERR_DB;
+ return CNID_INVALID;
}
#ifdef DEBUG
- syslog(LOG_INFO, "cnid_add: Returned CNID for did %u, name %s as %u",
- ntohl(did), name, ntohl(hint));
+ syslog(LOG_INFO, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
#endif
+
return hint;
cleanup_abort:
txn_abort(tid);
-cleanup_err:
- return 0;
+ errno = CNID_ERR_DB;
+ return CNID_INVALID;
}
#endif /* CNID_DB */
/*
- * $Id: cnid_close.c,v 1.12.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_close.c,v 1.12.2.4 2002-02-09 20:29:02 jmarcus Exp $
*/
#ifdef HAVE_CONFIG_H
char **list, **first;
int cfd = -1;
- if ((cfd = open(db->close_file, O_RDWR | O_CREAT, 0666)) > -1) {
- /* Checkpoint the databases until we can checkpoint no
- * more. */
+ /* Checkpoint the databases until we can checkpoint no
+ * more. */
+ rc = txn_checkpoint(db->dbenv, 0, 0, 0);
+ while (rc == DB_INCOMPLETE) {
rc = txn_checkpoint(db->dbenv, 0, 0, 0);
- while (rc == DB_INCOMPLETE) {
- rc = txn_checkpoint(db->dbenv, 0, 0, 0);
- }
+ }
#if DB_VERSION_MINOR > 2
- if ((rc = log_archive(db->dbenv, &list, DB_ARCH_LOG | DB_ARCH_ABS)) != 0) {
+ if ((rc = log_archive(db->dbenv, &list, DB_ARCH_ABS)) != 0) {
#else /* DB_VERSION_MINOR < 2 */
- if ((rc = log_archive(db->dbenv, &list, DB_ARCH_LOG | DB_ARCH_ABS, NULL)) != 0) {
+ if ((rc = log_archive(db->dbenv, &list, DB_ARCH_ABS, NULL)) != 0) {
#endif /* DB_VERSION_MINOR */
- syslog(LOG_ERR, "cnid_close: Unable to archive logfiles: %s",
- db_strerror(rc));
- }
+ syslog(LOG_ERR, "cnid_close: Unable to archive logfiles: %s", db_strerror(rc));
+ }
- if (list != NULL) {
- for (first = list; *list != NULL; ++list) {
- if ((rc = remove(*list)) != 0) {
+ if (list != NULL) {
+ for (first = list; *list != NULL; ++list) {
+ if ((rc = remove(*list)) != 0) {
#ifdef DEBUG
- syslog(LOG_INFO, "cnid_close: failed to remove %s: %s",
- *list, strerror(rc));
+ syslog(LOG_INFO, "cnid_close: failed to remove %s: %s", *list, strerror(rc));
#endif
- }
}
- free(first);
}
- (void)remove(db->close_file);
- close(cfd);
- }
- else {
- syslog(LOG_ERR, "cnid_close: Failed to open database closing lock file: %s", strerror(errno));
+ free(first);
}
}
+ (void)remove(db->lock_file);
}
db->db_didname->close(db->db_didname, 0);
/*
- * $Id: cnid_delete.c,v 1.9.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_delete.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
case DB_NOTFOUND:
#ifdef DEBUG
syslog(LOG_INFO, "cnid_delete: CNID %u not in database",
- ntohl(id));
+ ntohl(id));
#endif
return 0;
default:
syslog(LOG_ERR, "cnid_delete: Unable to delete entry: %s",
- db_strerror(rc));
+ db_strerror(rc));
return rc;
}
}
retry:
if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) {
syslog(LOG_ERR, "cnid_delete: Failed to begin transaction: %s",
- db_strerror(rc));
+ db_strerror(rc));
return rc;
}
case DB_LOCK_DEADLOCK:
if ((rc = txn_abort(tid)) != 0) {
syslog(LOG_ERR, "cnid_delete: txn_abort: %s",
- db_strerror(rc));
+ db_strerror(rc));
return rc;
}
goto retry;
default:
if ((rc = txn_abort(tid)) != 0) {
syslog(LOG_ERR, "cnid_delete: txn_abort: %s",
- db_strerror(rc));
+ db_strerror(rc));
return rc;
}
goto abort_err;
case DB_LOCK_DEADLOCK:
if ((rc = txn_abort(tid)) != 0) {
syslog(LOG_ERR, "cnid_delete: txn_abort: %s",
- db_strerror(rc));
+ db_strerror(rc));
return rc;
}
goto retry;
default:
if ((rc = txn_abort(tid)) != 0) {
syslog(LOG_ERR, "cnid_delete: txn_abort: %s",
- db_strerror(rc));
+ db_strerror(rc));
return rc;
}
goto abort_err;
#endif
if ((rc = txn_commit(tid, 0)) != 0) {
syslog(LOG_ERR, "cnid_delete: Failed to commit transaction: %s",
- db_strerror(rc));
+ db_strerror(rc));
return rc;
}
return 0;
abort_err:
syslog(LOG_ERR, "cnid_delete: Unable to delete CNID %u: %s",
- ntohl(id), db_strerror(rc));
+ ntohl(id), db_strerror(rc));
return rc;
}
#endif /*CNID_DB */
/*
- * $Id: cnid_get.c,v 1.9.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_get.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $
*/
#ifdef HAVE_CONFIG_H
if (rc != DB_NOTFOUND) {
syslog(LOG_ERR, "cnid_get: Unable to get CNID %u, name %s: %s",
- ntohl(did), name, db_strerror(rc));
+ ntohl(did), name, db_strerror(rc));
}
return 0;
memcpy(&id, data.data, sizeof(id));
#ifdef DEBUG
syslog(LOG_INFO, "cnid_get: Returning CNID for %u, name %s as %u",
- ntohl(did), name, ntohl(id));
+ ntohl(did), name, ntohl(id));
#endif
return id;
}
/*
- * $Id: cnid_lookup.c,v 1.9.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_lookup.c,v 1.9.2.4 2002-02-09 20:29:02 jmarcus Exp $
*/
#ifdef HAVE_CONFIG_H
break;
default:
syslog(LOG_ERR, "cnid_lookup: txn_checkpoint: %s",
- db_strerror(rc));
+ db_strerror(rc));
return 0;
}
}
}
syslog(LOG_ERR, "cnid_lookup: Unable to get CNID dev %u, ino %u: %s",
- st->st_dev, st->st_ino, db_strerror(rc));
+ st->st_dev, st->st_ino, db_strerror(rc));
return 0;
}
}
syslog(LOG_ERR, "cnid_lookup: Unable to get CNID %u, name %s: %s",
- ntohl(did), name, db_strerror(rc));
+ ntohl(did), name, db_strerror(rc));
return 0;
}
if ((devino && didname) || !(devino || didname)) {
#ifdef DEBUG
syslog(LOG_INFO, "cnid_lookup: Looked up did %u, name %s, as %u",
- ntohl(did), name, ntohl(id));
+ ntohl(did), name, ntohl(id));
#endif
return id;
}
/*
- * $Id: cnid_nextid.c,v 1.6.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_nextid.c,v 1.6.2.4 2002-02-09 20:29:02 jmarcus Exp $
*/
#ifdef unused
/*
- * $Id: cnid_open.c,v 1.19.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_open.c,v 1.19.2.4 2002-02-09 20:29:02 jmarcus Exp $
*
* Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT.
* 1 -- parent of root directory (handled by afpd)
* 2 -- root directory (handled by afpd)
*
- * so, CNID_START begins at 3.
+ * CNIDs 4-16 are reserved according to page 31 of the AFP 3.0 spec so,
+ * CNID_START begins at 17.
*/
#ifdef HAVE_CONFIG_H
#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \
DB_INIT_LOG | DB_INIT_TXN)
#else /* DB_VERSION_MINOR < 1 */
-#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \
-DB_INIT_LOG | DB_INIT_TXN | DB_TXN_NOSYNC)
/*#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \
-DB_INIT_LOG | DB_INIT_TXN)*/
+DB_INIT_LOG | DB_INIT_TXN | DB_TXN_NOSYNC)*/
+#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \
+DB_INIT_LOG | DB_INIT_TXN)
#endif /* DB_VERSION_MINOR */
-/* Let's try and use the random deadlock decider if available. This adds
- * a bit of entropy to the mix that might be beneficial. If random isn't
- * available, we'll decide deadlocks by kicking off the youngest process.
+/* Let's try and use the youngest lock detector if present.
* If we can't do that, then let DB3 use its default deadlock detector. */
-#ifdef DB_LOCK_RANDOM
-#define DEAD_LOCK_DETECT DB_LOCK_RANDOM
-#elif defined DB_LOCK_YOUNGEST
+#if defined DB_LOCK_YOUNGEST
#define DEAD_LOCK_DETECT DB_LOCK_YOUNGEST
-#else /* DB_LOCK_RANDOM */
+#else /* DB_LOCK_YOUNGEST */
#define DEAD_LOCK_DETECT DB_LOCK_DEFAULT
-#endif /* DB_LOCK_RANDOM */
+#endif /* DB_LOCK_YOUNGEST */
#define MAXITER 0xFFFF /* maximum number of simultaneously open CNID
* databases. */
#endif /* DB_VERSION_MINOR */
}
-static int have_lock = 0;
-
void *cnid_open(const char *dir) {
- struct stat st, rsb, csb;
+ struct stat st, rsb, lsb, csb;
struct flock lock;
char path[MAXPATHLEN + 1];
- char recover_file[MAXPATHLEN + 1];
CNID_private *db;
DBT key, data;
DB_TXN *tid;
- u_int32_t DBEXTRAS = 0;
int open_flag, len;
- int rc, rfd = -1;
+ int rc;
if (!dir) {
return NULL;
strcat(path, "/");
len++;
- strcpy(db->close_file, path);
- strcat(db->close_file, DBCLOSEFILE);
-
- /* Check to make sure that a client isn't in the process of closing
- * the database environment. To do this, select on the close file. */
- while(stat(db->close_file, &csb) == 0) {
- struct timeval ct;
- ct.tv_sec = 1;
- ct.tv_usec = 0;
- (void)select(0, NULL, NULL, NULL, &ct);
- }
-
- strcpy(recover_file, path);
- strcat(recover_file, DBRECOVERFILE);
-
/* Search for a byte lock. This allows us to cleanup the log files
* at cnid_close() in a clean fashion.
*
* NOTE: This won't work if multiple volumes for the same user refer
* to the sahe directory. */
strcat(path, DBLOCKFILE);
+ strcpy(db->lock_file, path);
if ((db->lockfd = open(path, O_RDWR | O_CREAT, 0666)) > -1) {
lock.l_start = 0;
lock.l_len = 1;
syslog(LOG_ERR, "cnid_open: Cannot establish logfile cleanup lock for database environment %s (open() failed)", path);
}
- /* Create a file to represent database recovery. While this file
- * exists, the database is being recovered, and all other clients will
- * select until recovery is complete, and this file goes away. */
- if (!have_lock && db->lockfd > -1 && lock.l_start == 0) {
- if (stat(recover_file, &rsb) == 0) {
- (void)remove(recover_file);
- }
- if ((rfd = open(recover_file, O_RDWR | O_CREAT, 0666)) > -1) {
- DBEXTRAS |= DB_RECOVER;
- have_lock = 1;
- }
- }
- else if (!have_lock) {
- while (stat(recover_file, &rsb) == 0) {
- struct timeval rt;
- rt.tv_sec = 1;
- rt.tv_usec = 0;
- (void)select(0, NULL, NULL, NULL, &rt);
- }
- }
-
path[len + DBHOMELEN] = '\0';
open_flag = DB_CREATE;
}
#if DB_VERSION_MINOR > 1
+#if 0
/* Take care of setting the DB_TXN_NOSYNC flag in db3 > 3.1.x. */
if ((rc = db->dbenv->set_flags(db->dbenv, DB_TXN_NOSYNC, 1)) != 0) {
syslog(LOG_ERR, "cnid_open: set_flags: %s", db_strerror(rc));
goto fail_lock;
}
+#endif
#endif /* DB_VERSION_MINOR > 1 */
/* Open the database environment. */
- if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS | DBEXTRAS, 0666)) != 0) {
+ if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666)) != 0) {
if (rc == DB_RUNRECOVERY) {
/* This is the mother of all errors. We _must_ fail here. */
syslog(LOG_ERR, "cnid_open: CATASTROPHIC ERROR opening database environment %s. Run db_recovery -c immediately", path);
* open the environment with no flags. */
if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666)) != 0) {
syslog(LOG_ERR, "cnid_open: dbenv->open of %s failed: %s",
- path, db_strerror(rc));
+ path, db_strerror(rc));
goto fail_lock;
}
}
syslog(LOG_INFO, "cnid_open: Obtained read-only database environment %s", path);
}
- /* If we have the recovery lock, close the file, remove it, so other
- * clients can proceed opening the DB environment. */
- if (rfd > -1) {
- (void)remove(recover_file);
- switch(errno) {
- case 0:
- case ENOENT:
- break;
- default:
- syslog(LOG_ERR, "cnid_open: Unable to remove %s: %s",
- recover_file, strerror(errno));
- }
- close(rfd);
- rfd = -1;
- }
-
/* did/name reverse mapping. We use a BTree for this one. */
if ((rc = db_create(&db->db_didname, db->dbenv, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to create did/name database: %s",
- db_strerror(rc));
+ db_strerror(rc));
goto fail_appinit;
}
- db->db_didname->set_bt_compare(db->db_didname, &compare_unix);
+ /*db->db_didname->set_bt_compare(db->db_didname, &compare_unix);*/
if ((rc = db->db_didname->open(db->db_didname, DBDIDNAME, NULL,
- DB_BTREE, open_flag, 0666))) {
+ DB_HASH, open_flag, 0666))) {
syslog(LOG_ERR, "cnid_open: Failed to open did/name database: %s",
- db_strerror(rc));
+ db_strerror(rc));
goto fail_appinit;
}
dbversion_retry:
if ((rc = txn_begin(db->dbenv, NULL, &tid, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: txn_begin: failed to check db version: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
goto fail_appinit;
}
if (ret == DB_LOCK_DEADLOCK) {
if ((ret = txn_abort(tid)) != 0) {
syslog(LOG_ERR, "cnid_open: txn_abort: %s",
- db_strerror(ret));
+ db_strerror(ret));
db->db_didname->close(db->db_didname, 0);
goto fail_appinit;
}
* successfully or not. */
txn_abort(tid);
syslog(LOG_ERR, "cnid_open: Error putting new version: %s",
- db_strerror(ret));
+ db_strerror(ret));
db->db_didname->close(db->db_didname, 0);
goto fail_appinit;
}
default:
txn_abort(tid);
syslog(LOG_ERR, "cnid_open: Failed to check db version: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
goto fail_appinit;
}
if ((rc = txn_commit(tid, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to commit db version: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
goto fail_appinit;
}
/* did/macname (31 character) mapping. Use a BTree for this one. */
if ((rc = db_create(&db->db_macname, db->dbenv, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to create did/macname database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
goto fail_appinit;
}
db->db_macname->set_bt_compare(db->db_macname, &compare_mac);
if ((rc = db->db_macname->open(db->db_macname, DBMACNAME, NULL, DB_BTREE, open_flag, 0666)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to open did/macname database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
goto fail_appinit;
}
/* did/shortname (DOS 8.3) mapping. Use a BTree for this one. */
if ((rc = db_create(&db->db_shortname, db->dbenv, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to create did/shortname database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
db->db_macname->close(db->db_macname, 0);
goto fail_appinit;
db->db_shortname->set_bt_compare(db->db_shortname, &compare_mac);
if ((rc = db->db_shortname->open(db->db_shortname, DBSHORTNAME, NULL, DB_BTREE, open_flag, 0666)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to open did/shortname database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
db->db_macname->close(db->db_macname, 0);
goto fail_appinit;
/* did/longname (Unicode) mapping. Use a BTree for this one. */
if ((rc = db_create(&db->db_longname, db->dbenv, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to create did/longname database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
db->db_macname->close(db->db_macname, 0);
db->db_shortname->close(db->db_shortname, 0);
db->db_longname->set_bt_compare(db->db_longname, &compare_unicode);
if ((rc = db->db_longname->open(db->db_longname, DBLONGNAME, NULL, DB_BTREE, open_flag, 0666)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to open did/longname database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
db->db_macname->close(db->db_macname, 0);
db->db_shortname->close(db->db_shortname, 0);
/* dev/ino reverse mapping. Use a hash for this one. */
if ((rc = db_create(&db->db_devino, db->dbenv, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to create dev/ino database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
#ifdef EXTENDED_DB
db->db_macname->close(db->db_macname, 0);
if ((rc = db->db_devino->open(db->db_devino, DBDEVINO, NULL, DB_HASH, open_flag, 0666)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to open devino database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
#ifdef EXTENDED_DB
db->db_macname->close(db->db_macname, 0);
/* Main CNID database. Use a hash for this one. */
if ((rc = db_create(&db->db_cnid, db->dbenv, 0)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to create cnid database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
#ifdef EXTENDED_DB
db->db_macname->close(db->db_macname, 0);
if ((rc = db->db_cnid->open(db->db_cnid, DBCNID, NULL, DB_HASH, open_flag, 0666)) != 0) {
syslog(LOG_ERR, "cnid_open: Failed to open dev/ino database: %s",
- db_strerror(rc));
+ db_strerror(rc));
db->db_didname->close(db->db_didname, 0);
#ifdef EXTENDED_DB
db->db_macname->close(db->db_macname, 0);
goto fail_appinit;
}
+ /* Print out the version of DB3 we're linked against. */
+ syslog(LOG_INFO, "CNID DB initialized using %s",
+ db_version(NULL, NULL, NULL));
+
return db;
fail_appinit:
fail_lock:
if (db->lockfd > -1) {
close(db->lockfd);
- }
- if (rfd > -1) {
- (void)remove(recover_file);
- close(rfd);
+ (void)remove(db->lock_file);
}
fail_adouble:
/*
- * $Id: cnid_private.h,v 1.3.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_private.h,v 1.3.2.4 2002-02-09 20:29:02 jmarcus Exp $
*/
#ifndef LIBATALK_CNID_PRIVATE_H
#define CNID_DID_LEN 4
#define CNID_HEADER_LEN (CNID_DEVINO_LEN + CNID_DID_LEN)
-#define CNID_START 3
+#define CNID_START 17
#define CNIDFLAG_ROOTINFO_RO (1 << 0)
#define CNIDFLAG_DB_RO (1 << 1)
#endif /* EXTENDED_DB */
DB_ENV* dbenv;
int lockfd, flags;
- char close_file[MAXPATHLEN + 1];
+ char lock_file[MAXPATHLEN + 1];
} CNID_private;
/* on-disk data format (in network byte order where appropriate) --
/*
- * $Id: cnid_resolve.c,v 1.8.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_resolve.c,v 1.8.2.4 2002-02-09 20:29:02 jmarcus Exp $
*/
#ifdef HAVE_CONFIG_H
if (rc != DB_NOTFOUND) {
syslog(LOG_ERR, "cnid_resolve: Unable to get did/name: %s",
- db_strerror(rc));
+ db_strerror(rc));
}
*id = 0;
memcpy(id, (char *)data.data + CNID_DEVINO_LEN, sizeof(cnid_t));
#ifdef DEBUG
syslog(LOG_INFO, "cnid_resolve: Returning id = %u, did/name = %s",
- ntohl(*id), (char *)data.data + CNID_HEADER_LEN);
+ ntohl(*id), (char *)data.data + CNID_HEADER_LEN);
#endif
return (char *)data.data + CNID_HEADER_LEN;
}
/*
- * $Id: cnid_update.c,v 1.12.2.3 2001-12-15 06:35:28 jmarcus Exp $
+ * $Id: cnid_update.c,v 1.12.2.4 2002-02-09 20:29:02 jmarcus Exp $
*/
#ifdef HAVE_CONFIG_H
retry:
if ((rc = txn_begin(db->dbenv, NULL, &tid, 0))) {
- syslog(LOG_ERR, "cnid_update: Failed to begin transaction: %s",
- db_strerror(rc));
+ syslog(LOG_ERR, "cnid_update: Failed to begin transaction: %s", db_strerror(rc));
return rc;
}
update_err:
syslog(LOG_ERR, "cnid_update: Unable to update CNID %u: %s",
- ntohl(id), db_strerror(rc));
+ ntohl(id), db_strerror(rc));
return -1;
}
#endif /* CNID_DB */
-dnl $Id: db3-check.m4,v 1.6 2001-11-16 21:51:05 jnewman Exp $
+dnl $Id: db3-check.m4,v 1.6.2.1 2002-02-09 20:29:02 jmarcus Exp $
dnl Autoconf macro to check for the Berkeley DB3 library
AC_DEFUN([AC_PATH_DB3], [
db3found=yes
DB3_CFLAGS="-I$db3dir"
DB3_LIBS="-L$db3libdir -ldb"
+ DB3_PATH="`echo $db3dir | sed 's,include/db3$,,'`"
])
CFLAGS="$savedcflags"
LDFLAGS="$savedldflags"
AC_SUBST(DB3_CFLAGS)
AC_SUBST(DB3_LIBS)
+ AC_SUBST(DB3_PATH)
])