[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[gd/samba/.git] / source / tdb / common / open.c
similarity index 93%
rename from source/lib/tdb/common/open.c
rename to source/tdb/common/open.c
index 84e67f1993c29ed828b20c4750ce9bc5843652e7..402352d3af208088627318d19cd3dc1ad61da7e0 100644 (file)
@@ -35,8 +35,8 @@ static struct tdb_context *tdbs = NULL;
 /* This is based on the hash algorithm from gdbm */
 static unsigned int default_tdb_hash(TDB_DATA *key)
 {
-       uint32_t value; /* Used to compute the hash value.  */
-       uint32_t i;     /* Used to cycle through random values. */
+       u32 value;      /* Used to compute the hash value.  */
+       u32   i;        /* Used to cycle through random values. */
 
        /* Set the initial value from the key size. */
        for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
@@ -50,7 +50,9 @@ static unsigned int default_tdb_hash(TDB_DATA *key)
 static int tdb_new_database(struct tdb_context *tdb, int hash_size)
 {
        struct tdb_header *newdb;
-       int size, ret = -1;
+       size_t size;
+       int ret = -1;
+       ssize_t written;
 
        /* We make it up in memory, then write it out if not internal */
        size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
@@ -79,10 +81,22 @@ static int tdb_new_database(struct tdb_context *tdb, int hash_size)
        memcpy(&tdb->header, newdb, sizeof(tdb->header));
        /* Don't endian-convert the magic food! */
        memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
-       if (write(tdb->fd, newdb, size) != size) {
-               ret = -1;
-       } else {
+       /* we still have "ret == -1" here */
+       written = write(tdb->fd, newdb, size);
+       if (written == size) {
                ret = 0;
+       } else if (written != -1) {
+               /* call write once again, this usually should return -1 and
+                * set errno appropriately */
+               size -= written;
+               written = write(tdb->fd, newdb+written, size);
+               if (written == size) {
+                       ret = 0;
+               } else if (written >= 0) {
+                       /* a second incomplete write - we give up.
+                        * guessing the errno... */
+                       errno = ENOSPC;
+               }
        }
 
   fail:
@@ -138,7 +152,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
        struct stat st;
        int rev = 0, locked = 0;
        unsigned char *vp;
-       uint32_t vertest;
+       u32 vertest;
 
        if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
                /* Can't log this */
@@ -165,10 +179,6 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
                tdb->page_size = 0x2000;
        }
 
-       if (open_flags & TDB_VOLATILE) {
-               tdb->max_dead_records = 5;
-       }
-
        if ((open_flags & O_ACCMODE) == O_WRONLY) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n",
                         name));
@@ -221,20 +231,23 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
                }
        }
 
+       errno = 0;
        if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
            || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
            || (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) {
-                       errno = EIO; /* ie bad format or something */
+                       if (errno == 0) {
+                               errno = EIO; /* ie bad format or something */
+                       }
                        goto fail;
                }
                rev = (tdb->flags & TDB_CONVERT);
        }
        vp = (unsigned char *)&tdb->header.version;
-       vertest = (((uint32_t)vp[0]) << 24) | (((uint32_t)vp[1]) << 16) |
-                 (((uint32_t)vp[2]) << 8) | (uint32_t)vp[3];
+       vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) |
+                 (((u32)vp[2]) << 8) | (u32)vp[3];
        tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
        if (!rev)
                tdb->flags &= ~TDB_CONVERT;