r23600: First step in abstracting the winbindd cache validation
authorMichael Adam <obnox@samba.org>
Mon, 25 Jun 2007 20:17:04 +0000 (20:17 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:23:35 +0000 (12:23 -0500)
code into a generic tdb validation code.
In lib/util_tdb.c for a start.

Michael

source/include/util_tdb.h
source/lib/util_tdb.c
source/nsswitch/winbindd_cache.c

index 803d18c5eb06287bd79e147df11b2db14768c90f..5fd05f59fc55a94ccd27f9a637c363d90b1ae382 100644 (file)
@@ -41,6 +41,16 @@ struct tdb_wrap {
        struct tdb_wrap *next, *prev;
 };
 
+struct tdb_validation_status {
+       BOOL tdb_error;
+       BOOL bad_freelist;
+       BOOL bad_entry;
+       BOOL unknown_key;
+       BOOL success;
+};
+
+typedef int (*tdb_validate_data_func)(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state);
+
 TDB_LIST_NODE *tdb_search_keys(struct tdb_context*, const char*);
 void tdb_search_list_free(TDB_LIST_NODE*);
 int32 tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32 *oldval, int32 change_val);
index 6d783198d62569602b4afaa036398c0f48149a07..cb53b7f2e37cdfaf6875b1023eff6e469306c763 100644 (file)
@@ -980,3 +980,206 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err)
 
        return NT_STATUS_INTERNAL_ERROR;
 }
+
+
+/*********************************************************************
+ * the following is a generic validation mechanism for tdbs.
+ *********************************************************************/
+
+/* 
+ * internal validation function, executed by the child.  
+ */
+static int tdb_validate_child(const char *tdb_path,
+                             tdb_validate_data_func validate_fn, 
+                             int pfd)
+{
+       int ret = -1;
+       int tfd = -1;
+       int num_entries = 0;
+       TDB_CONTEXT *tdb = NULL;
+       struct tdb_validation_status v_status;
+       
+       v_status.tdb_error = False;
+       v_status.bad_freelist = False;
+       v_status.bad_entry = False;
+       v_status.unknown_key = False;
+       v_status.success = True;
+
+       tdb = tdb_open_log(tdb_path,
+                       WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+                       lp_winbind_offline_logon() 
+                               ?  TDB_DEFAULT 
+                               : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST),
+                       O_RDWR|O_CREAT, 0600);
+       if (!tdb) {
+               v_status.tdb_error = True;
+               v_status.success = False;
+               goto out;
+       }
+
+       tfd = tdb_fd(tdb);
+
+       /* Check the cache freelist is good. */
+       if (tdb_validate_freelist(tdb, &num_entries) == -1) {
+               DEBUG(0,("tdb_validate_child: bad freelist in cache %s\n",
+                       tdb_path));
+               v_status.bad_freelist = True;
+               v_status.success = False;
+               goto out;
+       }
+
+       DEBUG(10,("tdb_validate_child: cache %s freelist has %d entries\n",
+               tdb_path, num_entries));
+
+       /* Now traverse the cache to validate it. */
+       num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status);
+       if (num_entries == -1 || !(v_status.success)) {
+               DEBUG(0,("tdb_validate_child: cache %s traverse failed\n",
+                       tdb_path));
+               if (!(v_status.success)) {
+                       if (v_status.bad_entry) {
+                               DEBUGADD(0, (" -> bad entry found\n"));
+                       }
+                       if (v_status.unknown_key) {
+                               DEBUGADD(0, (" -> unknown key encountered\n"));
+                       }
+               }
+               goto out;
+       }
+
+       DEBUG(10,("tdb_validate_child: cache %s is good "
+               "with %d entries\n", tdb_path, num_entries));
+       ret = 0; /* Cache is good. */
+
+out:
+       if (tdb) {
+               if (ret == 0) {
+                       tdb_close(tdb);
+               } 
+               else if (tfd != -1) {
+                       close(tfd);
+               }
+       }
+
+       DEBUG(10, ("tdb_validate_child: writing status to pipe\n"));
+       write (pfd, (const char *)&v_status, sizeof(v_status));
+       close(pfd);
+
+       return ret;
+}
+
+int tdb_validate(const char *tdb_path, tdb_validate_data_func validate_fn)
+{
+       pid_t child_pid = -1;
+       int child_status = 0;
+       int wait_pid = 0;
+       int ret = -1;
+       int pipe_fds[2];
+       struct tdb_validation_status v_status;
+       int bytes_read = 0;
+       
+       /* 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. 
+        * communicate the extended status struct over a pipe. */
+
+       if (pipe(pipe_fds) != 0) {
+               DEBUG(0, ("tdb_validate: unable to create pipe, "
+                         "error %s", strerror(errno)));
+               smb_panic("winbind_validate_cache: unable to create pipe.");
+       }
+
+       DEBUG(10, ("tdb_validate: forking to let child do validation.\n"));
+       child_pid = sys_fork();
+       if (child_pid == 0) {
+               DEBUG(10, ("tdb_validate (validation child): created\n"));
+               close(pipe_fds[0]); /* close reading fd */
+               DEBUG(10, ("tdb_validate (validation child): "
+                          "calling tdb_validate_child\n"));
+               exit(tdb_validate_child(tdb_path, validate_fn, pipe_fds[1]));
+       }
+       else if (child_pid < 0) {
+               smb_panic("tdb_validate: fork for validation failed.");
+       }
+
+       /* parent */
+
+       DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n", 
+                  child_pid));
+       close(pipe_fds[1]); /* close writing fd */
+
+       v_status.success = True;
+       v_status.bad_entry = False;
+       v_status.unknown_key = False;
+
+       DEBUG(10, ("tdb_validate: reading from pipe.\n"));
+       bytes_read = read(pipe_fds[0], (void *)&v_status, sizeof(v_status));
+       close(pipe_fds[0]);
+
+       if (bytes_read != sizeof(v_status)) {
+               DEBUG(10, ("tdb_validate: read %d bytes from pipe "
+                          "but expected %d", bytes_read, (int)sizeof(v_status)));
+               DEBUGADD(10, (" -> assuming child crashed\n"));
+               v_status.success = False;
+       }
+       else {
+               DEBUG(10,    ("tdb_validate: read status from child\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"));
+               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"));
+       }
+
+       if (!v_status.success) {
+               DEBUG(10, ("tdb_validate: validation not successful.\n"));
+               DEBUGADD(10, ("removing tdb %s.\n", tdb_path));
+               unlink(tdb_path);
+       }
+
+       DEBUG(10, ("tdb_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, retrying\n"));
+                       errno = 0;
+                       continue;
+               }
+               DEBUG(0, ("tdb_validate: waitpid failed with "
+                          "errno %s\n", strerror(errno)));
+               smb_panic("tdb_validate: waitpid failed.");
+       }
+       if (wait_pid != child_pid) {
+               DEBUG(0, ("tdb_validate: waitpid returned pid %d, "
+                         "but %d was expexted\n", wait_pid, child_pid));
+               smb_panic("tdb_validate: waitpid returned "
+                            "unexpected PID.");
+       }
+
+               
+       DEBUG(10, ("tdb_validate: validating child returned.\n"));
+       if (WIFEXITED(child_status)) {
+               DEBUG(10, ("tdb_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", WTERMSIG(child_status)));
+#ifdef WCOREDUMP
+               if (WCOREDUMP(child_status)) {
+                       DEBUGADD(10, ("core dumped\n"));
+               }
+#endif
+               ret = WTERMSIG(child_status);
+       }
+       if (WIFSTOPPED(child_status)) {
+               DEBUG(10, ("tdb_validate: child was stopped "
+                          "by signal %d\n",
+                          WSTOPSIG(child_status)));
+               ret = WSTOPSIG(child_status);
+       }
+
+       return ret;
+}
+
index 017a2ebfebb8c9973b59c0624fe1b3daff31187c..122432d95b27e661f6049b4018f1ceb51782218a 100644 (file)
@@ -2749,16 +2749,8 @@ BOOL get_global_winbindd_state_offline(void)
  Validate functions for all possible cache tdb keys.
 ***********************************************************************/
 
-struct validation_status {
-       BOOL tdb_error;
-       BOOL bad_freelist;
-       BOOL bad_entry;
-       BOOL unknown_key;
-       BOOL success;
-};
-
 static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA data, 
-                                                 struct validation_status *state)
+                                                 struct tdb_validation_status *state)
 {
        struct cache_entry *centry;
 
@@ -2786,7 +2778,7 @@ static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA dat
 }
 
 static int validate_seqnum(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                          struct validation_status *state)
+                          struct tdb_validation_status *state)
 {
        if (dbuf.dsize != 8) {
                DEBUG(0,("validate_seqnum: Corrupt cache for key %s (len %u != 8) ?\n",
@@ -2798,7 +2790,7 @@ static int validate_seqnum(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbu
 }
 
 static int validate_ns(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        if (!centry) {
@@ -2821,7 +2813,7 @@ static int validate_ns(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_sn(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        if (!centry) {
@@ -2844,7 +2836,7 @@ static int validate_sn(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_u(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                     struct validation_status *state)
+                     struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        DOM_SID sid;
@@ -2871,7 +2863,7 @@ static int validate_u(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_loc_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                           struct validation_status *state)
+                           struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
 
@@ -2893,7 +2885,7 @@ static int validate_loc_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db
 }
 
 static int validate_pwd_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                           struct validation_status *state)
+                           struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
 
@@ -2917,7 +2909,7 @@ static int validate_pwd_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db
 }
 
 static int validate_cred(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                        struct validation_status *state)
+                        struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
 
@@ -2943,7 +2935,7 @@ static int validate_cred(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_ul(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        int32 num_entries, i;
@@ -2974,7 +2966,7 @@ static int validate_ul(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_gl(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        int32 num_entries, i;
@@ -3001,7 +2993,7 @@ static int validate_gl(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_ug(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        int32 num_groups, i;
@@ -3027,7 +3019,7 @@ static int validate_ug(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_ua(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        int32 num_aliases, i;
@@ -3052,7 +3044,7 @@ static int validate_ua(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_gm(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        int32 num_names, i;
@@ -3080,7 +3072,7 @@ static int validate_gm(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_dr(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        /* Can't say anything about this other than must be nonzero. */
        if (dbuf.dsize == 0) {
@@ -3096,7 +3088,7 @@ static int validate_dr(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                      struct validation_status *state)
+                      struct tdb_validation_status *state)
 {
        /* Can't say anything about this other than must be nonzero. */
        if (dbuf.dsize == 0) {
@@ -3112,7 +3104,7 @@ static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 }
 
 static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                             struct validation_status *state)
+                             struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
        int32 num_domains, i;
@@ -3141,7 +3133,7 @@ static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA
 
 static int validate_trustdomcache(TALLOC_CTX *mem_ctx, const char *keystr, 
                                  TDB_DATA dbuf,
-                                 struct validation_status *state)
+                                 struct tdb_validation_status *state)
 {
        if (dbuf.dsize == 0) {
                DEBUG(0, ("validate_trustdomcache: Corrupt cache for "
@@ -3157,7 +3149,7 @@ static int validate_trustdomcache(TALLOC_CTX *mem_ctx, const char *keystr,
 }
 
 static int validate_offline(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                           struct validation_status *state)
+                           struct tdb_validation_status *state)
 {
        if (dbuf.dsize != 4) {
                DEBUG(0,("validate_offline: Corrupt cache for key %s (len %u != 4) ?\n",
@@ -3171,7 +3163,7 @@ static int validate_offline(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db
 }
 
 static int validate_cache_version(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
-                                 struct validation_status *state)
+                                 struct tdb_validation_status *state)
 {
        if (dbuf.dsize != 4) {
                DEBUG(0, ("validate_cache_version: Corrupt cache for "
@@ -3193,7 +3185,7 @@ static int validate_cache_version(TALLOC_CTX *mem_ctx, const char *keystr, TDB_D
 
 struct key_val_struct {
        const char *keyname;
-       int (*validate_data_fn)(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, struct validation_status* state);
+       int (*validate_data_fn)(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, struct tdb_validation_status* state);
 } key_val[] = {
        {"SEQNUM/", validate_seqnum},
        {"NS/", validate_ns},
@@ -3224,7 +3216,7 @@ struct key_val_struct {
 static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
 {
        int i;
-       struct validation_status *v_state = (struct validation_status *)state;
+       struct tdb_validation_status *v_state = (struct tdb_validation_status *)state;
 
        /* Paranoia check. */
        if (kbuf.dsize > 1024) {
@@ -3285,201 +3277,15 @@ static void validate_panic(const char *const why)
  function) will restart us as we don't know if we crashed or not.
 ***********************************************************************/
 
-/* 
- * internal validation function, executed by the child.  
- */
-static int winbindd_validate_cache_child(const char *cache_path, int pfd)
-{
-       int ret = -1;
-       int tfd = -1;
-       int num_entries = 0;
-       TDB_CONTEXT *tdb = NULL;
-       struct validation_status v_status;
-       
-       v_status.tdb_error = False;
-       v_status.bad_freelist = False;
-       v_status.bad_entry = False;
-       v_status.unknown_key = False;
-       v_status.success = True;
-
-       tdb = tdb_open_log(cache_path,
-                       WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
-                       lp_winbind_offline_logon() 
-                               ?  TDB_DEFAULT 
-                               : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST),
-                       O_RDWR|O_CREAT, 0600);
-       if (!tdb) {
-               v_status.tdb_error = True;
-               v_status.success = False;
-               goto out;
-       }
-
-       tfd = tdb_fd(tdb);
-
-       /* Check the cache freelist is good. */
-       if (tdb_validate_freelist(tdb, &num_entries) == -1) {
-               DEBUG(0,("winbindd_validate_cache_child: bad freelist in cache %s\n",
-                       cache_path));
-               v_status.bad_freelist = True;
-               v_status.success = False;
-               goto out;
-       }
-
-       DEBUG(10,("winbindd_validate_cache_child: cache %s freelist has %d entries\n",
-               cache_path, num_entries));
-
-       /* Now traverse the cache to validate it. */
-       num_entries = tdb_traverse(tdb, cache_traverse_validate_fn, (void *)&v_status);
-       if (num_entries == -1 || !(v_status.success)) {
-               DEBUG(0,("winbindd_validate_cache_child: cache %s traverse failed\n",
-                       cache_path));
-               if (!(v_status.success)) {
-                       if (v_status.bad_entry) {
-                               DEBUGADD(0, (" -> bad entry found\n"));
-                       }
-                       if (v_status.unknown_key) {
-                               DEBUGADD(0, (" -> unknown key encountered\n"));
-                       }
-               }
-               goto out;
-       }
-
-       DEBUG(10,("winbindd_validate_cache_child: cache %s is good "
-               "with %d entries\n", cache_path, num_entries));
-       ret = 0; /* Cache is good. */
-
-out:
-       if (tdb) {
-               if (ret == 0) {
-                       tdb_close(tdb);
-               } 
-               else if (tfd != -1) {
-                       close(tfd);
-               }
-       }
-
-       DEBUG(10, ("winbindd_validate_cache_child: writing status to pipe\n"));
-       write (pfd, (const char *)&v_status, sizeof(v_status));
-       close(pfd);
-
-       return ret;
-}
-
 int winbindd_validate_cache(void)
 {
-       pid_t child_pid = -1;
-       int child_status = 0;
-       int wait_pid = 0;
-       int ret = -1;
-       int pipe_fds[2];
-       struct validation_status v_status;
-       int bytes_read = 0;
-       const char *cache_path = lock_path("winbindd_cache.tdb");
-       
+       int ret;
+
        DEBUG(10, ("winbindd_validate_cache: replacing panic function\n"));
        smb_panic_fn = validate_panic;
 
-       /* 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. 
-        * communicate the extended status struct over a pipe. */
-
-       if (pipe(pipe_fds) != 0) {
-               DEBUG(0, ("winbindd_validate_cache: unable to create pipe, "
-                         "error %s", strerror(errno)));
-               smb_panic("winbind_validate_cache: unable to create pipe.");
-       }
-
-       DEBUG(10, ("winbindd_validate_cache: forking to let child do validation.\n"));
-       child_pid = sys_fork();
-       if (child_pid == 0) {
-               DEBUG(10, ("winbindd_validate_cache (validation child): created\n"));
-               close(pipe_fds[0]); /* close reading fd */
-               DEBUG(10, ("winbindd_validate_cache (validation child): "
-                          "calling winbindd_validate_cache_child\n"));
-               exit(winbindd_validate_cache_child(cache_path, pipe_fds[1]));
-       }
-       else if (child_pid < 0) {
-               smb_panic("winbindd_validate_cache: fork for validation failed.");
-       }
-
-       /* parent */
-
-       DEBUG(10, ("winbindd_validate_cache: fork succeeded, child PID = %d\n", 
-                  child_pid));
-       close(pipe_fds[1]); /* close writing fd */
-
-       v_status.success = True;
-       v_status.bad_entry = False;
-       v_status.unknown_key = False;
-
-       DEBUG(10, ("winbindd_validate_cache: reading from pipe.\n"));
-       bytes_read = read(pipe_fds[0], (void *)&v_status, sizeof(v_status));
-       close(pipe_fds[0]);
-
-       if (bytes_read != sizeof(v_status)) {
-               DEBUG(10, ("winbindd_validate_cache: read %d bytes from pipe "
-                          "but expected %d", bytes_read, (int)sizeof(v_status)));
-               DEBUGADD(10, (" -> assuming child crashed\n"));
-               v_status.success = False;
-       }
-       else {
-               DEBUG(10,    ("winbindd_validate_cache: read status from child\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"));
-               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"));
-       }
-
-       if (!v_status.success) {
-               DEBUG(10, ("winbindd_validate_cache: validation not successful.\n"));
-               DEBUGADD(10, ("removing tdb %s.\n", cache_path));
-               unlink(cache_path);
-       }
-
-       DEBUG(10, ("winbindd_validate_cache: waiting for child to finish...\n"));
-       while  ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) {
-               if (errno == EINTR) {
-                       DEBUG(10, ("winbindd_validate_cache: got signal during "
-                                  "waitpid, retrying\n"));
-                       errno = 0;
-                       continue;
-               }
-               DEBUG(0, ("winbindd_validate_cache: waitpid failed with "
-                          "errno %s\n", strerror(errno)));
-               smb_panic("winbindd_validate_cache: waitpid failed.");
-       }
-       if (wait_pid != child_pid) {
-               DEBUG(0, ("winbindd_validate_cache: waitpid returned pid %d, "
-                         "but %d was expexted\n", wait_pid, child_pid));
-               smb_panic("winbindd_validate_cache: waitpid returned "
-                            "unexpected PID.");
-       }
-
-               
-       DEBUG(10, ("winbindd_validate_cache: validating child returned.\n"));
-       if (WIFEXITED(child_status)) {
-               DEBUG(10, ("winbindd_validate_cache: child exited, code %d.\n",
-                          WEXITSTATUS(child_status)));
-               ret = WEXITSTATUS(child_status);
-       }
-       if (WIFSIGNALED(child_status)) {
-               DEBUG(10, ("winbindd_validate_cache: child terminated "
-                          "by signal %d\n", WTERMSIG(child_status)));
-#ifdef WCOREDUMP
-               if (WCOREDUMP(child_status)) {
-                       DEBUGADD(10, ("core dumped\n"));
-               }
-#endif
-               ret = WTERMSIG(child_status);
-       }
-       if (WIFSTOPPED(child_status)) {
-               DEBUG(10, ("winbindd_validate_cache: child was stopped "
-                          "by signal %d\n",
-                          WSTOPSIG(child_status)));
-               ret = WSTOPSIG(child_status);
-       }
+       ret = tdb_validate(lock_path("winbindd_cache.tdb"),
+                          cache_traverse_validate_fn);
 
        DEBUG(10, ("winbindd_validate_cache: restoring panic function\n"));
        smb_panic_fn = smb_panic;