int connections_forall(int (*fn)(struct db_record *rec, const struct connections_key *key, const struct connections_data *data, void *private_data), void *private_data) { struct db_context *ctx; struct conn_traverse_state state; NTSTATUS status; int count; ctx = connections_db_ctx(true); if (ctx == NULL) { return -1; } state.fn = fn; state.private_data = private_data; status = dbwrap_traverse(ctx, conn_traverse_fn, (void *)&state, &count); if (!NT_STATUS_IS_OK(status)) { return -1; } return count; }
static NTSTATUS smbXsrv_tcon_disconnect_all(struct smbXsrv_tcon_table *table, uint64_t vuid) { struct smbXsrv_tcon_disconnect_all_state state; NTSTATUS status; int count = 0; if (table == NULL) { return NT_STATUS_OK; } ZERO_STRUCT(state); state.vuid = vuid; status = dbwrap_traverse(table->local.db_ctx, smbXsrv_tcon_disconnect_all_callback, &state, &count); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("smbXsrv_tcon_disconnect_all: " "dbwrap_traverse() failed: %s\n", nt_errstr(status))); return status; } if (!NT_STATUS_IS_OK(state.first_status)) { DEBUG(0, ("smbXsrv_tcon_disconnect_all: " "count[%d] errors[%d] first[%s]\n", count, state.errors, nt_errstr(state.first_status))); return state.first_status; } return NT_STATUS_OK; }
static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data) { struct dbwrap_trans_traverse_action_ctx* ctx = (struct dbwrap_trans_traverse_action_ctx*)private_data; NTSTATUS status = dbwrap_traverse(db, ctx->f, ctx->private_data, NULL); return status; }
static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn, void *private_data) { struct db_context *db; NTSTATUS status; db = get_printer_list_db(); if (db == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } status = dbwrap_traverse(db, fn, private_data, NULL); return status; }
static int dbwrap_cache_traverse(struct db_context *db, int (*f)(struct db_record *rec, void *private_data), void *private_data) { struct db_cache_ctx *ctx = talloc_get_type_abort( db->private_data, struct db_cache_ctx); NTSTATUS status; int ret; status = dbwrap_traverse(ctx->backing, f, private_data, &ret); if (!NT_STATUS_IS_OK(status)) { return -1; } return ret; }
/** * dbwrap_tool_erase: erase the whole data base * the keyname argument is not used. */ static int dbwrap_tool_erase(struct db_context *db, const char *keyname, const char *data) { NTSTATUS status; status = dbwrap_traverse(db, delete_fn, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, "ERROR erasing the database\n"); return -1; } return 0; }
bool serverid_traverse(int (*fn)(struct db_record *rec, const struct server_id *id, uint32_t msg_flags, void *private_data), void *private_data) { struct db_context *db; struct serverid_traverse_state state; NTSTATUS status; db = serverid_db(); if (db == NULL) { return false; } state.fn = fn; state.private_data = private_data; status = dbwrap_traverse(db, serverid_traverse_fn, &state, NULL); return NT_STATUS_IS_OK(status); }
int connections_traverse(int (*fn)(struct db_record *rec, void *private_data), void *private_data) { NTSTATUS status; int count; struct db_context *ctx = connections_db_ctx(False); if (ctx == NULL) { return -1; } status = dbwrap_traverse(ctx, fn, private_data, &count); if (!NT_STATUS_IS_OK(status)) { return -1; } return count; }
static WERROR regdb_upgrade_v1_to_v2(struct db_context *db) { TALLOC_CTX *mem_ctx; NTSTATUS status; WERROR werr; mem_ctx = talloc_stackframe(); status = dbwrap_traverse(db, regdb_normalize_keynames_fn, db, NULL); if (!NT_STATUS_IS_OK(status)) { werr = WERR_REG_IO_FAILURE; goto done; } werr = regdb_store_regdb_version(db, REGDB_VERSION_V2); done: talloc_free(mem_ctx); return werr; }
static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32_t from) { struct tdbsam_convert_state state; struct db_context *db = NULL; NTSTATUS status; /* We only need the update backup for local db's. */ if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) { DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name)); return false; } db = *pp_db; state.from = from; state.success = true; if (dbwrap_transaction_start(db) != 0) { DEBUG(0, ("tdbsam_convert: Could not start transaction\n")); return false; } if (!tdbsam_upgrade_next_rid(db)) { DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n")); goto cancel; } status = dbwrap_traverse(db, tdbsam_convert_one, &state, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("tdbsam_convert: traverse failed\n")); goto cancel; } if (!state.success) { DEBUG(0, ("tdbsam_convert: Converting records failed\n")); goto cancel; } status = dbwrap_store_int32_bystring(db, TDBSAM_VERSION_STRING, TDBSAM_VERSION); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("tdbsam_convert: Could not store tdbsam version: " "%s\n", nt_errstr(status))); goto cancel; } status = dbwrap_store_int32_bystring(db, TDBSAM_MINOR_VERSION_STRING, TDBSAM_MINOR_VERSION); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor " "version: %s\n", nt_errstr(status))); goto cancel; } if (dbwrap_transaction_commit(db) != 0) { DEBUG(0, ("tdbsam_convert: Could not commit transaction\n")); return false; } return true; cancel: if (dbwrap_transaction_cancel(db) != 0) { smb_panic("tdbsam_convert: transaction_cancel failed"); } return false; }
static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) { TALLOC_CTX *frame = talloc_stackframe(); const char *tmp_fname = NULL; struct db_context *tmp_db = NULL; struct db_context *orig_db = *pp_db; struct tdbsam_backup_state bs; NTSTATUS status; tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname); if (!tmp_fname) { TALLOC_FREE(frame); return false; } unlink(tmp_fname); /* Remember to open this on the NULL context. We need * it to stay around after we return from here. */ tmp_db = db_open(NULL, tmp_fname, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (tmp_db == NULL) { DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd " "[%s]\n", tmp_fname)); TALLOC_FREE(frame); return false; } if (dbwrap_transaction_start(orig_db) != 0) { DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n")); unlink(tmp_fname); TALLOC_FREE(tmp_db); TALLOC_FREE(frame); return false; } if (dbwrap_transaction_start(tmp_db) != 0) { DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n")); dbwrap_transaction_cancel(orig_db); unlink(tmp_fname); TALLOC_FREE(tmp_db); TALLOC_FREE(frame); return false; } bs.new_db = tmp_db; bs.success = true; status = dbwrap_traverse(orig_db, backup_copy_fn, (void *)&bs, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("tdbsam_convert_backup: traverse failed\n")); goto cancel; } if (!bs.success) { DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n")); goto cancel; } if (dbwrap_transaction_commit(orig_db) != 0) { smb_panic("tdbsam_convert_backup: orig commit failed\n"); } if (dbwrap_transaction_commit(tmp_db) != 0) { smb_panic("tdbsam_convert_backup: orig commit failed\n"); } /* be sure to close the DBs _before_ renaming the file */ TALLOC_FREE(orig_db); TALLOC_FREE(tmp_db); /* This is safe from other users as we know we're * under a mutex here. */ if (rename(tmp_fname, dbname) == -1) { DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n", tmp_fname, dbname, strerror(errno))); smb_panic("tdbsam_convert_backup: replace passdb failed\n"); } TALLOC_FREE(frame); /* re-open the converted TDB */ orig_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (orig_db == NULL) { DEBUG(0, ("tdbsam_convert_backup: Failed to re-open " "converted passdb TDB [%s]\n", dbname)); return false; } DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n", dbname )); /* Replace the global db pointer. */ *pp_db = orig_db; return true; cancel: if (dbwrap_transaction_cancel(orig_db) != 0) { smb_panic("tdbsam_convert: transaction_cancel failed"); } if (dbwrap_transaction_cancel(tmp_db) != 0) { smb_panic("tdbsam_convert: transaction_cancel failed"); } unlink(tmp_fname); TALLOC_FREE(tmp_db); TALLOC_FREE(frame); return false; }
static bool idmap_tdb_upgrade(struct idmap_domain *dom, struct db_context *db) { int32 vers; bool bigendianheader; struct convert_fn_state s; NTSTATUS status; #if BUILD_TDB2 /* If we are bigendian, tdb is bigendian if NOT converted. */ union { uint16 large; unsigned char small[2]; } u; u.large = 0x0102; if (u.small[0] == 0x01) bigendianheader = !(dbwrap_get_flags(db) & TDB_CONVERT); else { assert(u.small[0] == 0x02); bigendianheader = (dbwrap_get_flags(db) & TDB_CONVERT); } #else bigendianheader = (dbwrap_get_flags(db) & TDB_BIGENDIAN) ? True : False; #endif DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n")); status = dbwrap_fetch_int32(db, "IDMAP_VERSION", &vers); if (!NT_STATUS_IS_OK(status)) { vers = -1; } if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) { /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ /* * high and low records were created on a * big endian machine and will need byte-reversing. */ int32 wm; status = dbwrap_fetch_int32(db, HWM_USER, &wm); if (!NT_STATUS_IS_OK(status)) { wm = -1; } if (wm != -1) { wm = IREV(wm); } else { wm = dom->low_id; } status = dbwrap_store_int32(db, HWM_USER, wm); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to byteswap user hwm in idmap " "database: %s\n", nt_errstr(status))); return False; } status = dbwrap_fetch_int32(db, HWM_GROUP, &wm); if (!NT_STATUS_IS_OK(status)) { wm = -1; } if (wm != -1) { wm = IREV(wm); } else { wm = dom->low_id; } status = dbwrap_store_int32(db, HWM_GROUP, wm); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to byteswap group hwm in idmap " "database: %s\n", nt_errstr(status))); return False; } } s.db = db; s.failed = false; /* the old format stored as DOMAIN/rid - now we store the SID direct */ status = dbwrap_traverse(db, convert_fn, &s, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Database traverse failed during conversion\n")); return false; } if (s.failed) { DEBUG(0, ("Problem during conversion\n")); return False; } status = dbwrap_store_int32(db, "IDMAP_VERSION", IDMAP_VERSION); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to store idmap version in database: %s\n", nt_errstr(status))); return False; } return True; }
static bool upgrade_v2_to_v3_check_subkeylist(struct db_context *db, const char *key, const char *subkey) { static uint32_t zero = 0; static TDB_DATA empty_subkey_list = { .dptr = (unsigned char*)&zero, .dsize = sizeof(uint32_t), }; bool success = false; char *path = talloc_asprintf(talloc_tos(), "%s\\%s", key, subkey); strupper_m(path); if (!dbwrap_exists(db, string_term_tdb_data(path))) { NTSTATUS status; DEBUG(10, ("regdb_upgrade_v2_to_v3: writing subkey list [%s]\n", path)); status = dbwrap_store_bystring(db, path, empty_subkey_list, TDB_INSERT); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("regdb_upgrade_v2_to_v3: writing subkey list " "[%s] failed\n", path)); goto done; } } success = true; done: talloc_free(path); return success; } static bool upgrade_v2_to_v3_check_parent(struct db_context *db, const char *key) { const char *sep = strrchr_m(key, '\\'); if (sep != NULL) { char *pkey = talloc_strndup(talloc_tos(), key, sep-key); if (!dbwrap_exists(db, string_term_tdb_data(pkey))) { DEBUG(0, ("regdb_upgrade_v2_to_v3: missing subkey list " "[%s]\nrun \"net registry check\"\n", pkey)); } talloc_free(pkey); } return true; } #define IS_EQUAL(d,s) (((d).dsize == strlen(s)+1) && \ (strcmp((char*)(d).dptr, (s)) == 0)) #define STARTS_WITH(d,s) (((d).dsize > strlen(s)) && \ (strncmp((char*)(d).dptr, (s), strlen(s)) == 0)) #define SSTR(d) (int)(d).dsize , (char*)(d).dptr static int regdb_upgrade_v2_to_v3_fn(struct db_record *rec, void *private_data) { struct db_context *db = (struct db_context *)private_data; TDB_DATA key = dbwrap_record_get_key(rec); TDB_DATA val = dbwrap_record_get_value(rec); if (tdb_data_is_empty(key)) { return 0; } if (db == NULL) { DEBUG(0, ("regdb_upgrade_v2_to_v3_fn: ERROR: " "NULL db context handed in via private_data\n")); return 1; } if (IS_EQUAL(key, REGDB_VERSION_KEYNAME) || STARTS_WITH(key, REG_VALUE_PREFIX) || STARTS_WITH(key, REG_SECDESC_PREFIX)) { DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping [%.*s]\n", SSTR(key))); return 0; } if (STARTS_WITH(key, REG_SORTED_SUBKEYS_PREFIX)) { NTSTATUS status; /* Delete the deprecated sorted subkeys cache. */ DEBUG(10, ("regdb_upgrade_v2_to_v3: deleting [%.*s]\n", SSTR(key))); status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("regdb_upgrade_v2_to_v3: deleting [%.*s] " "failed!\n", SSTR(key))); return 1; } return 0; } if ( tdb_data_is_cstr(key) && hive_info((char*)key.dptr) != NULL ) { /* * Found a regular subkey list record. * Walk the list and create the list record for those * subkeys that don't already have one. */ TDB_DATA pos = val; char *subkey, *path = (char*)key.dptr; uint32_t num_items, found_items = 0; DEBUG(10, ("regdb_upgrade_v2_to_v3: scanning subkeylist of " "[%s]\n", path)); if (!tdb_data_read_uint32(&pos, &num_items)) { /* invalid or empty - skip */ return 0; } while (tdb_data_read_cstr(&pos, &subkey)) { found_items++; if (!upgrade_v2_to_v3_check_subkeylist(db, path, subkey)) { return 1; } if (!upgrade_v2_to_v3_check_parent(db, path)) { return 1; } } if (found_items != num_items) { DEBUG(0, ("regdb_upgrade_v2_to_v3: inconsistent subkey " "list [%s]\nrun \"net registry check\"\n", path)); } } else { DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping invalid [%.*s]\n" "run \"net registry check\"\n", SSTR(key))); } return 0; } static WERROR regdb_upgrade_v2_to_v3(struct db_context *db) { NTSTATUS status; WERROR werr; status = dbwrap_traverse(db, regdb_upgrade_v2_to_v3_fn, db, NULL); if (!NT_STATUS_IS_OK(status)) { werr = WERR_REG_IO_FAILURE; goto done; } werr = regdb_store_regdb_version(db, REGDB_VERSION_V3); done: return werr; }
static bool idmap_tdb_upgrade(struct idmap_domain *dom, struct db_context *db) { int32_t vers; struct convert_fn_state s; NTSTATUS status; status = dbwrap_fetch_int32_bystring(db, "IDMAP_VERSION", &vers); if (!NT_STATUS_IS_OK(status)) { vers = -1; } if (IREV(vers) == IDMAP_VERSION) { /* Arrggghh ! Bytereversed - make order independent ! */ /* * high and low records were created on a * big endian machine and will need byte-reversing. */ int32_t wm; status = dbwrap_fetch_int32_bystring(db, HWM_USER, &wm); if (!NT_STATUS_IS_OK(status)) { wm = -1; } if (wm != -1) { wm = IREV(wm); } else { wm = dom->low_id; } status = dbwrap_store_int32_bystring(db, HWM_USER, wm); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to byteswap user hwm in idmap " "database: %s\n", nt_errstr(status))); return False; } status = dbwrap_fetch_int32_bystring(db, HWM_GROUP, &wm); if (!NT_STATUS_IS_OK(status)) { wm = -1; } if (wm != -1) { wm = IREV(wm); } else { wm = dom->low_id; } status = dbwrap_store_int32_bystring(db, HWM_GROUP, wm); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to byteswap group hwm in idmap " "database: %s\n", nt_errstr(status))); return False; } } s.db = db; s.failed = false; /* the old format stored as DOMAIN/rid - now we store the SID direct */ status = dbwrap_traverse(db, convert_fn, &s, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Database traverse failed during conversion\n")); return false; } if (s.failed) { DEBUG(0, ("Problem during conversion\n")); return False; } status = dbwrap_store_int32_bystring(db, "IDMAP_VERSION", IDMAP_VERSION); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to store idmap version in database: %s\n", nt_errstr(status))); return False; } return True; }
bool share_info_db_init(void) { const char *vstring = "INFO/version"; int32 vers_id = 0; bool upgrade_ok = true; NTSTATUS status; if (share_db != NULL) { return True; } share_db = db_open(NULL, state_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); if (share_db == NULL) { DEBUG(0,("Failed to open share info database %s (%s)\n", state_path("share_info.tdb"), strerror(errno) )); return False; } status = dbwrap_fetch_int32(share_db, vstring, &vers_id); if (!NT_STATUS_IS_OK(status)) { vers_id = 0; } if (vers_id == SHARE_DATABASE_VERSION_V3) { return true; } if (dbwrap_transaction_start(share_db) != 0) { DEBUG(0, ("transaction_start failed\n")); TALLOC_FREE(share_db); return false; } status = dbwrap_fetch_int32(share_db, vstring, &vers_id); if (!NT_STATUS_IS_OK(status)) { vers_id = 0; } if (vers_id == SHARE_DATABASE_VERSION_V3) { /* * Race condition */ if (dbwrap_transaction_cancel(share_db)) { smb_panic("transaction_cancel failed"); } return true; } /* Move to at least V2. */ /* Cope with byte-reversed older versions of the db. */ if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) { /* Written on a bigendian machine with old fetch_int code. Save as le. */ status = dbwrap_store_int32(share_db, vstring, SHARE_DATABASE_VERSION_V2); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dbwrap_store_int32 failed: %s\n", nt_errstr(status))); goto cancel; } vers_id = SHARE_DATABASE_VERSION_V2; } if (vers_id != SHARE_DATABASE_VERSION_V2) { status = dbwrap_traverse(share_db, delete_fn, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("traverse failed\n")); goto cancel; } status = dbwrap_store_int32(share_db, vstring, SHARE_DATABASE_VERSION_V2); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dbwrap_store_int32 failed: %s\n", nt_errstr(status))); goto cancel; } } /* Finally upgrade to version 3, with canonicalized sharenames. */ status = dbwrap_traverse(share_db, upgrade_v2_to_v3, &upgrade_ok, NULL); if (!NT_STATUS_IS_OK(status) || upgrade_ok == false) { DEBUG(0, ("traverse failed\n")); goto cancel; } status = dbwrap_store_int32(share_db, vstring, SHARE_DATABASE_VERSION_V3); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dbwrap_store_int32 failed: %s\n", nt_errstr(status))); goto cancel; } if (dbwrap_transaction_commit(share_db) != 0) { DEBUG(0, ("transaction_commit failed\n")); return false; } return true; cancel: if (dbwrap_transaction_cancel(share_db)) { smb_panic("transaction_cancel failed"); } return false; }