/** * Wrap db action(s) into a transaction. */ NTSTATUS dbwrap_trans_do(struct db_context *db, NTSTATUS (*action)(struct db_context *, void *), void *private_data) { int res; NTSTATUS status; res = dbwrap_transaction_start(db); if (res != 0) { DEBUG(5, ("transaction_start failed\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } status = action(db, private_data); if (!NT_STATUS_IS_OK(status)) { if (dbwrap_transaction_cancel(db) != 0) { smb_panic("Cancelling transaction failed"); } return status; } res = dbwrap_transaction_commit(db); if (res == 0) { return NT_STATUS_OK; } DEBUG(2, ("transaction_commit failed\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; }
static NTSTATUS idmap_tdb_init_hwm(struct idmap_domain *dom) { uint32_t low_uid; uint32_t low_gid; bool update_uid = false; bool update_gid = false; struct idmap_tdb_common_context *ctx; NTSTATUS status; ctx = talloc_get_type(dom->private_data, struct idmap_tdb_common_context); status = dbwrap_fetch_uint32_bystring(ctx->db, HWM_USER, &low_uid); if (!NT_STATUS_IS_OK(status) || low_uid < dom->low_id) { update_uid = true; } status = dbwrap_fetch_uint32_bystring(ctx->db, HWM_GROUP, &low_gid); if (!NT_STATUS_IS_OK(status) || low_gid < dom->low_id) { update_gid = true; } if (!update_uid && !update_gid) { return NT_STATUS_OK; } if (dbwrap_transaction_start(ctx->db) != 0) { DEBUG(0, ("Unable to start upgrade transaction!\n")); return NT_STATUS_INTERNAL_DB_ERROR; } if (update_uid) { status = dbwrap_store_uint32_bystring(ctx->db, HWM_USER, dom->low_id); if (!NT_STATUS_IS_OK(status)) { dbwrap_transaction_cancel(ctx->db); DEBUG(0, ("Unable to initialise user hwm in idmap " "database: %s\n", nt_errstr(status))); return NT_STATUS_INTERNAL_DB_ERROR; } } if (update_gid) { status = dbwrap_store_uint32_bystring(ctx->db, HWM_GROUP, dom->low_id); if (!NT_STATUS_IS_OK(status)) { dbwrap_transaction_cancel(ctx->db); DEBUG(0, ("Unable to initialise group hwm in idmap " "database: %s\n", nt_errstr(status))); return NT_STATUS_INTERNAL_DB_ERROR; } } if (dbwrap_transaction_commit(ctx->db) != 0) { DEBUG(0, ("Unable to commit upgrade transaction!\n")); return NT_STATUS_INTERNAL_DB_ERROR; } return NT_STATUS_OK; }
static bool open_db(struct idmap_tdb_common_context *ctx) { NTSTATUS status; char *db_path; if(ctx->db) { /* already open */ return true; } db_path = talloc_asprintf(talloc_tos(), "%s/idmap_test.tdb", lp_private_dir()); if(!db_path) { DEBUG(0, ("Out of memory!\n")); return false; } ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if(!ctx->db) { DEBUG(0, ("Failed to open database: %s\n", strerror(errno))); return false; } if(dbwrap_transaction_start(ctx->db) != 0) { DEBUG(0, ("Failed to start transaction!\n")); return false; } status = dbwrap_store_uint32_bystring(ctx->db, ctx->hwmkey_uid, LOW_ID); if(!NT_STATUS_IS_OK(status)) { dbwrap_transaction_cancel(ctx->db); return false; } status = dbwrap_store_uint32_bystring(ctx->db, ctx->hwmkey_gid, LOW_ID); if(!NT_STATUS_IS_OK(status)) { dbwrap_transaction_cancel(ctx->db); return false; } if(dbwrap_transaction_commit(ctx->db) != 0) { DEBUG(0, ("Failed to commit transaction!\n")); return false; } return true; }
/* return our global_sam_sid */ struct dom_sid *get_global_sam_sid(void) { struct db_context *db; if (global_sam_sid != NULL) return global_sam_sid; /* * memory for global_sam_sid is allocated in * pdb_generate_sam_sid() as needed * * Note: this is guarded by a transaction * to prevent races on startup which * can happen with some dbwrap backends */ db = secrets_db_ctx(); if (!db) { smb_panic("could not open secrets db"); } if (dbwrap_transaction_start(db) != 0) { smb_panic("could not start transaction on secrets db"); } if (!(global_sam_sid = pdb_generate_sam_sid())) { dbwrap_transaction_cancel(db); smb_panic("could not generate a machine SID"); } if (dbwrap_transaction_commit(db) != 0) { smb_panic("could not start commit secrets db"); } return global_sam_sid; }
static void test_store_records(struct db_context *db, struct tevent_context *ev) { TDB_DATA key; uint32_t *counters; TALLOC_CTX *tmp_ctx = talloc_stackframe(); struct timeval start; key = string_term_tdb_data("testkey"); start = timeval_current(); while ((timelimit == 0) || (timeval_elapsed(&start) < timelimit)) { struct db_record *rec; TDB_DATA data; TDB_DATA value; int ret; NTSTATUS status; if (!no_trans) { if (verbose) DEBUG(1, ("starting transaction\n")); ret = dbwrap_transaction_start(db); if (ret != 0) { DEBUG(0, ("Failed to start transaction on node " "%d\n", pnn)); goto fail; } if (verbose) DEBUG(1, ("transaction started\n")); do_sleep(torture_delay); } if (verbose) DEBUG(1, ("calling fetch_lock\n")); rec = dbwrap_fetch_locked(db, tmp_ctx, key); if (rec == NULL) { DEBUG(0, ("Failed to fetch record\n")); goto fail; } if (verbose) DEBUG(1, ("fetched record ok\n")); do_sleep(torture_delay); value = dbwrap_record_get_value(rec); data.dsize = MAX(value.dsize, sizeof(uint32_t) * (pnn+1)); data.dptr = (unsigned char *)talloc_zero_size(tmp_ctx, data.dsize); if (data.dptr == NULL) { DEBUG(0, ("Failed to allocate data\n")); goto fail; } memcpy(data.dptr, value.dptr, value.dsize); counters = (uint32_t *)data.dptr; /* bump our counter */ counters[pnn]++; if (verbose) DEBUG(1, ("storing data\n")); status = dbwrap_record_store(rec, data, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to store record\n")); if (!no_trans) { ret = dbwrap_transaction_cancel(db); if (ret != 0) { DEBUG(0, ("Error cancelling transaction.\n")); } } goto fail; } talloc_free(rec); if (verbose) DEBUG(1, ("stored data ok\n")); do_sleep(torture_delay); if (!no_trans) { if (verbose) DEBUG(1, ("calling transaction_commit\n")); ret = dbwrap_transaction_commit(db); if (ret != 0) { DEBUG(0, ("Failed to commit transaction\n")); goto fail; } if (verbose) DEBUG(1, ("transaction committed\n")); } /* store the counters and verify that they are sane */ if (verbose || (pnn == 0)) { if (!check_counters(db, data)) { goto fail; } } talloc_free(data.dptr); do_sleep(torture_delay); } goto done; fail: success = false; done: talloc_free(tmp_ctx); return; }
static int dbwrap_cache_transaction_commit(struct db_context *db) { struct db_cache_ctx *ctx = talloc_get_type_abort( db->private_data, struct db_cache_ctx); return dbwrap_transaction_commit(ctx->backing); }
/*************************************************************************** Renames a struct samu - check for the posix user/rename user script - Add and lock the new user record - rename the posix user - rewrite the rid->username record - delete the old user - unlock the new user record ***************************************************************************/ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods, struct samu *old_acct, const char *newname) { struct samu *new_acct = NULL; char *rename_script = NULL; int rename_ret; fstring oldname_lower; fstring newname_lower; /* can't do anything without an external script */ if ( !(new_acct = samu_new( talloc_tos() )) ) { return NT_STATUS_NO_MEMORY; } rename_script = lp_rename_user_script(new_acct); if (!rename_script) { TALLOC_FREE(new_acct); return NT_STATUS_NO_MEMORY; } if (!*rename_script) { TALLOC_FREE(new_acct); return NT_STATUS_ACCESS_DENIED; } if ( !pdb_copy_sam_account(new_acct, old_acct) || !pdb_set_username(new_acct, newname, PDB_CHANGED)) { TALLOC_FREE(new_acct); return NT_STATUS_NO_MEMORY; } /* open the database */ if ( !tdbsam_open( tdbsam_filename ) ) { DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename)); TALLOC_FREE(new_acct); return NT_STATUS_ACCESS_DENIED; } if (dbwrap_transaction_start(db_sam) != 0) { DEBUG(0, ("Could not start transaction\n")); TALLOC_FREE(new_acct); return NT_STATUS_ACCESS_DENIED; } /* add the new account and lock it */ if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) { goto cancel; } /* Rename the posix user. Follow the semantics of _samr_create_user() so that we lower case the posix name but preserve the case in passdb */ fstrcpy( oldname_lower, pdb_get_username(old_acct) ); if (!strlower_m( oldname_lower )) { goto cancel; } fstrcpy( newname_lower, newname ); if (!strlower_m( newname_lower )) { goto cancel; } rename_script = talloc_string_sub2(new_acct, rename_script, "%unew", newname_lower, true, false, true); if (!rename_script) { goto cancel; } rename_script = talloc_string_sub2(new_acct, rename_script, "%uold", oldname_lower, true, false, true); if (!rename_script) { goto cancel; } rename_ret = smbrun(rename_script, NULL, NULL); DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret)); if (rename_ret != 0) { goto cancel; } smb_nscd_flush_user_cache(); /* rewrite the rid->username record */ if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) { goto cancel; } tdb_delete_samacct_only( old_acct ); if (dbwrap_transaction_commit(db_sam) != 0) { /* * Ok, we're screwed. We've changed the posix account, but * could not adapt passdb.tdb. Shall we change the posix * account back? */ DEBUG(0, ("transaction_commit failed\n")); TALLOC_FREE(new_acct); return NT_STATUS_INTERNAL_DB_CORRUPTION; } TALLOC_FREE(new_acct ); return NT_STATUS_OK; cancel: if (dbwrap_transaction_cancel(db_sam) != 0) { smb_panic("transaction_cancel failed"); } TALLOC_FREE(new_acct); return NT_STATUS_ACCESS_DENIED; }
static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag) { uint32_t oldrid; uint32_t newrid; if (!(newrid = pdb_get_user_rid(newpwd))) { DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd))); return False; } oldrid = newrid; /* open the database */ if ( !tdbsam_open( tdbsam_filename ) ) { DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename)); return False; } if (dbwrap_transaction_start(db_sam) != 0) { DEBUG(0, ("Could not start transaction\n")); return false; } /* If we are updating, we may be changing this users RID. Retrieve the old RID so we can check. */ if (flag == TDB_MODIFY) { struct samu *account = samu_new(talloc_tos()); if (account == NULL) { DEBUG(0,("tdb_update_sam: samu_new() failed\n")); goto cancel; } if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods, account, pdb_get_username(newpwd)))) { DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n", pdb_get_username(newpwd))); TALLOC_FREE(account); goto cancel; } if (!(oldrid = pdb_get_user_rid(account))) { DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n")); TALLOC_FREE(account); goto cancel; } TALLOC_FREE(account); } /* Update the new samu entry. */ if (!tdb_update_samacct_only(newpwd, flag)) { goto cancel; } /* Now take care of the case where the RID changed. We need * to delete the old RID key and add the new. */ if (flag == TDB_MODIFY && newrid != oldrid) { fstring keystr; /* Delete old RID key */ DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid)); fstr_sprintf(keystr, "%s%.8x", RIDPREFIX, oldrid); if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam, keystr))) { DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr)); goto cancel; } /* Insert new RID key */ DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid)); if (!tdb_update_ridrec_only(newpwd, TDB_INSERT)) { goto cancel; } } else { DEBUG(10, ("tdb_update_sam: %s key for RID %u\n", flag == TDB_MODIFY ? "Updating" : "Inserting", newrid)); if (!tdb_update_ridrec_only(newpwd, flag)) { goto cancel; } } if (dbwrap_transaction_commit(db_sam) != 0) { DEBUG(0, ("Could not commit transaction\n")); return false; } return true; cancel: if (dbwrap_transaction_cancel(db_sam) != 0) { smb_panic("transaction_cancel failed"); } return false; }
static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; fstring keystr; uint32_t rid; fstring name; /* open the database */ if ( !tdbsam_open( tdbsam_filename ) ) { DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n", tdbsam_filename)); return NT_STATUS_ACCESS_DENIED; } fstrcpy(name, pdb_get_username(sam_pass)); if (!strlower_m(name)) { return NT_STATUS_INVALID_PARAMETER; } /* set the search key */ fstr_sprintf(keystr, "%s%s", USERPREFIX, name); rid = pdb_get_user_rid(sam_pass); /* it's outaa here! 8^) */ if (dbwrap_transaction_start(db_sam) != 0) { DEBUG(0, ("Could not start transaction\n")); return NT_STATUS_UNSUCCESSFUL; } nt_status = dbwrap_delete_bystring(db_sam, keystr); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(5, ("Error deleting entry from tdb passwd " "database: %s!\n", nt_errstr(nt_status))); goto cancel; } /* set the search key */ fstr_sprintf(keystr, "%s%.8x", RIDPREFIX, rid); /* it's outaa here! 8^) */ nt_status = dbwrap_delete_bystring(db_sam, keystr); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(5, ("Error deleting entry from tdb rid " "database: %s!\n", nt_errstr(nt_status))); goto cancel; } if (dbwrap_transaction_commit(db_sam) != 0) { DEBUG(0, ("Could not commit transaction\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } return NT_STATUS_OK; cancel: if (dbwrap_transaction_cancel(db_sam) != 0) { smb_panic("transaction_cancel failed"); } return nt_status; }
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 NTSTATUS idmap_tdb_open_db(struct idmap_domain *dom) { NTSTATUS ret; TALLOC_CTX *mem_ctx; char *tdbfile = NULL; struct db_context *db = NULL; int32_t version; bool config_error = false; struct idmap_tdb_context *ctx; ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); if (ctx->db) { /* it is already open */ return NT_STATUS_OK; } /* use our own context here */ mem_ctx = talloc_stackframe(); /* use the old database if present */ tdbfile = state_path("winbindd_idmap.tdb"); if (!tdbfile) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } DEBUG(10,("Opening tdbfile %s\n", tdbfile )); /* Open idmap repository */ db = db_open(mem_ctx, tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644); if (!db) { DEBUG(0, ("Unable to open idmap database\n")); ret = NT_STATUS_UNSUCCESSFUL; goto done; } /* check against earlier versions */ ret = dbwrap_fetch_int32(db, "IDMAP_VERSION", &version); if (!NT_STATUS_IS_OK(ret)) { version = -1; } if (version != IDMAP_VERSION) { if (config_error) { DEBUG(0,("Upgrade of IDMAP_VERSION from %d to %d is not " "possible with incomplete configuration\n", version, IDMAP_VERSION)); ret = NT_STATUS_UNSUCCESSFUL; goto done; } if (dbwrap_transaction_start(db) != 0) { DEBUG(0, ("Unable to start upgrade transaction!\n")); ret = NT_STATUS_INTERNAL_DB_ERROR; goto done; } if (!idmap_tdb_upgrade(dom, db)) { dbwrap_transaction_cancel(db); DEBUG(0, ("Unable to open idmap database, it's in an old format, and upgrade failed!\n")); ret = NT_STATUS_INTERNAL_DB_ERROR; goto done; } if (dbwrap_transaction_commit(db) != 0) { DEBUG(0, ("Unable to commit upgrade transaction!\n")); ret = NT_STATUS_INTERNAL_DB_ERROR; goto done; } } ctx->db = talloc_move(ctx, &db); ret = idmap_tdb_init_hwm(dom); done: talloc_free(mem_ctx); return ret; }
WERROR regdb_transaction_commit(void) { return (dbwrap_transaction_commit(regdb) == 0) ? WERR_OK : WERR_REG_IO_FAILURE; }
WERROR regdb_init(void) { int32_t vers_id; WERROR werr; NTSTATUS status; if (regdb) { DEBUG(10, ("regdb_init: incrementing refcount (%d->%d)\n", regdb_refcount, regdb_refcount+1)); regdb_refcount++; return WERR_OK; } regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600, DBWRAP_LOCK_ORDER_1); if (!regdb) { regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1); if (!regdb) { werr = ntstatus_to_werror(map_nt_error_from_unix(errno)); DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n", state_path("registry.tdb"), strerror(errno) )); return werr; } werr = regdb_store_regdb_version(regdb, REGDB_CODE_VERSION); if (!W_ERROR_IS_OK(werr)) { DEBUG(1, ("regdb_init: Failed to store version: %s\n", win_errstr(werr))); return werr; } DEBUG(10,("regdb_init: Successfully created registry tdb\n")); } regdb_refcount = 1; DEBUG(10, ("regdb_init: registry db openend. refcount reset (%d)\n", regdb_refcount)); status = dbwrap_fetch_int32(regdb, REGDB_VERSION_KEYNAME, &vers_id); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("regdb_init: registry version uninitialized " "(got %d), initializing to version %d\n", vers_id, REGDB_VERSION_V1)); /* * There was a regdb format version prior to version 1 * which did not store a INFO/version key. The format * of this version was identical to version 1 except for * the lack of the sorted subkey cache records. * Since these are disposable, we can safely assume version * 1 if no INFO/version key is found and run the db through * the whole chain of upgrade. If the database was not * initialized, this does not harm. If it was the unversioned * version ("0"), then it do the right thing with the records. */ werr = regdb_store_regdb_version(regdb, REGDB_VERSION_V1); if (!W_ERROR_IS_OK(werr)) { return werr; } vers_id = REGDB_VERSION_V1; } if (vers_id == REGDB_CODE_VERSION) { return WERR_OK; } if (vers_id > REGDB_CODE_VERSION || vers_id == 0) { DEBUG(0, ("regdb_init: unknown registry version %d " "(code version = %d), refusing initialization\n", vers_id, REGDB_CODE_VERSION)); return WERR_CAN_NOT_COMPLETE; } if (dbwrap_transaction_start(regdb) != 0) { return WERR_REG_IO_FAILURE; } if (vers_id == REGDB_VERSION_V1) { DEBUG(10, ("regdb_init: upgrading registry from version %d " "to %d\n", REGDB_VERSION_V1, REGDB_VERSION_V2)); werr = regdb_upgrade_v1_to_v2(regdb); if (!W_ERROR_IS_OK(werr)) { dbwrap_transaction_cancel(regdb); return werr; } vers_id = REGDB_VERSION_V2; } if (vers_id == REGDB_VERSION_V2) { DEBUG(10, ("regdb_init: upgrading registry from version %d " "to %d\n", REGDB_VERSION_V2, REGDB_VERSION_V3)); werr = regdb_upgrade_v2_to_v3(regdb); if (!W_ERROR_IS_OK(werr)) { dbwrap_transaction_cancel(regdb); return werr; } vers_id = REGDB_VERSION_V3; } /* future upgrade code should go here */ if (dbwrap_transaction_commit(regdb) != 0) { return WERR_REG_IO_FAILURE; } return WERR_OK; }
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; }
/* * write out the current fsrvp server state to a TDB. This clears any content * currently written to the TDB. */ _PRIVATE_ NTSTATUS fss_state_store(TALLOC_CTX *mem_ctx, struct fss_sc_set *sc_sets, uint32_t sc_sets_count, const char *db_path) { TALLOC_CTX *tmp_ctx; struct db_context *db; NTSTATUS status; int ret; struct fss_sc_set *sc_set; tmp_ctx = talloc_new(mem_ctx); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } db = db_open(tmp_ctx, db_path, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { DEBUG(0, ("Failed to open fss state database %s\n", db_path)); status = NT_STATUS_ACCESS_DENIED; goto err_ctx_free; } ret = dbwrap_wipe(db); if (ret != 0) { status = NT_STATUS_UNSUCCESSFUL; goto err_db_free; } status = dbwrap_store_int32_bystring(db, FSS_DB_KEY_VERSION, FSRVP_STATE_DB_VERSION); if (!NT_STATUS_IS_OK(status)) { goto err_db_free; } ret = dbwrap_transaction_start(db); if (ret != 0) { status = NT_STATUS_UNSUCCESSFUL; goto err_db_free; } status = dbwrap_store_int32_bystring(db, FSS_DB_KEY_SC_SET_COUNT, sc_sets_count); if (!NT_STATUS_IS_OK(status)) { status = NT_STATUS_UNSUCCESSFUL; goto err_trans_cancel; } for (sc_set = sc_sets; sc_set; sc_set = sc_set->next) { status = fss_state_sc_set_store(tmp_ctx, db, sc_set); if (!NT_STATUS_IS_OK(status)) { goto err_trans_cancel; } } ret = dbwrap_transaction_commit(db); if (ret != 0) { status = NT_STATUS_UNSUCCESSFUL; goto err_trans_cancel; } talloc_free(db); talloc_free(tmp_ctx); return NT_STATUS_OK; err_trans_cancel: dbwrap_transaction_cancel(db); err_db_free: talloc_free(db); err_ctx_free: talloc_free(tmp_ctx); return status; }