source3/lib/tdb_validate: convert to dbwrap, rename to db_validate.
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 21 Jun 2012 13:16:58 +0000 (22:46 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 21 Jun 2012 13:16:58 +0000 (22:46 +0930)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
source3/Makefile.in
source3/lib/db_validate.c [moved from source3/lib/tdb_validate.c with 52% similarity]
source3/lib/db_validate.h [moved from source3/lib/tdb_validate.h with 59% similarity]
source3/wscript_build

index f4b00a7ff035617e0f8dc5c6d539e104ab9b8781..0af1004ef2df1bfe3f5a162df7e77b091f26d88b 100644 (file)
@@ -272,7 +272,7 @@ TDB_LIB_OBJ = lib/util_tdb.o ../lib/util/util_tdb.o \
          ../lib/dbwrap/dbwrap_rbt.o \
          ../lib/dbwrap/dbwrap_util.o
 
-TDB_VALIDATE_OBJ = lib/tdb_validate.o
+DB_VALIDATE_OBJ = lib/db_validate.o
 
 SMBLDAP_OBJ = @SMBLDAP@
 
@@ -1513,7 +1513,7 @@ WINBINDD_OBJ = \
                $(NPA_TSTREAM_OBJ) \
                $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \
                $(LIBADS_SERVER_OBJ) \
-               $(TDB_VALIDATE_OBJ) \
+               $(DB_VALIDATE_OBJ) \
                $(LIBCLI_DSSETUP_OBJ) \
                $(LIBCLI_LSA_OBJ) \
                $(LIBCLI_SAMR_OBJ) \
similarity index 52%
rename from source3/lib/tdb_validate.c
rename to source3/lib/db_validate.c
index 2592402afd8b7b3e13eaabe41f661c2733c99f6c..6b9640d186ef5277cbbf0098616724a0fc4a1581 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Unix SMB/CIFS implementation.
  *
- * A general tdb content validation mechanism
+ * A general (n)tdb content validation mechanism
  *
  * Copyright (C) Michael Adam      2007
  *
 #include "includes.h"
 #include "system/filesys.h"
 #include "util_tdb.h"
-#include "tdb_validate.h"
+#include "db_validate.h"
+#include "dbwrap/dbwrap.h"
+#include "dbwrap/dbwrap_open.h"
+#include <ccan/str/str.h>
 
 /*
  * internal validation function, executed by the child.
  */
-static int tdb_validate_child(struct tdb_context *tdb,
-                             tdb_validate_data_func validate_fn)
+static int db_validate_child(struct db_context *db,
+                            db_validate_data_func validate_fn)
 {
        int ret = 1;
-       int num_entries = 0;
-       struct tdb_validation_status v_status;
+       int num_entries;
+       struct db_validation_status v_status;
 
-       v_status.tdb_error = False;
-       v_status.bad_freelist = False;
+       v_status.db_error = False;
        v_status.bad_entry = False;
        v_status.unknown_key = False;
        v_status.success = True;
 
-       if (!tdb) {
-               v_status.tdb_error = True;
+       if (!db) {
+               v_status.db_error = True;
                v_status.success = False;
                goto out;
        }
 
-       /*
-        * we can simplify this by passing a check function,
-        * but I don't want to change all the callers...
-        */
-       ret = tdb_check(tdb, NULL, NULL);
+       ret = dbwrap_check(db);
        if (ret != 0) {
-               v_status.tdb_error = True;
+               v_status.db_error = True;
                v_status.success = False;
                goto out;
        }
 
-       /* Check if the tdb's freelist is good. */
-       if (tdb_validate_freelist(tdb, &num_entries) == -1) {
-               v_status.bad_freelist = True;
+       /* Now traverse the db to validate it. */
+       if (!NT_STATUS_IS_OK(dbwrap_traverse(db, validate_fn,
+                                            (void *)&v_status,
+                                            &num_entries))) {
+               v_status.db_error = True;
                v_status.success = False;
                goto out;
        }
 
-       DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n",
-                 tdb_name(tdb), num_entries));
-
-       /* Now traverse the tdb to validate it. */
-       num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status);
        if (!v_status.success) {
                goto out;
-       } else if (num_entries < 0) {
-               v_status.tdb_error = True;
-               v_status.success = False;
-               goto out;
        }
 
-       DEBUG(10,("tdb_validate_child: tdb %s is good with %d entries\n",
-                 tdb_name(tdb), num_entries));
+       DEBUG(10,("db_validate_child: db %s is good with %d entries\n",
+                 dbwrap_name(db), num_entries));
        ret = 0; /* Cache is good. */
 
 out:
-       DEBUG(10,   ("tdb_validate_child: summary of validation status:\n"));
-       DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no"));
-       DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no"));
+       DEBUG(10,   ("db_validate_child: summary of validation status:\n"));
+       DEBUGADD(10,(" * db error: %s\n", v_status.db_error ? "yes" : "no"));
        DEBUGADD(10,(" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no"));
        DEBUGADD(10,(" * unknown key: %s\n", v_status.unknown_key?"yes":"no"));
        DEBUGADD(10,(" => overall success: %s\n", v_status.success?"yes":"no"));
@@ -93,73 +83,73 @@ out:
 }
 
 /*
- * tdb validation function.
- * returns 0 if tdb is ok, != 0 if it isn't.
- * this function expects an opened tdb.
+ * (n)tdb validation function.
+ * returns 0 if db is ok, != 0 if it isn't.
+ * this function expects an opened db.
  */
-int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn)
+int db_validate(struct db_context *db, db_validate_data_func validate_fn)
 {
        pid_t child_pid = -1;
        int child_status = 0;
        int wait_pid = 0;
        int ret = 1;
 
-       if (tdb == NULL) {
-               DEBUG(1, ("Error: tdb_validate called with tdb == NULL\n"));
+       if (db == NULL) {
+               DEBUG(1, ("Error: db_validate called with db == NULL\n"));
                return ret;
        }
 
-       DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_name(tdb)));
+       DEBUG(5, ("db_validate called for db '%s'\n", dbwrap_name(db)));
 
        /* fork and let the child do the validation.
         * benefit: no need to twist signal handlers and panic functions.
         * just let the child panic. we catch the signal. */
 
-       DEBUG(10, ("tdb_validate: forking to let child do validation.\n"));
+       DEBUG(10, ("db_validate: forking to let child do validation.\n"));
        child_pid = fork();
        if (child_pid == 0) {
                /* child code */
-               DEBUG(10, ("tdb_validate (validation child): created\n"));
-               DEBUG(10, ("tdb_validate (validation child): "
-                          "calling tdb_validate_child\n"));
-               exit(tdb_validate_child(tdb, validate_fn));
+               DEBUG(10, ("db_validate (validation child): created\n"));
+               DEBUG(10, ("db_validate (validation child): "
+                          "calling db_validate_child\n"));
+               exit(db_validate_child(db, validate_fn));
        }
        else if (child_pid < 0) {
-               DEBUG(1, ("tdb_validate: fork for validation failed.\n"));
+               DEBUG(1, ("db_validate: fork for validation failed.\n"));
                goto done;
        }
 
        /* parent */
 
-       DEBUG(10, ("tdb_validate: fork succeeded, child PID = %u\n",
+       DEBUG(10, ("db_validate: fork succeeded, child PID = %u\n",
                (unsigned int)child_pid));
 
-       DEBUG(10, ("tdb_validate: waiting for child to finish...\n"));
+       DEBUG(10, ("db_validate: waiting for child to finish...\n"));
        while  ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) {
                if (errno == EINTR) {
-                       DEBUG(10, ("tdb_validate: got signal during waitpid, "
+                       DEBUG(10, ("db_validate: got signal during waitpid, "
                                   "retrying\n"));
                        errno = 0;
                        continue;
                }
-               DEBUG(1, ("tdb_validate: waitpid failed with error '%s'.\n",
+               DEBUG(1, ("db_validate: waitpid failed with error '%s'.\n",
                          strerror(errno)));
                goto done;
        }
        if (wait_pid != child_pid) {
-               DEBUG(1, ("tdb_validate: waitpid returned pid %d, "
+               DEBUG(1, ("db_validate: waitpid returned pid %d, "
                          "but %u was expected\n", wait_pid, (unsigned int)child_pid));
                goto done;
        }
 
-       DEBUG(10, ("tdb_validate: validating child returned.\n"));
+       DEBUG(10, ("db_validate: validating child returned.\n"));
        if (WIFEXITED(child_status)) {
-               DEBUG(10, ("tdb_validate: child exited, code %d.\n",
+               DEBUG(10, ("db_validate: child exited, code %d.\n",
                           WEXITSTATUS(child_status)));
                ret = WEXITSTATUS(child_status);
        }
        if (WIFSIGNALED(child_status)) {
-               DEBUG(10, ("tdb_validate: child terminated by signal %d\n",
+               DEBUG(10, ("db_validate: child terminated by signal %d\n",
                           WTERMSIG(child_status)));
 #ifdef WCOREDUMP
                if (WCOREDUMP(child_status)) {
@@ -169,95 +159,118 @@ int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn)
                ret = WTERMSIG(child_status);
        }
        if (WIFSTOPPED(child_status)) {
-               DEBUG(10, ("tdb_validate: child was stopped by signal %d\n",
+               DEBUG(10, ("db_validate: child was stopped by signal %d\n",
                           WSTOPSIG(child_status)));
                ret = WSTOPSIG(child_status);
        }
 
 done:
-       DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret,
-                 tdb_name(tdb)));
+       DEBUG(5, ("db_validate returning code '%d' for db '%s'\n", ret,
+                 dbwrap_name(db)));
 
        return ret;
 }
 
 /*
- * tdb validation function.
- * returns 0 if tdb is ok, != 0 if it isn't.
+ * db validation function.
+ * returns the (talloced) true path of db if ok, NULL if it isn't.
  * this is a wrapper around the actual validation function that opens and closes
- * the tdb.
+ * the (n)tdb.
  */
-int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn)
+char *db_validate_open(TALLOC_CTX *ctx,
+                      const char *tdb_path,
+                      db_validate_data_func validate_fn)
 {
-       TDB_CONTEXT *tdb = NULL;
-       int ret = 1;
+       struct db_context *db = NULL;
+       char *name;
 
-       DEBUG(5, ("tdb_validate_open called for tdb '%s'\n", tdb_path));
+       DEBUG(5, ("db_validate_open called for tdb '%s'\n", tdb_path));
 
-       tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDWR, 0);
-       if (!tdb) {
+       db = db_s3open(NULL, tdb_path, 0, TDB_DEFAULT, O_RDWR, 0);
+       if (!db) {
                DEBUG(1, ("Error opening tdb %s\n", tdb_path));
-               return ret;
+               return NULL;
        }
 
-       ret = tdb_validate(tdb, validate_fn);
-       tdb_close(tdb);
-       return ret;
+       if (db_validate(db, validate_fn) == 0) {
+               name = talloc_strdup(NULL, dbwrap_name(db));
+       } else {
+               name = NULL;
+       }
+
+       talloc_free(db);
+       return name;
 }
 
 /*
- * tdb backup function and helpers for tdb_validate wrapper with backup
+ * db backup function and helpers for tdb_validate wrapper with backup
  * handling.
  */
 
 /* this structure eliminates the need for a global overall status for
  * the traverse-copy */
-struct tdb_copy_data {
-       struct tdb_context *dst;
+struct db_copy_data {
+       struct db_context *dst;
        bool success;
 };
 
-static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key,
-                           TDB_DATA dbuf, void *private_data)
+static int traverse_copy_fn(struct db_record *rec, void *private_data)
 {
-       struct tdb_copy_data *data = (struct tdb_copy_data *)private_data;
+       struct db_copy_data *data = (struct db_copy_data *)private_data;
+       TDB_DATA key = dbwrap_record_get_key(rec);
+       TDB_DATA dbuf = dbwrap_record_get_value(rec);
+       NTSTATUS status;
 
-       if (tdb_store(data->dst, key, dbuf, TDB_INSERT) != 0) {
-               DEBUG(4, ("Failed to insert into %s: %s\n", tdb_name(data->dst),
-                         strerror(errno)));
+       status = dbwrap_store(data->dst, key, dbuf, TDB_INSERT);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(4, ("Failed to insert into %s: %s\n",
+                         dbwrap_name(data->dst),
+                         nt_errstr(status)));
                data->success = False;
                return 1;
        }
        return 0;
 }
 
-static int tdb_copy(struct tdb_context *src, struct tdb_context *dst)
+static int db_copy(struct db_context *src, struct db_context *dst)
 {
-       struct tdb_copy_data data;
+       struct db_copy_data data;
        int count;
 
        data.dst = dst;
        data.success = True;
 
-       count = tdb_traverse(src, traverse_copy_fn, (void *)(&data));
-       if ((count < 0) || (data.success == False)) {
+       if (!NT_STATUS_IS_OK(dbwrap_traverse(src, traverse_copy_fn,
+                                            &data, &count))
+           || data.success == False) {
                return -1;
        }
        return count;
 }
 
-static int tdb_verify_basic(struct tdb_context *tdb)
+static int do_nothing(struct db_record *rec, void *unused)
 {
-       return tdb_traverse(tdb, NULL, NULL);
+       return 0;
+}
+
+static int db_verify_basic(struct db_context *db)
+{
+       int count;
+
+       if (!NT_STATUS_IS_OK(dbwrap_traverse(db, do_nothing, NULL, &count))) {
+               return -1;
+       }
+       return count;
 }
 
 /* this backup function is essentially taken from lib/tdb/tools/tdbbackup.tdb
  */
-static int tdb_backup(TALLOC_CTX *ctx, const char *src_path,
+static int db_backup(TALLOC_CTX *ctx, const char *src_path,
                      const char *dst_path, int hash_size)
 {
-       struct tdb_context *src_tdb = NULL;
-       struct tdb_context *dst_tdb = NULL;
+       struct db_context *src_db = NULL;
+       struct db_context *dst_db = NULL;
        char *tmp_path = NULL;
        struct stat st;
        int count1, count2;
@@ -270,19 +283,19 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path,
                goto done;
        }
 
-       /* open old tdb RDWR - so we can lock it */
-       src_tdb = tdb_open_log(src_path, 0, TDB_DEFAULT, O_RDWR, 0);
-       if (src_tdb == NULL) {
-               DEBUG(3, ("Failed to open tdb '%s'\n", src_path));
+       /* open old db RDWR - so we can lock it */
+       src_db = db_s3open(ctx, src_path, 0, TDB_DEFAULT, O_RDWR, 0);
+       if (src_db == NULL) {
+               DEBUG(3, ("Failed to open db '%s'\n", src_path));
                goto done;
        }
 
-       if (tdb_lockall(src_tdb) != 0) {
-               DEBUG(3, ("Failed to lock tdb '%s'\n", src_path));
+       if (dbwrap_transaction_start(src_db) != 0) {
+               DEBUG(3, ("Failed to lock db '%s'\n", src_path));
                goto done;
        }
 
-       tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp");
+       tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp.tdb");
        if (!tmp_path) {
                DEBUG(3, ("talloc fail\n"));
                goto done;
@@ -291,50 +304,64 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path,
        unlink(tmp_path);
 
        if (!hash_size) {
-               hash_size = tdb_hash_size(src_tdb);
+               hash_size = dbwrap_hash_size(src_db);
        }
 
-       dst_tdb = tdb_open_log(tmp_path, hash_size,
-                              TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL,
-                              st.st_mode & 0777);
-       if (dst_tdb == NULL) {
-               DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path,
-                         strerror(errno)));
+       /* This might open .tmp.tdb or .tmp.ntdb! */
+       dst_db = db_s3open(NULL, tmp_path, hash_size,
+                          TDB_DEFAULT, O_RDWR | O_CREAT | O_TRUNC,
+                          st.st_mode & 0777);
+       if (dst_db == NULL) {
                saved_errno = errno;
+               DEBUG(3, ("Error creating db '%s': %s\n", tmp_path,
+                         strerror(errno)));
                unlink(tmp_path);
                goto done;
        }
 
-       count1 = tdb_copy(src_tdb, dst_tdb);
+       if (dbwrap_transaction_start(dst_db) != 0) {
+               saved_errno = errno;
+               unlink(dbwrap_name(dst_db));
+               goto done;
+       }
+
+       count1 = db_copy(src_db, dst_db);
        if (count1 < 0) {
-               DEBUG(3, ("Failed to copy tdb '%s': %s\n", src_path,
+               DEBUG(3, ("Failed to copy db '%s': %s\n", src_path,
                          strerror(errno)));
-               tdb_close(dst_tdb);
+               unlink(dbwrap_name(dst_db));
+               TALLOC_FREE(dst_db);
+               goto done;
+       }
+
+       if (dbwrap_transaction_commit(dst_db) != 0) {
+               unlink(dbwrap_name(dst_db));
                goto done;
        }
 
        /* reopen ro and do basic verification */
-       tdb_close(dst_tdb);
-       dst_tdb = tdb_open_log(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0);
-       if (!dst_tdb) {
-               DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path,
+       TALLOC_FREE(dst_db);
+       dst_db = db_s3open(NULL, tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0);
+       if (!dst_db) {
+               DEBUG(3, ("Failed to reopen db '%s': %s\n", tmp_path,
                          strerror(errno)));
                goto done;
        }
-       count2 = tdb_verify_basic(dst_tdb);
+       count2 = db_verify_basic(dst_db);
        if (count2 != count1) {
-               DEBUG(3, ("Failed to verify result of copying tdb '%s'.\n",
+               DEBUG(3, ("Failed to verify result of copying db '%s'.\n",
                          src_path));
-               tdb_close(dst_tdb);
+               TALLOC_FREE(dst_db);
                goto done;
        }
 
-       DEBUG(10, ("tdb_backup: successfully copied %d entries\n", count1));
+       DEBUG(10, ("db_backup: successfully copied %d entries\n", count1));
 
-       /* make sure the new tdb has reached stable storage
-        * then rename it to its destination */
-       fsync(tdb_fd(dst_tdb));
-       tdb_close(dst_tdb);
+       /* Grab name before we close db. */
+       talloc_free(tmp_path);
+       tmp_path = talloc_strdup(src_db, dbwrap_name(dst_db));
+
+       TALLOC_FREE(dst_db);
        unlink(dst_path);
        if (rename(tmp_path, dst_path) != 0) {
                DEBUG(3, ("Failed to rename '%s' to '%s': %s\n",
@@ -346,9 +373,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path,
        ret = 0;
 
 done:
-       if (src_tdb != NULL) {
-               tdb_close(src_tdb);
-       }
+       TALLOC_FREE(src_db);
        if (tmp_path != NULL) {
                unlink(tmp_path);
                TALLOC_FREE(tmp_path);
@@ -388,19 +413,19 @@ static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path,
 }
 
 /*
- * do a backup of a tdb, moving the destination out of the way first
+ * do a backup of a db, moving the destination out of the way first
  */
-static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path,
-                                 const char *dst_path, int hash_size,
-                                 const char *rotate_suffix,
-                                 bool retry_norotate_if_nospc,
-                                 bool rename_as_last_resort_if_nospc)
+static int db_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path,
+                                const char *dst_path, int hash_size,
+                                const char *rotate_suffix,
+                                bool retry_norotate_if_nospc,
+                                bool rename_as_last_resort_if_nospc)
 {
        int ret;
 
        rename_file_with_suffix(ctx, dst_path, rotate_suffix);
 
-       ret = tdb_backup(ctx, src_path, dst_path, hash_size);
+       ret = db_backup(ctx, src_path, dst_path, hash_size);
 
        if (ret != 0) {
                DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno)));
@@ -421,14 +446,14 @@ static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path,
                        DEBUG(10, ("unlink of %s failed: %s\n", rotate_path,
                                   strerror(errno)));
                } else {
-                       ret = tdb_backup(ctx, src_path, dst_path, hash_size);
+                       ret = db_backup(ctx, src_path, dst_path, hash_size);
                }
                TALLOC_FREE(rotate_path);
        }
 
        if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc)
        {
-               DEBUG(10, ("backup of %s failed due to lack of space\n", 
+               DEBUG(10, ("backup of %s failed due to lack of space\n",
                           src_path));
                DEBUGADD(10, ("using 'rename' as a last resort\n"));
                ret = rename(src_path, dst_path);
@@ -451,14 +476,14 @@ static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path,
  *     if restore is successful, return 0 (success),
  *    - otherwise return -1 (failure)
  */
-int tdb_validate_and_backup(const char *tdb_path,
-                           tdb_validate_data_func validate_fn)
+int db_validate_and_backup(const char *tdb_path,
+                          db_validate_data_func validate_fn)
 {
        int ret = -1;
        const char *backup_suffix = ".bak";
        const char *corrupt_suffix = ".corrupt";
        const char *rotate_suffix = ".old";
-       char *tdb_path_backup;
+       const char *tdb_path_backup, *realname;
        struct stat st;
        TALLOC_CTX *ctx = NULL;
 
@@ -468,41 +493,54 @@ int tdb_validate_and_backup(const char *tdb_path,
                goto done;
        }
 
-       tdb_path_backup = talloc_asprintf(ctx, "%s%s", tdb_path, backup_suffix);
-       if (!tdb_path_backup) {
-               DEBUG(0, ("tdb_validate_and_backup: out of memory\n"));
-               goto done;
-       }
-
-       ret = tdb_validate_open(tdb_path, validate_fn);
-
-       if (ret == 0) {
-               DEBUG(1, ("tdb '%s' is valid\n", tdb_path));
-               ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0,
-                                            rotate_suffix, True, False);
+       realname = db_validate_open(ctx, tdb_path, validate_fn);
+       if (realname) {
+               DEBUG(1, ("tdb '%s' is valid\n", realname));
+               tdb_path_backup = talloc_asprintf(ctx, "%s%s",
+                                                 realname, backup_suffix);
+               if (!tdb_path_backup) {
+                       DEBUG(0, ("tdb_validate_and_backup: out of memory\n"));
+                       goto done;
+               }
+               ret = db_backup_with_rotate(ctx, realname, tdb_path_backup, 0,
+                                           rotate_suffix, True, False);
                if (ret != 0) {
                        DEBUG(1, ("Error creating backup of tdb '%s'\n",
-                                 tdb_path));
+                                 realname));
                        /* the actual validation was successful: */
                        ret = 0;
                } else {
                        DEBUG(1, ("Created backup '%s' of tdb '%s'\n",
-                                 tdb_path_backup, tdb_path));
+                                 tdb_path_backup, realname));
                }
        } else {
+               realname = tdb_path;
                DEBUG(1, ("tdb '%s' is invalid\n", tdb_path));
 
-               ret =stat(tdb_path_backup, &st);
+               tdb_path_backup = talloc_asprintf(ctx, "%s%s",
+                                                 tdb_path, backup_suffix);
+               ret = stat(tdb_path_backup, &st);
+               if (ret != 0 && strends(tdb_path, ".tdb")) {
+                       /* Try .ntdb? */
+                       realname = talloc_asprintf(ctx, "%.*s.ntdb",
+                                                  strlen(tdb_path)-4,
+                                                  tdb_path);
+                       tdb_path_backup = talloc_asprintf(ctx, "%s%s",
+                                                         realname,
+                                                         backup_suffix);
+                       ret = stat(tdb_path_backup, &st);
+               }
                if (ret != 0) {
                        DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup,
                                  strerror(errno)));
                        DEBUG(1, ("No backup found.\n"));
                } else {
                        DEBUG(1, ("backup '%s' found.\n", tdb_path_backup));
-                       ret = tdb_validate_open(tdb_path_backup, validate_fn);
-                       if (ret != 0) {
+                       if (db_validate_open(ctx, tdb_path_backup, validate_fn)
+                           == NULL) {
                                DEBUG(1, ("Backup '%s' is invalid.\n",
                                          tdb_path_backup));
+                               ret = -1;
                        }
                }
 
@@ -520,8 +558,8 @@ int tdb_validate_and_backup(const char *tdb_path,
                }
 
                DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup));
-               ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0,
-                                            corrupt_suffix, True, True);
+               ret = db_backup_with_rotate(ctx, tdb_path_backup, realname, 0,
+                                           corrupt_suffix, True, True);
                if (ret != 0) {
                        DEBUG(1, ("Error restoring backup from '%s'\n",
                                  tdb_path_backup));
similarity index 59%
rename from source3/lib/tdb_validate.h
rename to source3/lib/db_validate.h
index 5bb043d2924c6a75345a420b7631c16fb9c55d87..f225a3b6a036b4ba689854d20f46875a8b3497f2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Unix SMB/CIFS implementation.
  *
- * A general tdb content validation mechanism
+ * A general (n)tdb content validation mechanism
  *
  * Copyright (C) Michael Adam      2007
  *
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __TDB_VALIDATE_H__
-#define __TDB_VALIDATE_H__
+#ifndef __DB_VALIDATE_H__
+#define __DB_VALIDATE_H__
 
 #include "lib/replace/replace.h"
-#include "tdb_compat.h"
+#include "dbwrap/dbwrap.h"
 
 /**
  * Flag field for keeping track of the status of a validation.
  */
-struct tdb_validation_status {
-       bool tdb_error;
-       bool bad_freelist;
+struct db_validation_status {
+       bool db_error;
        bool bad_entry;
        bool unknown_key;
        bool success;
@@ -39,41 +38,41 @@ struct tdb_validation_status {
 /**
  * Callback function type for the validation mechanism.
  */
-typedef int (*tdb_validate_data_func)(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
-                                     TDB_DATA dbuf, void *state);
+typedef int (*db_validate_data_func)(struct db_record*, void*);
 
 /**
- * tdb validation function.
- * returns 0 if tdb is ok, != 0 if it isn't.
- * this function expects an opened tdb.
+ * (n)tdb validation function.
+ * returns 0 if db is ok, != 0 if it isn't.
+ * this function expects an opened db.
  */
-int tdb_validate(struct tdb_context *tdb,
-                tdb_validate_data_func validate_fn);
+int db_validate(struct db_context *db,
+               db_validate_data_func validate_fn);
 
 /**
- * tdb validation function.
- * returns 0 if tdb is ok, != 0 if it isn't.
+ * (n)tdb validation function.
+ * returns the real name of db if ok, NULL if it isn't.
+ * tallocs return value off ctx.
  * This is a wrapper around the actual validation function that
  * opens and closes the tdb.
  */
-int tdb_validate_open(const char *tdb_path,
-                     tdb_validate_data_func validate_fn);
+char *db_validate_open(TALLOC_CTX *ctx, const char *db_path,
+                      db_validate_data_func validate_fn);
 
 /**
  * validation function with backup handling:
  *
- *  - calls tdb_validate
- *  - if the tdb is ok, create a backup "name.bak", possibly moving
+ *  - calls db_validate
+ *  - if the db is ok, create a backup "name.bak", possibly moving
  *    existing backup to name.bak.old,
  *    return 0 (success) even if the backup fails
- *  - if the tdb is corrupt:
- *    - move the tdb to "name.corrupt"
+ *  - if the db is corrupt:
+ *    - move the db to "name.corrupt"
  *    - check if there is valid backup.
  *      if so, restore the backup.
  *      if restore is successful, return 0 (success),
  *    - otherwise return -1 (failure)
  */
-int tdb_validate_and_backup(const char *tdb_path,
-                           tdb_validate_data_func validate_fn);
+int db_validate_and_backup(const char *db_path,
+                          db_validate_data_func validate_fn);
 
-#endif /* __TDB_VALIDATE_H__ */
+#endif /* __DB_VALIDATE_H__ */
index bcafe763a29b2eaba87c0a031276b92fd327bd4b..534ea60760b1df88b2dca22bf163f54426972bc5 100755 (executable)
@@ -9,7 +9,7 @@ TDB_LIB_SRC = '''
           lib/dbwrap/dbwrap_watch.c
           lib/g_lock.c'''
 
-TDB_VALIDATE_SRC = '''lib/tdb_validate.c'''
+DB_VALIDATE_SRC = '''lib/db_validate.c'''
 
 SMBLDAP_SRC = '''lib/smbldap.c'''
 
@@ -325,7 +325,7 @@ WINBINDD_SRC1 = '''winbindd/winbindd.c
                    winbindd/winbindd_pam_chng_pswd_auth_crap.c'''
 
 WINBINDD_SRC = '''${WINBINDD_SRC1}
-                  ${TDB_VALIDATE_SRC}'''
+                  ${DB_VALIDATE_SRC}'''
 
 MANGLE_SRC = '''smbd/mangle.c smbd/mangle_hash.c smbd/mangle_hash2.c'''