예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
/**
 * 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;
}
예제 #7
0
파일: serverid.c 프로젝트: Gazzonyx/samba
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);
}
예제 #8
0
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;
}
예제 #9
0
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;
}
예제 #10
0
파일: pdb_tdb.c 프로젝트: Alexander--/samba
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;
}
예제 #11
0
파일: pdb_tdb.c 프로젝트: Alexander--/samba
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;
}
예제 #12
0
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;
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
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;
}