summaryrefslogtreecommitdiff
path: root/source3/tdb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/tdb')
-rw-r--r--source3/tdb/README9
-rw-r--r--source3/tdb/tdb.c39
-rw-r--r--source3/tdb/tdb.h1
3 files changed, 44 insertions, 5 deletions
diff --git a/source3/tdb/README b/source3/tdb/README
index fc99a68acc..3c0059c5cb 100644
--- a/source3/tdb/README
+++ b/source3/tdb/README
@@ -11,7 +11,7 @@ Compilation
-----------
add HAVE_MMAP=1 to use mmap instead of read/write
-add TDB_DEBUG for verbose debug info
+add TDB_DEBUG=1 for verbose debug info
add NOLOCK=1 to disable locking code
Testing
@@ -21,6 +21,12 @@ Compile tdbtest.c and link with gdbm for testing. tdbtest will perform
identical operations via tdb and gdbm then make sure the result is the
same
+Also included is tdbtool, which allows simple database manipulation
+on the commandline.
+
+tdbtest and tdbtool are not built as part of Samba, but are included
+for completeness.
+
Interface
---------
@@ -31,3 +37,4 @@ The interface is very similar to gdbm except for the following:
- no tdbm_reorganise() function
- no tdbm_sync() function. No operations are cached in the library anyway
- added a tdb_traverse() function for traversing the whole database
+
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c
index dacecf9572..01d2e740f7 100644
--- a/source3/tdb/tdb.c
+++ b/source3/tdb/tdb.c
@@ -102,10 +102,39 @@ static tdb_off tdb_hash_top(TDB_CONTEXT *tdb, unsigned hash)
return ret;
}
+
+/* check for an out of bounds access - if it is out of bounds then
+ see if the database has been expanded by someone else and expand
+ if necessary */
+static int tdb_oob(TDB_CONTEXT *tdb, tdb_off offset)
+{
+ struct stat st;
+ if (offset < tdb->map_size) return 0;
+
+ fstat(tdb->fd, &st);
+ if (st.st_size <= tdb->map_size) return -1;
+
+#if HAVE_MMAP
+ if (tdb->map_ptr) {
+ munmap(tdb->map_ptr, tdb->map_size);
+ tdb->map_ptr = NULL;
+ }
+#endif
+
+ tdb->map_size = st.st_size;
+#if HAVE_MMAP
+ tdb->map_ptr = (void *)mmap(NULL, tdb->map_size,
+ tdb->read_only?PROT_READ:PROT_READ|PROT_WRITE,
+ MAP_SHARED | MAP_FILE, tdb->fd, 0);
+#endif
+ return 0;
+}
+
+
/* write a lump of data at a specified offset */
static int tdb_write(TDB_CONTEXT *tdb, tdb_off offset, char *buf, tdb_len len)
{
- if (offset + len > tdb->map_size) {
+ if (tdb_oob(tdb, offset + len) != 0) {
/* oops - trying to write beyond the end of the database! */
#if TDB_DEBUG
printf("write error of length %u at offset %u (max %u)\n",
@@ -128,7 +157,7 @@ static int tdb_write(TDB_CONTEXT *tdb, tdb_off offset, char *buf, tdb_len len)
/* read a lump of data at a specified offset */
static int tdb_read(TDB_CONTEXT *tdb, tdb_off offset, char *buf, tdb_len len)
{
- if (offset + len > tdb->map_size) {
+ if (tdb_oob(tdb, offset + len) != 0) {
/* oops - trying to read beyond the end of the database! */
#if TDB_DEBUG
printf("read error of length %u at offset %u (max %u)\n",
@@ -514,6 +543,7 @@ int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
/* traverse the entire database - calling fn(tdb, key, data) on each element.
return -1 on error or the record count traversed
+ if fn is NULL then it is not called
a non-zero return value from fn() indicates that the traversal should stop
*/
int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf))
@@ -552,7 +582,7 @@ int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB
dbuf.dsize = rec.data_len;
count++;
- if (fn(tdb, key, dbuf) != 0) {
+ if (fn && fn(tdb, key, dbuf) != 0) {
/* they want us to stop traversing */
free(data);
return count;
@@ -915,9 +945,10 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode)
/* map the database and fill in the return structure */
tdb.name = (char *)strdup(name);
tdb.map_size = st.st_size;
+ tdb.read_only = ((flags & O_ACCMODE) == O_RDONLY);
#if HAVE_MMAP
tdb.map_ptr = (void *)mmap(NULL, st.st_size,
- (flags & O_ACCMODE) == O_RDONLY? PROT_READ : PROT_READ|PROT_WRITE,
+ tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED | MAP_FILE, tdb.fd, 0);
#endif
tdb.header = header;
diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h
index 316338606b..111b804f71 100644
--- a/source3/tdb/tdb.h
+++ b/source3/tdb/tdb.h
@@ -39,6 +39,7 @@ typedef struct {
void *map_ptr; /* where it is currently mapped */
int fd; /* open file descriptor for the database */
tdb_len map_size; /* how much space has been mapped */
+ int read_only; /* opened read-only */
int write_locked; /* set if we have the db locked */
struct tdb_header header; /* a cached copy of the header */
} TDB_CONTEXT;