diff options
-rw-r--r-- | source3/tdb/tdb.c | 54 | ||||
-rw-r--r-- | source3/tdb/tdb.h | 14 |
2 files changed, 55 insertions, 13 deletions
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index 69e36ebd3e..85429d6546 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -1,4 +1,4 @@ -/* + /* Unix SMB/Netbios implementation. Version 3.0 Samba database functions @@ -149,7 +149,10 @@ struct list_struct { }; /* a byte range locking function - return 0 on success - this functions locks/unlocks 1 byte at the specified offset */ + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). */ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, int rw_type, int lck_type, int probe) { @@ -157,8 +160,10 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, if (tdb->flags & TDB_NOLOCK) return 0; - if (tdb->read_only) + if (tdb->read_only) { + errno = EACCES; return -1; + } fl.l_type = rw_type; fl.l_whence = SEEK_SET; @@ -171,6 +176,7 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, TDB_LOG((tdb, 5,"tdb_brlock failed at offset %d rw_type=%d lck_type=%d\n", offset, rw_type, lck_type)); } + /* errno set by fcntl */ return TDB_ERRCODE(TDB_ERR_LOCK, -1); } return 0; @@ -1369,10 +1375,18 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) database file. A flags value of O_WRONLY is invalid. The hash size is advisory, use zero for a default value. - return is NULL on error */ + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). */ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode) { + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL); +} + +TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn) +{ TDB_CONTEXT tdb, *ret, *i; struct stat st; int rev = 0, locked; @@ -1384,9 +1398,13 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, tdb.lockedkeys = NULL; tdb.flags = tdb_flags; tdb.open_flags = open_flags; + tdb.log_fn = log_fn; - if ((open_flags & O_ACCMODE) == O_WRONLY) + if ((open_flags & O_ACCMODE) == O_WRONLY) { + errno = EINVAL; goto fail; + } + if (hash_size == 0) hash_size = DEFAULT_HASH_SIZE; if ((open_flags & O_ACCMODE) == O_RDONLY) { @@ -1405,18 +1423,18 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, } if ((tdb.fd = open(name, open_flags, mode)) == -1) - goto fail; + goto fail; /* errno set by open(2) */ /* ensure there is only one process initialising at once */ if (tdb_brlock(&tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) - goto fail; + goto fail; /* errno set by tdb_brlock */ /* we need to zero database if we are the only one with it open */ if ((locked = (tdb_brlock(&tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0)) && (tdb_flags & TDB_CLEAR_IF_FIRST)) { open_flags |= O_CREAT; if (ftruncate(tdb.fd, 0) == -1) - goto fail; + goto fail; /* errno set by ftruncate */ } if (read(tdb.fd, &tdb.header, sizeof(tdb.header)) != sizeof(tdb.header) @@ -1424,8 +1442,10 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, || (tdb.header.version != TDB_VERSION && !(rev = (tdb.header.version==TDB_BYTEREV(TDB_VERSION))))) { /* its not a valid database - possibly initialise it */ - if (!(open_flags & O_CREAT) || tdb_new_database(&tdb, hash_size) == -1) + if (!(open_flags & O_CREAT) || tdb_new_database(&tdb, hash_size) == -1) { + errno = EIO; /* ie bad format or something */ goto fail; + } rev = (tdb.flags & TDB_CONVERT); } if (!rev) @@ -1448,14 +1468,18 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, /* map the database and fill in the return structure */ tdb.name = (char *)strdup(name); - if (!tdb.name) + if (!tdb.name) { + errno = ENOMEM; goto fail; + } tdb.map_size = st.st_size; tdb.device = st.st_dev; tdb.inode = st.st_ino; tdb.locked = calloc(tdb.header.hash_size+1, sizeof(tdb.locked[0])); - if (!tdb.locked) + if (!tdb.locked) { + errno = ENOMEM; goto fail; + } tdb_mmap(&tdb); if (locked) { if (!tdb.read_only) @@ -1468,8 +1492,10 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, goto fail; internal: - if (!(ret = malloc(sizeof(tdb)))) + if (!(ret = malloc(sizeof(tdb)))) { + errno = ENOMEM; goto fail; + } *ret = tdb; if (tdb_brlock(&tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) goto fail; @@ -1478,6 +1504,8 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, return ret; fail: + { int save_errno = errno; + if (tdb.map_ptr) { if (tdb.flags & TDB_INTERNAL) free(tdb.map_ptr); @@ -1490,7 +1518,9 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, close(tdb.fd); if (tdb.locked) free(tdb.locked); + errno = save_errno; return NULL; + } } /* close a database */ diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h index 4efe263ee8..e3eab41fd6 100644 --- a/source3/tdb/tdb.h +++ b/source3/tdb/tdb.h @@ -99,10 +99,17 @@ typedef struct tdb_context { } TDB_CONTEXT; typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode); -void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)); +TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn); + +int tdb_reopen(TDB_CONTEXT *tdb); +int tdb_reopen_all(void); +void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func); enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb); const char *tdb_errorstr(TDB_CONTEXT *tdb); TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); @@ -121,6 +128,11 @@ void tdb_unlockall(TDB_CONTEXT *tdb); /* Low level locking functions: use with care */ int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); void tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); + +/* Debug functions. Not used in production. */ +void tdb_dump_all(TDB_CONTEXT *tdb); +void tdb_printfreelist(TDB_CONTEXT *tdb); + extern TDB_DATA tdb_null; #ifdef __cplusplus } |