Esempio n. 1
0
/*
 * On rmdir we need to delete the tdb record
 */
static int posix_eadb_rmdir(vfs_handle_struct *handle, const char *path)
{
	NTSTATUS status;
	struct tdb_wrap *ea_tdb;
	int ret;

	SMB_VFS_HANDLE_GET_DATA(handle, ea_tdb, struct tdb_wrap, return -1);

	if (tdb_transaction_start(ea_tdb->tdb) != 0) {
		return -1;
	}

	status = unlink_posix_eadb_raw(ea_tdb, path, -1);
	if (!NT_STATUS_IS_OK(status)) {
		tdb_transaction_cancel(ea_tdb->tdb);
	}

	ret = SMB_VFS_NEXT_RMDIR(handle, path);

	if (ret == -1) {
		tdb_transaction_cancel(ea_tdb->tdb);
	} else {
		if (tdb_transaction_commit(ea_tdb->tdb) != 0) {
			return -1;
		}
	}

	return ret;
}
Esempio n. 2
0
/*
 * On unlink we need to delete the tdb record
 */
static int posix_eadb_unlink(vfs_handle_struct *handle,
			    const struct smb_filename *smb_fname)
{
	struct smb_filename *smb_fname_tmp = NULL;
	int ret = -1;

	struct tdb_wrap *ea_tdb;

	SMB_VFS_HANDLE_GET_DATA(handle, ea_tdb, struct tdb_wrap, return -1);

	smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
	if (smb_fname_tmp == NULL) {
		errno = ENOMEM;
		return -1;
	}

	if (lp_posix_pathnames()) {
		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp);
	} else {
		ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp);
	}
	if (ret == -1) {
		goto out;
	}

	if (smb_fname_tmp->st.st_ex_nlink == 1) {
		NTSTATUS status;

		/* Only remove record on last link to file. */

		if (tdb_transaction_start(ea_tdb->tdb) != 0) {
			ret = -1;
			goto out;
		}

		status = unlink_posix_eadb_raw(ea_tdb, smb_fname->base_name, -1);
		if (!NT_STATUS_IS_OK(status)) {
			tdb_transaction_cancel(ea_tdb->tdb);
			ret = -1;
			goto out;
		}
	}

	ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);

	if (ret == -1) {
		tdb_transaction_cancel(ea_tdb->tdb);
		goto out;
	} else {
		if (tdb_transaction_commit(ea_tdb->tdb) != 0) {
			ret = -1;
			goto out;
		}
	}

out:
	TALLOC_FREE(smb_fname_tmp);
	return ret;
}
Esempio n. 3
0
static int ltdb_del_trans(struct ldb_module *module)
{
	void *data = ldb_module_get_private(module);
	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);

	ltdb->in_transaction--;

	if (ltdb_index_transaction_cancel(module) != 0) {
		tdb_transaction_cancel(ltdb->tdb);
		return ltdb_err_map(tdb_error(ltdb->tdb));
	}

	tdb_transaction_cancel(ltdb->tdb);
	return LDB_SUCCESS;
}
Esempio n. 4
0
static int db_tdb_transaction_cancel(struct db_context *db)
{
	struct db_tdb_ctx *db_ctx =
		talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
	tdb_transaction_cancel(db_ctx->wtdb->tdb);
	return 0;
}
Esempio n. 5
0
/**
 * Close a database.
 *
 * @returns -1 for error; 0 for success.
 **/
int tdb_close(struct tdb_context *tdb)
{
	struct tdb_context **i;
	int ret = 0;

	if (tdb->transaction) {
		tdb_transaction_cancel(tdb);
	}

	if (tdb->map_ptr) {
		if (tdb->flags & TDB_INTERNAL)
			SAFE_FREE(tdb->map_ptr);
		else
			tdb_munmap(tdb);
	}
	SAFE_FREE(tdb->name);
	if (tdb->fd != -1)
		ret = close(tdb->fd);
	SAFE_FREE(tdb->locked);

	/* Remove from contexts list */
	for (i = &tdbs; *i; i = &(*i)->next) {
		if (*i == tdb) {
			*i = tdb->next;
			break;
		}
	}

	memset(tdb, 0, sizeof(*tdb));
	SAFE_FREE(tdb);

	return ret;
}
Esempio n. 6
0
static int do_child(int tdb_flags, int to, int from)
{
	struct tdb_context *tdb;
	unsigned int log_count;
	struct tdb_logging_context log_ctx = { log_fn, &log_count };
	int ret;
	char c = 0;

	tdb = tdb_open_ex("mutex-transaction1.tdb", 3, tdb_flags,
			  O_RDWR|O_CREAT, 0755, &log_ctx, NULL);
	ok(tdb, "tdb_open_ex should succeed");

	ret = tdb_transaction_start(tdb);
	ok(ret == 0, "tdb_transaction_start should succeed");

	ret = tdb_store(tdb, key, data, TDB_INSERT);
	ok(ret == 0, "tdb_store(tdb, key, data, TDB_INSERT) should succeed");

	write(to, &c, sizeof(c));
	read(from, &c, sizeof(c));

	ret = tdb_transaction_cancel(tdb);
	ok(ret == 0, "tdb_transaction_cancel should succeed");

	write(to, &c, sizeof(c));
	read(from, &c, sizeof(c));

	ret = tdb_transaction_start(tdb);
	ok(ret == 0, "tdb_transaction_start should succeed");

	ret = tdb_store(tdb, key, data, TDB_INSERT);
	ok(ret == 0, "tdb_store(tdb, key, data, TDB_INSERT) should succeed");

	write(to, &c, sizeof(c));
	read(from, &c, sizeof(c));

	ret = tdb_transaction_commit(tdb);
	ok(ret == 0, "tdb_transaction_commit should succeed");

	write(to, &c, sizeof(c));
	read(from, &c, sizeof(c));

	ret = tdb_transaction_start(tdb);
	ok(ret == 0, "tdb_transaction_start should succeed");

	ret = tdb_store(tdb, key, key, TDB_REPLACE);
	ok(ret == 0, "tdb_store(tdb, key, data, TDB_REPLACE) should succeed");

	write(to, &c, sizeof(c));
	read(from, &c, sizeof(c));

	ret = tdb_transaction_commit(tdb);
	ok(ret == 0, "tdb_transaction_commit should succeed");

	write(to, &c, sizeof(c));
	read(from, &c, sizeof(c));

	return 0;
}
Esempio n. 7
0
static int run_child(int i, int seed, unsigned num_loops, unsigned start,
		     int tdb_flags)
{
	struct sigaction act = { .sa_sigaction = segv_handler,
				 .sa_flags = SA_SIGINFO };
	sigaction(11, &act, NULL);	

	db = tdb_open("torture.tdb", tdb_flags, O_RDWR | O_CREAT, 0600,
		      &log_attr);
	if (!db) {
		fatal(NULL, "db open failed");
	}

#if 0
	if (i == 0) {
		printf("pid %i\n", getpid());
		sleep(9);
	} else
		sleep(10);
#endif

	srand(seed + i);
	srandom(seed + i);

	/* Set global, then we're ready to handle being killed. */
	loopnum = start;
	signal(SIGUSR1, send_count_and_suicide);

	for (;loopnum<num_loops && error_count == 0;loopnum++) {
		addrec_db();
	}

	if (error_count == 0) {
		tdb_traverse(db, NULL, NULL);
#if TRANSACTION_PROB
		if (always_transaction) {
			while (in_transaction) {
				tdb_transaction_cancel(db);
				in_transaction--;
			}
			if (tdb_transaction_start(db) != 0)
				fatal(db, "tdb_transaction_start failed");
		}
#endif
		tdb_traverse(db, traverse_fn, NULL);
		tdb_traverse(db, traverse_fn, NULL);

#if TRANSACTION_PROB
		if (always_transaction) {
			if (tdb_transaction_commit(db) != 0)
				fatal(db, "tdb_transaction_commit failed");
		}
#endif
	}

	tdb_close(db);

	return (error_count < 100 ? error_count : 100);
}
Esempio n. 8
0
static PyObject *obj_transaction_cancel(PyTdbObject *self)
{
	int ret;

	PyErr_TDB_RAISE_IF_CLOSED(self);

	ret = tdb_transaction_cancel(self->ctx);
	PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
	Py_RETURN_NONE;
}
Esempio n. 9
0
enum TDB_ERROR tdb_repack(struct tdb_context *tdb)
{
	struct tdb_context *tmp_db;
	struct traverse_state state;

	state.error = tdb_transaction_start(tdb);
	if (state.error != TDB_SUCCESS) {
		return state.error;
	}

	tmp_db = tdb_open("tmpdb", TDB_INTERNAL, O_RDWR|O_CREAT, 0, NULL);
	if (tmp_db == NULL) {
		state.error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
					 __location__
					 " Failed to create tmp_db");
		tdb_transaction_cancel(tdb);
		return tdb->last_error = state.error;
	}

	state.dest_db = tmp_db;
	if (tdb_traverse(tdb, repack_traverse, &state) < 0) {
		goto fail;
	}

	state.error = tdb_wipe_all(tdb);
	if (state.error != TDB_SUCCESS) {
		goto fail;
	}

	state.dest_db = tdb;
	if (tdb_traverse(tmp_db, repack_traverse, &state) < 0) {
		goto fail;
	}

	tdb_close(tmp_db);
	return tdb_transaction_commit(tdb);

fail:
	tdb_transaction_cancel(tdb);
	tdb_close(tmp_db);
	return state.error;
}
Esempio n. 10
0
/**
 * Cancel a transaction on database
 */
static int db_transaction_cancel_handler(struct ctdb_db_context *ctdb_db,
        void *private_data)
{
    int ret;

    tdb_add_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
    ret = tdb_transaction_cancel(ctdb_db->ltdb->tdb);
    if (ret != 0) {
        DEBUG(DEBUG_ERR, ("Failed to cancel transaction for db %s\n",
                          ctdb_db->db_name));
    }
    tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
    return 0;
}
static int run_child(const char *filename, int i, int seed, unsigned num_loops, unsigned start)
{
	db = tdb_open_ex(filename, hash_size, TDB_DEFAULT,
			 O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
	if (!db) {
		fatal("db open failed");
	}

	srand(seed + i);
	srandom(seed + i);

	/* Set global, then we're ready to handle being killed. */
	loopnum = start;
	signal(SIGUSR1, send_count_and_suicide);

	for (;loopnum<num_loops && error_count == 0;loopnum++) {
		addrec_db();
	}

	if (error_count == 0) {
		tdb_traverse_read(db, NULL, NULL);
		if (always_transaction) {
			while (in_transaction) {
				tdb_transaction_cancel(db);
				in_transaction--;
			}
			if (tdb_transaction_start(db) != 0)
				fatal("tdb_transaction_start failed");
		}
		tdb_traverse(db, traverse_fn, NULL);
		tdb_traverse(db, traverse_fn, NULL);
		if (always_transaction) {
			if (tdb_transaction_commit(db) != 0)
				fatal("tdb_transaction_commit failed");
		}
	}

	tdb_close(db);

	return (error_count < 100 ? error_count : 100);
}
Esempio n. 12
0
/*
 * Transaction delete
 */
int partition_metadata_del_trans(struct ldb_module *module)
{
	struct partition_private_data *data;
	struct tdb_context *tdb;

	data = talloc_get_type_abort(ldb_module_get_private(module),
				     struct partition_private_data);
	if (!data || !data->metadata || !data->metadata->db) {
		return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
					"partition_metadata: metadata not initialized");
	}
	tdb = data->metadata->db->tdb;

	if (data->metadata->in_transaction == 0) {
		return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
					"partition_metadata: not in transaction");
	}

	data->metadata->in_transaction--;

	tdb_transaction_cancel(tdb);

	return LDB_SUCCESS;
}
Esempio n. 13
0
static int ltdb_prepare_commit(struct ldb_module *module)
{
	void *data = ldb_module_get_private(module);
	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);

	if (ltdb->in_transaction != 1) {
		return LDB_SUCCESS;
	}

	if (ltdb_index_transaction_commit(module) != 0) {
		tdb_transaction_cancel(ltdb->tdb);
		ltdb->in_transaction--;
		return ltdb_err_map(tdb_error(ltdb->tdb));
	}

	if (tdb_transaction_prepare_commit(ltdb->tdb) != 0) {
		ltdb->in_transaction--;
		return ltdb_err_map(tdb_error(ltdb->tdb));
	}

	ltdb->prepared_commit = true;

	return LDB_SUCCESS;
}
Esempio n. 14
0
/**
 * Start a transaction on database
 */
static int db_transaction_start_handler(struct ctdb_db_context *ctdb_db,
                                        void *private_data)
{
    bool freeze_transaction_started = *(bool *)private_data;
    int ret;

    tdb_add_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
    if (freeze_transaction_started) {
        ret = tdb_transaction_cancel(ctdb_db->ltdb->tdb);
        if (ret != 0) {
            DEBUG(DEBUG_ERR,
                  ("Failed to cancel transaction for db %s\n",
                   ctdb_db->db_name));
        }
    }
    ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
    tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK);
    if (ret != 0) {
        DEBUG(DEBUG_ERR, ("Failed to start transaction for db %s\n",
                          ctdb_db->db_name));
        return -1;
    }
    return 0;
}
Esempio n. 15
0
static int do_command(void)
{
	COMMAND_TABLE *ctp = cmd_table;
	enum commands mycmd = CMD_HELP;
	int cmd_len;

	if (cmdname && strlen(cmdname) == 0) {
		mycmd = CMD_NEXT;
	} else {
		while (ctp->name) {
			cmd_len = strlen(ctp->name);
			if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
				mycmd = ctp->cmd;
				break;
			}
			ctp++;
		}
	}

	switch (mycmd) {
	case CMD_CREATE_TDB:
		bIterate = 0;
		create_tdb(arg1);
		return 0;
	case CMD_OPEN_TDB:
		bIterate = 0;
		open_tdb(arg1);
		return 0;
	case CMD_SYSTEM:
		/* Shell command */
		if (system(arg1) == -1) {
			terror("system() call failed\n");
		}
		return 0;
	case CMD_QUIT:
		return 1;
	default:
		/* all the rest require a open database */
		if (!tdb) {
			bIterate = 0;
			terror("database not open");
			help();
			return 0;
		}
		switch (mycmd) {
		case CMD_TRANSACTION_START:
			bIterate = 0;
			tdb_transaction_start(tdb);
			return 0;
		case CMD_TRANSACTION_COMMIT:
			bIterate = 0;
			tdb_transaction_commit(tdb);
			return 0;
		case CMD_REPACK:
			bIterate = 0;
			tdb_repack(tdb);
			return 0;
		case CMD_TRANSACTION_CANCEL:
			bIterate = 0;
			tdb_transaction_cancel(tdb);
			return 0;
		case CMD_ERASE:
			bIterate = 0;
			tdb_traverse(tdb, do_delete_fn, NULL);
			return 0;
		case CMD_DUMP:
			bIterate = 0;
			tdb_traverse(tdb, print_rec, NULL);
			return 0;
		case CMD_INSERT:
			bIterate = 0;
			insert_tdb(arg1, arg1len,arg2,arg2len);
			return 0;
		case CMD_MOVE:
			bIterate = 0;
			move_rec(arg1,arg1len,arg2);
			return 0;
		case CMD_STORE:
			bIterate = 0;
			store_tdb(arg1,arg1len,arg2,arg2len);
			return 0;
		case CMD_SHOW:
			bIterate = 0;
			show_tdb(arg1, arg1len);
			return 0;
		case CMD_KEYS:
			tdb_traverse(tdb, print_key, NULL);
			return 0;
		case CMD_HEXKEYS:
			tdb_traverse(tdb, print_hexkey, NULL);
			return 0;
		case CMD_DELETE:
			bIterate = 0;
			delete_tdb(arg1,arg1len);
			return 0;
		case CMD_LIST_HASH_FREE:
			tdb_dump_all(tdb);
			return 0;
		case CMD_LIST_FREE:
			tdb_printfreelist(tdb);
			return 0;
		case CMD_FREELIST_SIZE: {
			int size;

			size = tdb_freelist_size(tdb);
			if (size < 0) {
				printf("Error getting freelist size.\n");
			} else {
				printf("freelist size: %d\n", size);
			}

			return 0;
		}
		case CMD_INFO:
			info_tdb();
			return 0;
		case CMD_SPEED:
			speed_tdb(arg1);
			return 0;
		case CMD_MMAP:
			toggle_mmap();
			return 0;
		case CMD_FIRST:
			bIterate = 1;
			first_record(tdb, &iterate_kbuf);
			return 0;
		case CMD_NEXT:
			if (bIterate)
				next_record(tdb, &iterate_kbuf);
			return 0;
		case CMD_CHECK:
			check_db(tdb);
			return 0;
		case CMD_HELP:
			help();
			return 0;
		case CMD_CREATE_TDB:
		case CMD_OPEN_TDB:
		case CMD_SYSTEM:
		case CMD_QUIT:
			/*
			 * unhandled commands.  cases included here to avoid compiler
			 * warnings.
			 */
			return 0;
		}
	}

	return 0;
}
Esempio n. 16
0
int main(int argc, char *argv[])
{
	struct tdb_context *tdb;
	TDB_DATA key, data;

	plan_tests(27);
	key.dsize = strlen("hi");
	key.dptr = (void *)"hi";

	tdb = tdb_open_ex("run-nested-transactions.tdb",
			  1024, TDB_CLEAR_IF_FIRST|TDB_DISALLOW_NESTING,
			  O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
	ok1(tdb);

	/* Nesting disallowed. */
	ok1(tdb_transaction_start(tdb) == 0);
	data.dptr = (void *)"world";
	data.dsize = strlen("world");
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	data = tdb_fetch(tdb, key);
	ok1(data.dsize == strlen("world"));
	ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
	free(data.dptr);
	ok1(tdb_transaction_start(tdb) != 0);
	ok1(tdb_error(tdb) == TDB_ERR_NESTING);

	data = tdb_fetch(tdb, key);
	ok1(data.dsize == strlen("world"));
	ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
	free(data.dptr);
	ok1(tdb_transaction_commit(tdb) == 0);
	data = tdb_fetch(tdb, key);
	ok1(data.dsize == strlen("world"));
	ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
	free(data.dptr);
	tdb_close(tdb);

	/* Nesting allowed by default */
	tdb = tdb_open_ex("run-nested-transactions.tdb",
			  1024, TDB_DEFAULT, O_RDWR, 0, &taplogctx, NULL);
	ok1(tdb);

	ok1(tdb_transaction_start(tdb) == 0);
	ok1(tdb_transaction_start(tdb) == 0);
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_transaction_commit(tdb) == 0);
	ok1(!tdb_exists(tdb, key));
	ok1(tdb_transaction_cancel(tdb) == 0);
	/* Surprise! Kills inner "committed" transaction. */
	ok1(tdb_exists(tdb, key));

	ok1(tdb_transaction_start(tdb) == 0);
	ok1(tdb_transaction_start(tdb) == 0);
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_transaction_commit(tdb) == 0);
	ok1(!tdb_exists(tdb, key));
	ok1(tdb_transaction_commit(tdb) == 0);
	ok1(!tdb_exists(tdb, key));
	tdb_close(tdb);

	return exit_status();
}
Esempio n. 17
0
/* The code should barf on TDBs created with rwlocks. */
int main(int argc, char *argv[])
{
	struct tdb_context *tdb;
	unsigned int log_count;
	struct tdb_logging_context log_ctx = { log_fn, &log_count };
	int ret, status;
	pid_t child, wait_ret;
	int fromchild[2];
	int tochild[2];
	TDB_DATA val;
	char c;
	int tdb_flags;
	bool runtime_support;

	runtime_support = tdb_runtime_check_for_robust_mutexes();

	if (!runtime_support) {
		skip(1, "No robust mutex support");
		return exit_status();
	}

	key.dsize = strlen("hi");
	key.dptr = discard_const_p(uint8_t, "hi");
	data.dsize = strlen("world");
	data.dptr = discard_const_p(uint8_t, "world");

	pipe(fromchild);
	pipe(tochild);

	tdb_flags = TDB_INCOMPATIBLE_HASH|
		TDB_MUTEX_LOCKING|
		TDB_CLEAR_IF_FIRST;

	child = fork();
	if (child == 0) {
		close(fromchild[0]);
		close(tochild[1]);
		return do_child(tdb_flags, fromchild[1], tochild[0]);
	}
	close(fromchild[1]);
	close(tochild[0]);

	read(fromchild[0], &c, sizeof(c));

	tdb = tdb_open_ex("mutex-transaction1.tdb", 0,
			  tdb_flags, O_RDWR|O_CREAT, 0755,
			  &log_ctx, NULL);
	ok(tdb, "tdb_open_ex should succeed");

	/*
	 * The child has the transaction running
	 */
	ret = tdb_transaction_start_nonblock(tdb);
	ok(ret == -1, "tdb_transaction_start_nonblock not succeed");

	ret = tdb_chainlock_nonblock(tdb, key);
	ok(ret == -1, "tdb_chainlock_nonblock should not succeed");

	/*
	 * We can still read
	 */
	ret = tdb_exists(tdb, key);
	ok(ret == 0, "tdb_exists(tdb, key) should return 0");

	val = tdb_fetch(tdb, key);
	ok(val.dsize == 0, "tdb_fetch(tdb, key) should return an empty value");

	write(tochild[1], &c, sizeof(c));

	/*
	 * When the child canceled we can start...
	 */
	ret = tdb_transaction_start(tdb);
	ok(ret == 0, "tdb_transaction_start should succeed");

	read(fromchild[0], &c, sizeof(c));
	write(tochild[1], &c, sizeof(c));

	ret = tdb_transaction_cancel(tdb);
	ok(ret == 0, "tdb_transaction_cancel should succeed");

	/*
	 * When we canceled the child can start and store...
	 */
	read(fromchild[0], &c, sizeof(c));

	/*
	 * We still see the old values before the child commits...
	 */
	ret = tdb_exists(tdb, key);
	ok(ret == 0, "tdb_exists(tdb, key) should return 0");

	val = tdb_fetch(tdb, key);
	ok(val.dsize == 0, "tdb_fetch(tdb, key) should return an empty value");

	write(tochild[1], &c, sizeof(c));
	read(fromchild[0], &c, sizeof(c));

	/*
	 * We see the new values after the commit...
	 */
	ret = tdb_exists(tdb, key);
	ok(ret == 1, "tdb_exists(tdb, key) should return 1");

	val = tdb_fetch(tdb, key);
	ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value");
	ok(val.dsize == data.dsize, "tdb_fetch(tdb, key) should return a value");
	ok(memcmp(val.dptr, data.dptr, data.dsize) == 0, "tdb_fetch(tdb, key) should return a value");

	write(tochild[1], &c, sizeof(c));
	read(fromchild[0], &c, sizeof(c));

	/*
	 * The child started a new transaction and replaces the value,
	 * but we still see the old values before the child commits...
	 */
	ret = tdb_exists(tdb, key);
	ok(ret == 1, "tdb_exists(tdb, key) should return 1");

	val = tdb_fetch(tdb, key);
	ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value");
	ok(val.dsize == data.dsize, "tdb_fetch(tdb, key) should return a value");
	ok(memcmp(val.dptr, data.dptr, data.dsize) == 0, "tdb_fetch(tdb, key) should return a value");

	write(tochild[1], &c, sizeof(c));
	read(fromchild[0], &c, sizeof(c));

	/*
	 * We see the new values after the commit...
	 */
	ret = tdb_exists(tdb, key);
	ok(ret == 1, "tdb_exists(tdb, key) should return 1");

	val = tdb_fetch(tdb, key);
	ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value");
	ok(val.dsize == key.dsize, "tdb_fetch(tdb, key) should return a value");
	ok(memcmp(val.dptr, key.dptr, key.dsize) == 0, "tdb_fetch(tdb, key) should return a value");

	write(tochild[1], &c, sizeof(c));

	wait_ret = wait(&status);
	ok(wait_ret == child, "child should have exited correctly");

	diag("done");
	return exit_status();
}
static void addrec_db(void)
{
	int klen, dlen;
	char *k, *d;
	TDB_DATA key, data;

	klen = 1 + (rand() % KEYLEN);
	dlen = 1 + (rand() % DATALEN);

	k = randbuf(klen);
	d = randbuf(dlen);

	key.dptr = (unsigned char *)k;
	key.dsize = klen+1;

	data.dptr = (unsigned char *)d;
	data.dsize = dlen+1;

#if REOPEN_PROB
	if (in_transaction == 0 && random() % REOPEN_PROB == 0) {
		tdb_reopen_all(0);
		goto next;
	}
#endif

#if TRANSACTION_PROB
	if (in_transaction == 0 &&
	    (always_transaction || random() % TRANSACTION_PROB == 0)) {
		if (tdb_transaction_start(db) != 0) {
			fatal("tdb_transaction_start failed");
		}
		in_transaction++;
		goto next;
	}
	if (in_transaction && random() % TRANSACTION_PROB == 0) {
		if (random() % TRANSACTION_PREPARE_PROB == 0) {
			if (tdb_transaction_prepare_commit(db) != 0) {
				fatal("tdb_transaction_prepare_commit failed");
			}
		}
		if (tdb_transaction_commit(db) != 0) {
			fatal("tdb_transaction_commit failed");
		}
		in_transaction--;
		goto next;
	}
	if (in_transaction && random() % TRANSACTION_PROB == 0) {
		if (tdb_transaction_cancel(db) != 0) {
			fatal("tdb_transaction_cancel failed");
		}
		in_transaction--;
		goto next;
	}
#endif

#if DELETE_PROB
	if (random() % DELETE_PROB == 0) {
		tdb_delete(db, key);
		goto next;
	}
#endif

#if STORE_PROB
	if (random() % STORE_PROB == 0) {
		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
			fatal("tdb_store failed");
		}
		goto next;
	}
#endif

#if APPEND_PROB
	if (random() % APPEND_PROB == 0) {
		if (tdb_append(db, key, data) != 0) {
			fatal("tdb_append failed");
		}
		goto next;
	}
#endif

#if LOCKSTORE_PROB
	if (random() % LOCKSTORE_PROB == 0) {
		tdb_chainlock(db, key);
		data = tdb_fetch(db, key);
		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
			fatal("tdb_store failed");
		}
		if (data.dptr) free(data.dptr);
		tdb_chainunlock(db, key);
		goto next;
	} 
#endif

#if TRAVERSE_PROB
	if (random() % TRAVERSE_PROB == 0) {
		tdb_traverse(db, cull_traverse, NULL);
		goto next;
	}
#endif

#if TRAVERSE_READ_PROB
	if (random() % TRAVERSE_READ_PROB == 0) {
		tdb_traverse_read(db, NULL, NULL);
		goto next;
	}
#endif

	data = tdb_fetch(db, key);
	if (data.dptr) free(data.dptr);

next:
	free(k);
	free(d);
}
Esempio n. 19
0
static errcode_t undo_write_tdb(io_channel channel,
				unsigned long long block, int count)

{
	int size, sz;
	unsigned long long block_num, backing_blk_num;
	errcode_t retval = 0;
	ext2_loff_t offset;
	struct undo_private_data *data;
	TDB_DATA tdb_key, tdb_data;
	unsigned char *read_ptr;
	unsigned long long end_block;

	data = (struct undo_private_data *) channel->private_data;

	if (data->tdb == NULL) {
		/*
		 * Transaction database not initialized
		 */
		return 0;
	}

	if (count == 1)
		size = channel->block_size;
	else {
		if (count < 0)
			size = -count;
		else
			size = count * channel->block_size;
	}
	/*
	 * Data is stored in tdb database as blocks of tdb_data_size size
	 * This helps in efficient lookup further.
	 *
	 * We divide the disk to blocks of tdb_data_size.
	 */
	offset = (block * channel->block_size) + data->offset ;
	block_num = offset / data->tdb_data_size;
	end_block = (offset + size) / data->tdb_data_size;

	tdb_transaction_start(data->tdb);
	while (block_num <= end_block ) {

		tdb_key.dptr = (unsigned char *)&block_num;
		tdb_key.dsize = sizeof(block_num);
		/*
		 * Check if we have the record already
		 */
		if (tdb_exists(data->tdb, tdb_key)) {
			/* Try the next block */
			block_num++;
			continue;
		}
		/*
		 * Read one block using the backing I/O manager
		 * The backing I/O manager block size may be
		 * different from the tdb_data_size.
		 * Also we need to recalcuate the block number with respect
		 * to the backing I/O manager.
		 */
		offset = block_num * data->tdb_data_size;
		backing_blk_num = (offset - data->offset) / channel->block_size;

		count = data->tdb_data_size +
				((offset - data->offset) % channel->block_size);
		retval = ext2fs_get_mem(count, &read_ptr);
		if (retval) {
			tdb_transaction_cancel(data->tdb);
			return retval;
		}

		memset(read_ptr, 0, count);
		actual_size = 0;
		if ((count % channel->block_size) == 0)
			sz = count / channel->block_size;
		else
			sz = -count;
		retval = io_channel_read_blk64(data->real, backing_blk_num,
					     sz, read_ptr);
		if (retval) {
			if (retval != EXT2_ET_SHORT_READ) {
				free(read_ptr);
				tdb_transaction_cancel(data->tdb);
				return retval;
			}
			/*
			 * short read so update the record size
			 * accordingly
			 */
			tdb_data.dsize = actual_size;
		} else {
			tdb_data.dsize = data->tdb_data_size;
		}
		tdb_data.dptr = read_ptr +
				((offset - data->offset) % channel->block_size);
#ifdef DEBUG
		printf("Printing with key %lld data %x and size %d\n",
		       block_num,
		       tdb_data.dptr,
		       tdb_data.dsize);
#endif
		if (!data->tdb_written) {
			data->tdb_written = 1;
			/* Write the blocksize to tdb file */
			retval = write_block_size(data->tdb,
						  data->tdb_data_size);
			if (retval) {
				tdb_transaction_cancel(data->tdb);
				retval = EXT2_ET_TDB_ERR_IO;
				free(read_ptr);
				return retval;
			}
		}
		retval = tdb_store(data->tdb, tdb_key, tdb_data, TDB_INSERT);
		if (retval == -1) {
			/*
			 * TDB_ERR_EXISTS cannot happen because we
			 * have already verified it doesn't exist
			 */
			tdb_transaction_cancel(data->tdb);
			retval = EXT2_ET_TDB_ERR_IO;
			free(read_ptr);
			return retval;
		}
		free(read_ptr);
		/* Next block */
		block_num++;
	}
	tdb_transaction_commit(data->tdb);

	return retval;
}
Esempio n. 20
0
NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
				    struct loadparm_context *lp_ctx,
				    const char *computer_name,
				    struct netr_Authenticator *received_authenticator,
				    struct netr_Authenticator *return_authenticator,
				    struct netlogon_creds_CredentialState **creds_out)
{
	TALLOC_CTX *tmpctx;
	struct tdb_wrap *tdb_sc;
	struct netlogon_creds_CredentialState *creds;
	NTSTATUS status;
	int ret;

	tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state");
	if (!tmpctx) {
		return NT_STATUS_NO_MEMORY;
	}

	tdb_sc = open_schannel_session_store(tmpctx, lp_ctx);
	if (!tdb_sc) {
		status = NT_STATUS_ACCESS_DENIED;
		goto done;
	}

	ret = tdb_transaction_start(tdb_sc->tdb);
	if (ret != 0) {
		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
		goto done;
	}

	/* Because this is a shared structure (even across
	 * disconnects) we must update the database every time we
	 * update the structure */

	status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx, 
						computer_name, &creds);
	if (!NT_STATUS_IS_OK(status)) {
		tdb_transaction_cancel(tdb_sc->tdb);
		goto done;
	}

	status = netlogon_creds_server_step_check(creds,
						  received_authenticator,
						  return_authenticator);
	if (!NT_STATUS_IS_OK(status)) {
		tdb_transaction_cancel(tdb_sc->tdb);
		goto done;
	}

	status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds);
	if (!NT_STATUS_IS_OK(status)) {
		tdb_transaction_cancel(tdb_sc->tdb);
		goto done;
	}

	tdb_transaction_commit(tdb_sc->tdb);

	if (creds_out) {
		*creds_out = talloc_steal(mem_ctx, creds);
		if (!*creds_out) {
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}
	}

	status = NT_STATUS_OK;

done:
	talloc_free(tmpctx);
	return status;
}
Esempio n. 21
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	unsigned char *buffer;
	int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
			TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT };
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data;

	buffer = malloc(1000);
	for (i = 0; i < 1000; i++)
		buffer[i] = i;

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 20 + 1);

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		tdb = tdb_open("run-55-transaction.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		ok1(tdb_transaction_start(tdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		/* Cancelling a transaction means no store */
		tdb_transaction_cancel(tdb);
		ok1(tdb->file->allrecord_lock.count == 0
		    && tdb->file->num_lockrecs == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_ERR_NOEXIST);

		/* Commit the transaction. */
		ok1(tdb_transaction_start(tdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);
		ok1(tdb_transaction_commit(tdb) == 0);
		ok1(tdb->file->allrecord_lock.count == 0
		    && tdb->file->num_lockrecs == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	free(buffer);
	return exit_status();
}
Esempio n. 22
0
static BOOL init_registry_data( void )
{
	pstring path, base, remaining;
	fstring keyname, subkeyname;
	REGSUBKEY_CTR *subkeys;
	REGVAL_CTR *values;
	int i;
	const char *p, *p2;
	UNISTR2 data;

	/*
	 * There are potentially quite a few store operations which are all
	 * indiviually wrapped in tdb transactions. Wrapping them in a single
	 * transaction gives just a single transaction_commit() to actually do
	 * its fsync()s. See tdb/common/transaction.c for info about nested
	 * transaction behaviour.
	 */

	if ( tdb_transaction_start( tdb_reg ) == -1 ) {
		DEBUG(0, ("init_registry_data: tdb_transaction_start "
			  "failed\n"));
		return False;
	}
	
	/* loop over all of the predefined paths and add each component */
	
	for ( i=0; builtin_registry_paths[i] != NULL; i++ ) {

		DEBUG(6,("init_registry_data: Adding [%s]\n", builtin_registry_paths[i]));

		pstrcpy( path, builtin_registry_paths[i] );
		pstrcpy( base, "" );
		p = path;
		
		while ( next_token(&p, keyname, "\\", sizeof(keyname)) ) {
		
			/* build up the registry path from the components */
			
			if ( *base )
				pstrcat( base, "\\" );
			pstrcat( base, keyname );
			
			/* get the immediate subkeyname (if we have one ) */
			
			*subkeyname = '\0';
			if ( *p ) {
				pstrcpy( remaining, p );
				p2 = remaining;
				
				if ( !next_token(&p2, subkeyname, "\\", sizeof(subkeyname)) )
					fstrcpy( subkeyname, p2 );
			}

			DEBUG(10,("init_registry_data: Storing key [%s] with subkey [%s]\n",
				base, *subkeyname ? subkeyname : "NULL"));
			
			/* we don't really care if the lookup succeeds or not since
			   we are about to update the record.  We just want any 
			   subkeys already present */
			
			if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
				DEBUG(0,("talloc() failure!\n"));
				goto fail;
			}

			regdb_fetch_keys( base, subkeys );
			if ( *subkeyname ) 
				regsubkey_ctr_addkey( subkeys, subkeyname );
			if ( !regdb_store_keys( base, subkeys ))
				goto fail;
			
			TALLOC_FREE( subkeys );
		}
	}

	/* loop over all of the predefined values and add each component */
	
	for ( i=0; builtin_registry_values[i].path != NULL; i++ ) {
		if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
			DEBUG(0,("talloc() failure!\n"));
			goto fail;
		}

		regdb_fetch_values( builtin_registry_values[i].path, values );

		/* preserve existing values across restarts.  Only add new ones */

		if ( !regval_ctr_key_exists( values, builtin_registry_values[i].valuename ) ) 
		{
			switch( builtin_registry_values[i].type ) {
			case REG_DWORD:
				regval_ctr_addvalue( values, 
				                     builtin_registry_values[i].valuename,
						     REG_DWORD,
						     (char*)&builtin_registry_values[i].data.dw_value,
						     sizeof(uint32) );
				break;
				
			case REG_SZ:
				init_unistr2( &data, builtin_registry_values[i].data.string, UNI_STR_TERMINATE);
				regval_ctr_addvalue( values, 
				                     builtin_registry_values[i].valuename,
						     REG_SZ,
						     (char*)data.buffer,
						     data.uni_str_len*sizeof(uint16) );
				break;
			
			default:
				DEBUG(0,("init_registry_data: invalid value type in builtin_registry_values [%d]\n",
					builtin_registry_values[i].type));
			}
			regdb_store_values( builtin_registry_values[i].path, values );
		}
		
		TALLOC_FREE( values );
	}
	
	if (tdb_transaction_commit( tdb_reg ) == -1) {
		DEBUG(0, ("init_registry_data: Could not commit "
			  "transaction\n"));
		return False;
	}

	return True;

 fail:

	if (tdb_transaction_cancel( tdb_reg ) == -1) {
		smb_panic("init_registry_data: tdb_transaction_cancel "
			  "failed\n");
	}

	return False;
}