s3:net ads join: reduce indentation in _net_ads_join_dns_updates()
[ira/wip.git] / source3 / utils / net_idmap_check.c
index 556a058edbb9d5fdb97f6dfa607a21ababd3a1ae..1269410beeca664ce132a77f96762269e277dc34 100644 (file)
 #include "net_idmap_check.h"
 #include "includes.h"
 #include "system/filesys.h"
-#include "dbwrap.h"
+#include "dbwrap/dbwrap.h"
+#include "dbwrap/dbwrap_open.h"
+#include "dbwrap/dbwrap_rbt.h"
 #include "net.h"
 #include "../libcli/security/dom_sid.h"
 #include "cbuf.h"
 #include "srprs.h"
-#include <termios.h>
+#include "util_tdb.h"
+#include "interact.h"
 
 static int traverse_commit(struct db_record *diff_rec, void* data);
 static int traverse_check(struct db_record *rec, void* data);
 
-static char* interact_edit(TALLOC_CTX* mem_ctx, const char* str);
-static int interact_prompt(const char* msg, const char* accept, char def);
-
 /* TDB_DATA *******************************************************************/
 static char*    print_data(TALLOC_CTX* mem_ctx, TDB_DATA d);
 static TDB_DATA parse_data(TALLOC_CTX* mem_ctx, const char** ptr);
 static TDB_DATA talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data);
-static bool is_empty(TDB_DATA data) {
-       return (data.dsize == 0) || (data.dptr == NULL);
-}
 
 /* record *********************************************************************/
 
 enum DT {
        DT_INV = 0,
        DT_SID, DT_UID, DT_GID,
-       DT_HWM, DT_VER
+       DT_HWM, DT_VER, DT_SEQ,
 };
 
 struct record {
@@ -225,8 +222,13 @@ static char get_action(struct check_action* a, struct record* r, TDB_DATA* v) {
                        d_printf("%s: %s ", a->name, print_data(r, r->key));
                        if (is_map(r)) {
                                d_printf("-> %s\n", print_data(r, r->val));
-                       } else {
+                       } else if (r->key_type == DT_HWM ||
+                                  r->key_type == DT_VER ||
+                                  r->key_type == DT_SEQ)
+                       {
                                d_printf(": %ld\n", r->id);
+                       } else {
+                               d_printf("\n");
                        }
                } else {
                        d_printf(a->fmt, a->name,
@@ -270,10 +272,10 @@ static TDB_DATA_diff unpack_diff(TDB_DATA data) {
 
 #define DEBUG_DIFF(LEV,MEM,MSG,KEY,OLD,NEW)                    \
        DEBUG(LEV, ("%s: %s\n", MSG, print_data(MEM, KEY)));    \
-       if (!is_empty(OLD)) {                                   \
+       if (!tdb_data_is_empty(OLD)) {                          \
                DEBUGADD(LEV, ("-%s\n", print_data(MEM, OLD))); \
        }                                                       \
-       if (!is_empty(NEW)) {                                   \
+       if (!tdb_data_is_empty(NEW)) {                          \
                DEBUGADD(LEV, ("+%s\n", print_data(MEM, NEW))); \
        }
 
@@ -305,21 +307,29 @@ static int add_record(struct check_ctx* ctx, TDB_DATA key, TDB_DATA value)
        NTSTATUS status;
        TDB_DATA_diff diff;
        TALLOC_CTX* mem = talloc_new(ctx->diff);
-       struct db_record* rec = ctx->diff->fetch_locked(ctx->diff, mem, key);
+       TDB_DATA recvalue;
+       struct db_record *rec = dbwrap_fetch_locked(ctx->diff, mem, key);
+
        if (rec == NULL) {
                return -1;
-       };
-       if (rec->value.dptr == 0) { /* first entry */
-               diff.oval = dbwrap_fetch(ctx->db, ctx->diff, key);
+       }
+
+       recvalue = dbwrap_record_get_value(rec);
+
+       if (recvalue.dptr == 0) { /* first entry */
+               status = dbwrap_fetch(ctx->db, ctx->diff, key, &diff.oval);
+               if (!NT_STATUS_IS_OK(status)) {
+                       diff.oval = tdb_null;
+               }
        } else {
-               diff = unpack_diff(rec->value);
+               diff = unpack_diff(recvalue);
                talloc_free(diff.nval.dptr);
        }
        diff.nval = talloc_copy(ctx->diff, value);
 
        DEBUG_DIFF(2, mem, "TDB DIFF", key, diff.oval, diff.nval);
 
-       status = rec->store(rec, pack_diff(&diff), 0);
+       status = dbwrap_record_store(rec, pack_diff(&diff), 0);
 
        talloc_free(mem);
 
@@ -339,20 +349,19 @@ static TDB_DATA
 fetch_record(struct check_ctx* ctx, TALLOC_CTX* mem_ctx, TDB_DATA key)
 {
        TDB_DATA tmp;
+       NTSTATUS status;
 
-       if (ctx->diff->fetch(ctx->diff, mem_ctx, key, &tmp) == -1) {
-               DEBUG(0, ("Out of memory!\n"));
-               return tdb_null;
-       }
-       if (tmp.dptr != NULL) {
+       status = dbwrap_fetch(ctx->diff, mem_ctx, key, &tmp);
+
+       if (NT_STATUS_IS_OK(status)) {
                TDB_DATA_diff diff = unpack_diff(tmp);
                TDB_DATA ret = talloc_copy(mem_ctx, diff.nval);
                talloc_free(tmp.dptr);
                return ret;
        }
 
-       if (ctx->db->fetch(ctx->db, mem_ctx, key, &tmp) == -1) {
-               DEBUG(0, ("Out of memory!\n"));
+       status = dbwrap_fetch(ctx->db, mem_ctx, key, &tmp);
+       if (!NT_STATUS_IS_OK(status)) {
                return tdb_null;
        }
 
@@ -381,10 +390,12 @@ static void edit_record(struct record* r) {
 static bool check_version(struct check_ctx* ctx) {
        static const char* key = "IDMAP_VERSION";
        uint32_t version;
-       bool no_version = !dbwrap_fetch_uint32(ctx->db, key, &version);
+       NTSTATUS status;
        char action = 's';
        struct check_actions* act = &ctx->action;
-       if (no_version) {
+
+       status = dbwrap_fetch_uint32(ctx->db, key, &version);
+       if (!NT_STATUS_IS_OK(status)) {
                d_printf("No version number, assume 2\n");
                action = get_action(&act->no_version, NULL, NULL);
        } else if (version != 2) {
@@ -410,9 +421,11 @@ static bool check_version(struct check_ctx* ctx) {
 static void check_hwm(struct check_ctx* ctx, const char* key, uint32_t target) {
        uint32_t hwm;
        char action = 's';
-       bool found = dbwrap_fetch_uint32(ctx->db, key, &hwm);
+       NTSTATUS status;
        struct check_actions* act = &ctx->action;
-       if (!found) {
+
+       status = dbwrap_fetch_uint32(ctx->db, key, &hwm);
+       if (!NT_STATUS_IS_OK(status)) {
                d_printf("No %s should be %d\n", key, target);
                action = get_action(&act->invalid_hwm, NULL, NULL);
        } else if (target < hwm) {
@@ -430,9 +443,16 @@ int traverse_check(struct db_record *rec, void* data) {
        struct check_ctx* ctx = (struct check_ctx*)data;
        struct check_actions* act = &ctx->action;
        TALLOC_CTX* mem = talloc_new(ctx->diff);
-       struct record* r = parse_record(mem, rec->key, rec->value);
+       TDB_DATA key;
+       TDB_DATA value;
+       struct record *r;
        char action = 's';
 
+       key = dbwrap_record_get_key(rec);
+       value = dbwrap_record_get_value(rec);
+
+       r = parse_record(mem, key, value);
+
        if (is_invalid(r)) {
                action = get_action(&act->invalid_record, r, NULL);
                ctx->n_invalid_record++;
@@ -464,10 +484,10 @@ int traverse_check(struct db_record *rec, void* data) {
                case 's': /* skip */
                        break;
                case 'd': /* delete */
-                       del_record(ctx, rec->key);
+                       del_record(ctx, key);
                        break;
                case 'f': /* add reverse mapping */
-                       add_record(ctx, rec->value, rec->key);
+                       add_record(ctx, value, key);
                        break;
                case 'e': /* edit */
                        edit_record(r);
@@ -476,9 +496,9 @@ int traverse_check(struct db_record *rec, void* data) {
                                action = get_action(&act->invalid_edit, r,NULL);
                                continue;
                        }
-                       if (!tdb_data_equal(rec->key, r->key)) {
+                       if (!tdb_data_equal(key, r->key)) {
                                TDB_DATA oval = fetch_record(ctx, mem, r->key);
-                               if (!is_empty(oval) &&
+                               if (!tdb_data_is_empty(oval) &&
                                    !tdb_data_equal(oval, r->val))
                                {
                                        action = get_action(&act->record_exists,
@@ -490,7 +510,7 @@ int traverse_check(struct db_record *rec, void* data) {
                        }
                        if (is_map(r)) {
                                TDB_DATA okey = fetch_record(ctx, mem, r->val);
-                               if (!is_empty(okey) &&
+                               if (!tdb_data_is_empty(okey) &&
                                    !tdb_data_equal(okey, r->key))
                                {
                                        action = get_action(&act->record_exists,
@@ -501,8 +521,8 @@ int traverse_check(struct db_record *rec, void* data) {
                        continue;
                case 'o': /* overwrite */
                        adjust_hwm(ctx, r);
-                       if (!tdb_data_equal(rec->key, r->key)) {
-                               del_record(ctx, rec->key);
+                       if (!tdb_data_equal(key, r->key)) {
+                               del_record(ctx, key);
                        }
                        add_record(ctx, r->key, r->val);
                        if (is_map(r)) {
@@ -543,7 +563,7 @@ TDB_DATA talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data) {
 }
 
 static bool is_cstr(TDB_DATA str) {
-       return !is_empty(str) && str.dptr[str.dsize-1] == '\0';
+       return !tdb_data_is_empty(str) && str.dptr[str.dsize-1] == '\0';
 }
 
 static bool parse_sid (TDB_DATA str, enum DT* type, struct dom_sid* sid) {
@@ -621,6 +641,12 @@ parse_record(TALLOC_CTX* mem_ctx, TDB_DATA key, TDB_DATA val)
                        ret->id = IVAL(val.dptr,0);
                        ret->val_type = DT_VER;
                }
+       } else if (strcmp((const char*)key.dptr, "__db_sequence_number__") == 0) {
+               ret->key_type = DT_SEQ;
+               if (val.dsize == 8) {
+                       ret->id = *(uint64_t*)val.dptr;
+                       ret->val_type = DT_SEQ;
+               }
        }
 
        return ret;
@@ -634,35 +660,10 @@ struct record* reverse_record(struct record* in)
 
 /******************************************************************************/
 
-int interact_prompt(const char* msg, const char* acc, char def) {
-       struct termios old_tio, new_tio;
-       int c;
-
-       tcgetattr(STDIN_FILENO, &old_tio);
-       new_tio=old_tio;
-       new_tio.c_lflag &=(~ICANON & ~ECHO);
-       tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
-
-       do {
-               d_printf("%s? [%c]\n", msg, def);
-               fflush(stdout);
-               c = getchar();
-               if (c == '\n') {
-                       c = def;
-                       break;
-               }
-               else if (strchr(acc, tolower(c)) != NULL) {
-                       break;
-               }
-               d_printf("Invalid input '%c'\n", c);
-       } while(c != EOF);
-       tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
-       return c;
-}
 
 char* print_data(TALLOC_CTX* mem_ctx, TDB_DATA d)
 {
-       if (!is_empty(d)) {
+       if (!tdb_data_is_empty(d)) {
                char* ret = NULL;
                cbuf* ost = cbuf_new(mem_ctx);
                int len = cbuf_print_quoted(ost, (const char*)d.dptr, d.dsize);
@@ -689,76 +690,17 @@ TDB_DATA parse_data(TALLOC_CTX* mem_ctx, const char** ptr) {
        return ret;
 }
 
-static const char* get_editor(void) {
-       static const char* editor = NULL;
-       if (editor == NULL) {
-               editor = getenv("VISUAL");
-               if (editor == NULL) {
-                       editor = getenv("EDITOR");
-               }
-               if (editor == NULL) {
-                       editor = "vi";
-               }
-       }
-       return editor;
-}
-
-char* interact_edit(TALLOC_CTX* mem_ctx, const char* str) {
-       char fname[] = "/tmp/net_idmap_check.XXXXXX";
-       char buf[128];
-       char* ret = NULL;
-       FILE* file;
-
-       int fd = mkstemp(fname);
-       if (fd == -1) {
-               DEBUG(0, ("failed to mkstemp %s: %s\n", fname,
-                         strerror(errno)));
-               return NULL;
-       }
-
-       file  = fdopen(fd, "w");
-       if (!file) {
-               DEBUG(0, ("failed to open %s for writing: %s\n", fname,
-                         strerror(errno)));
-               close(fd);
-               unlink(fname);
-               return NULL;
-       }
-
-       fprintf(file, "%s", str);
-       fclose(file);
-
-       snprintf(buf, sizeof(buf), "%s %s\n", get_editor(), fname);
-       if (system(buf) != 0) {
-               DEBUG(0, ("failed to start editor %s: %s\n", buf,
-                         strerror(errno)));
-               unlink(fname);
-               return NULL;
-       }
-
-       file = fopen(fname, "r");
-       if (!file) {
-               DEBUG(0, ("failed to open %s for reading: %s\n", fname,
-                         strerror(errno)));
-               unlink(fname);
-               return NULL;
-       }
-       while ( fgets(buf, sizeof(buf), file) ) {
-               ret = talloc_strdup_append(ret, buf);
-       }
-       fclose(file);
-       unlink(fname);
-
-       return talloc_steal(mem_ctx, ret);
-}
-
-
 static int traverse_print_diff(struct db_record *rec, void* data) {
        struct check_ctx* ctx = (struct check_ctx*)data;
-       TDB_DATA key = rec->key;
-       TDB_DATA_diff diff = unpack_diff(rec->value);
+       TDB_DATA key;
+       TDB_DATA value;
+       TDB_DATA_diff diff;
        TALLOC_CTX* mem = talloc_new(ctx->diff);
 
+       key = dbwrap_record_get_key(rec);
+       value = dbwrap_record_get_value(rec);
+       diff = unpack_diff(value);
+
        DEBUG_DIFF(0, mem, "DIFF", key, diff.oval, diff.nval);
 
        talloc_free(mem);
@@ -768,25 +710,34 @@ static int traverse_print_diff(struct db_record *rec, void* data) {
 
 static int traverse_commit(struct db_record *diff_rec, void* data) {
        struct check_ctx* ctx = (struct check_ctx*)data;
-       TDB_DATA_diff diff = unpack_diff(diff_rec->value);
-       TDB_DATA key = diff_rec->key;
+       TDB_DATA key;
+       TDB_DATA diff_value;
+       TDB_DATA_diff diff;
+       TDB_DATA value;
        TALLOC_CTX* mem = talloc_new(ctx->diff);
        int ret = -1;
        NTSTATUS status;
        struct check_actions* act = &ctx->action;
+       struct db_record* rec;
+
+       key = dbwrap_record_get_key(diff_rec);
+       diff_value = dbwrap_record_get_value(diff_rec);
+       diff = unpack_diff(diff_value);
 
-       struct db_record* rec = ctx->db->fetch_locked(ctx->db, mem, key);
+       rec = dbwrap_fetch_locked(ctx->db, mem, key);
        if (rec == NULL) {
                goto done;
-       };
+       }
+
+       value = dbwrap_record_get_value(rec);
 
-       if (!tdb_data_equal(rec->value, diff.oval)) {
+       if (!tdb_data_equal(value, diff.oval)) {
                char action;
 
                d_printf("Warning: record has changed: %s\n"
                         "expected: %s got %s\n", print_data(mem, key),
                         print_data(mem, diff.oval),
-                        print_data(mem, rec->value));
+                        print_data(mem, value));
 
                action = get_action(&act->invalid_diff, NULL, NULL);
                if (action == 's') {
@@ -799,10 +750,10 @@ static int traverse_commit(struct db_record *diff_rec, void* data) {
 
        DEBUG_DIFF(0, mem, "Commit", key, diff.oval, diff.nval);
 
-       if (is_empty(diff.nval)) {
-               status = rec->delete_rec(rec);
+       if (tdb_data_is_empty(diff.nval)) {
+               status = dbwrap_record_delete(rec);
        } else {
-               status = rec->store(rec, diff.nval, 0);
+               status = dbwrap_record_store(rec, diff.nval, 0);
        }
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -853,7 +804,8 @@ static bool check_open_db(struct check_ctx* ctx, const char* name, int oflags)
                }
        }
 
-       ctx->db = db_open(ctx, name, 0, TDB_DEFAULT, oflags, 0);
+       ctx->db = db_open(ctx, name, 0, TDB_DEFAULT, oflags, 0,
+                         DBWRAP_LOCK_ORDER_1);
        if (ctx->db == NULL) {
                d_fprintf(stderr,
                          _("Could not open idmap db (%s) for writing: %s\n"),
@@ -878,7 +830,7 @@ static bool check_do_checks(struct check_ctx* ctx)
                return false;
        }
 
-       status = dbwrap_traverse(ctx->db, traverse_check, ctx);
+       status = dbwrap_traverse(ctx->db, traverse_check, ctx, NULL);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("failed to traverse %s\n", ctx->name));
@@ -902,20 +854,20 @@ static void check_summary(const struct check_ctx* ctx)
 }
 
 static bool check_transaction_start(struct check_ctx* ctx) {
-       return (ctx->db->transaction_start(ctx->db) == 0);
+       return (dbwrap_transaction_start(ctx->db) == 0);
 }
 
 static bool check_transaction_commit(struct check_ctx* ctx) {
-       return (ctx->db->transaction_commit(ctx->db) == 0);
+       return (dbwrap_transaction_commit(ctx->db) == 0);
 }
 
 static bool check_transaction_cancel(struct check_ctx* ctx) {
-       return (ctx->db->transaction_cancel(ctx->db) == 0);
+       return (dbwrap_transaction_cancel(ctx->db) == 0);
 }
 
 
 static void check_diff_list(struct check_ctx* ctx) {
-       NTSTATUS status = dbwrap_traverse(ctx->diff, traverse_print_diff, ctx);
+       NTSTATUS status = dbwrap_traverse(ctx->diff, traverse_print_diff, ctx, NULL);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("failed to traverse diff\n"));
@@ -951,13 +903,13 @@ static bool check_commit(struct check_ctx* ctx)
                return false;
        }
 
-       status = dbwrap_traverse(ctx->diff, traverse_commit, ctx);
+       status = dbwrap_traverse(ctx->diff, traverse_commit, ctx, NULL);
 
        if (!NT_STATUS_IS_OK(status)) {
                check_transaction_cancel(ctx);
                return false;
        }
-       if (ctx->opts.test) { //get_action?
+       if (ctx->opts.test) { /*get_action? */
                return check_transaction_cancel(ctx);
        } else {
                return check_transaction_commit(ctx);