Example #1
0
static struct tdb_context *tdb_open_cloexec(
        const char *name,
        int hash_size,
        int tdb_flags,
        int open_flags,
        mode_t mode) {

    /* Mimics pa_open_cloexec() */

    struct tdb_context *c;

#ifdef O_NOCTTY
    open_flags |= O_NOCTTY;
#endif

#ifdef O_CLOEXEC
    errno = 0;
    if ((c = tdb_open(name, hash_size, tdb_flags, open_flags | O_CLOEXEC, mode)))
        goto finish;

    if (errno != EINVAL)
        return NULL;
#endif

    errno = 0;
    if (!(c = tdb_open(name, hash_size, tdb_flags, open_flags, mode)))
        return NULL;

finish:
    pa_make_fd_cloexec(tdb_fd(c));
    return c;
}
Example #2
0
/*
  wrapped connection to a tdb database. The caller should _not_ free
  this as it is not a talloc structure (as tdb does not use talloc
  yet). It will auto-close when the caller frees the mem_ctx that is
  passed to this call
 */
struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx,
				   const char *path, int hash_size, 
				   int tdb_flags,
				   int open_flags, mode_t mode, 
				   struct ldb_context *ldb)
{
	struct ltdb_wrap *w;
	struct stat st;
	struct tdb_logging_context log_ctx;

	log_ctx.log_fn = ltdb_log_fn;
	log_ctx.log_private = ldb;

	if (stat(path, &st) == 0) {
		for (w=tdb_list;w;w=w->next) {
			if (st.st_dev == w->device && st.st_ino == w->inode) {
				if (!talloc_reference(mem_ctx, w)) {
					return NULL;
				}
				return w->tdb;
			}
		}
	}

	w = talloc(mem_ctx, struct ltdb_wrap);
	if (w == NULL) {
		return NULL;
	}

	w->tdb = tdb_open_ex(path, hash_size, tdb_flags, open_flags, mode, &log_ctx, NULL);
	if (w->tdb == NULL) {
		talloc_free(w);
		return NULL;
	}

	if (fstat(tdb_fd(w->tdb), &st) != 0) {
		tdb_close(w->tdb);
		talloc_free(w);
		return NULL;
	}

	w->device = st.st_dev;
	w->inode  = st.st_ino;

	talloc_set_destructor(w, ltdb_wrap_destructor);

	DLIST_ADD(tdb_list, w);
	
	return w->tdb;
}
Example #3
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT };

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

		if (flags[i] & TDB_INTERNAL)
			ok1(tdb_fd(tdb) == -1);
		else
			ok1(tdb_fd(tdb) > 2);
		tdb_close(tdb);
		ok1(tap_log_messages == 0);
	}
	return exit_status();
}
Example #4
0
/*
  carefully backup a tdb, validating the contents and
  only doing the backup if its OK
  this function is also used for restore
*/
static int backup_tdb(const char *old_name, const char *new_name,
                      int hash_size, int nolock)
{
    TDB_CONTEXT *tdb;
    TDB_CONTEXT *tdb_new;
    char *tmp_name;
    struct stat st;
    int count1, count2;

    tmp_name = add_suffix(new_name, ".tmp");

    /* stat the old tdb to find its permissions */
    if (stat(old_name, &st) != 0) {
        perror(old_name);
        free(tmp_name);
        return 1;
    }

    /* open the old tdb */
    tdb = tdb_open_ex(old_name, 0,
                      TDB_DEFAULT | (nolock ? TDB_NOLOCK : 0),
                      O_RDWR, 0, &log_ctx, NULL);
    if (!tdb) {
        printf("Failed to open %s\n", old_name);
        free(tmp_name);
        return 1;
    }

    /* create the new tdb */
    unlink(tmp_name);
    tdb_new = tdb_open_ex(tmp_name,
                          hash_size ? hash_size : tdb_hash_size(tdb),
                          TDB_DEFAULT,
                          O_RDWR|O_CREAT|O_EXCL, st.st_mode & 0777,
                          &log_ctx, NULL);
    if (!tdb_new) {
        perror(tmp_name);
        free(tmp_name);
        return 1;
    }

    if (tdb_transaction_start(tdb) != 0) {
        printf("Failed to start transaction on old tdb\n");
        tdb_close(tdb);
        tdb_close(tdb_new);
        unlink(tmp_name);
        free(tmp_name);
        return 1;
    }

    /* lock the backup tdb so that nobody else can change it */
    if (tdb_lockall(tdb_new) != 0) {
        printf("Failed to lock backup tdb\n");
        tdb_close(tdb);
        tdb_close(tdb_new);
        unlink(tmp_name);
        free(tmp_name);
        return 1;
    }

    failed = 0;

    /* traverse and copy */
    count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new);
    if (count1 < 0 || failed) {
        fprintf(stderr,"failed to copy %s\n", old_name);
        tdb_close(tdb);
        tdb_close(tdb_new);
        unlink(tmp_name);
        free(tmp_name);
        return 1;
    }

    /* close the old tdb */
    tdb_close(tdb);

    /* copy done, unlock the backup tdb */
    tdb_unlockall(tdb_new);

#ifdef HAVE_FDATASYNC
    if (fdatasync(tdb_fd(tdb_new)) != 0) {
#else
    if (fsync(tdb_fd(tdb_new)) != 0) {
#endif
        /* not fatal */
        fprintf(stderr, "failed to fsync backup file\n");
    }

    /* close the new tdb and re-open read-only */
    tdb_close(tdb_new);
    tdb_new = tdb_open_ex(tmp_name,
                          0,
                          TDB_DEFAULT,
                          O_RDONLY, 0,
                          &log_ctx, NULL);
    if (!tdb_new) {
        fprintf(stderr,"failed to reopen %s\n", tmp_name);
        unlink(tmp_name);
        perror(tmp_name);
        free(tmp_name);
        return 1;
    }

    /* traverse the new tdb to confirm */
    count2 = tdb_traverse(tdb_new, test_fn, NULL);
    if (count2 != count1) {
        fprintf(stderr,"failed to copy %s\n", old_name);
        tdb_close(tdb_new);
        unlink(tmp_name);
        free(tmp_name);
        return 1;
    }

    /* close the new tdb and rename it to .bak */
    tdb_close(tdb_new);
    if (rename(tmp_name, new_name) != 0) {
        perror(new_name);
        free(tmp_name);
        return 1;
    }

    free(tmp_name);

    return 0;
}

/*
  verify a tdb and if it is corrupt then restore from *.bak
*/
static int verify_tdb(const char *fname, const char *bak_name)
{
    TDB_CONTEXT *tdb;
    int count = -1;

    /* open the tdb */
    tdb = tdb_open_ex(fname, 0, 0,
                      O_RDONLY, 0, &log_ctx, NULL);

    /* traverse the tdb, then close it */
    if (tdb) {
        count = tdb_traverse(tdb, test_fn, NULL);
        tdb_close(tdb);
    }

    /* count is < 0 means an error */
    if (count < 0) {
        printf("restoring %s\n", fname);
        return backup_tdb(bak_name, fname, 0, 0);
    }

    printf("%s : %d records\n", fname, count);

    return 0;
}
Example #5
0
struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
			       struct loadparm_context *lp_ctx,
			       const char *name,
			       int hash_size, int tdb_flags,
			       int open_flags, mode_t mode,
			       enum dbwrap_lock_order lock_order,
			       uint64_t dbrwap_flags)
{
	struct db_context *result = NULL;
	struct db_tdb_ctx *db_tdb;
	struct stat st;

	result = talloc_zero(mem_ctx, struct db_context);
	if (result == NULL) {
		DEBUG(0, ("talloc failed\n"));
		goto fail;
	}

	result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
	if (db_tdb == NULL) {
		DEBUG(0, ("talloc failed\n"));
		goto fail;
	}
	result->lock_order = lock_order;

	if (hash_size == 0) {
		hash_size = lpcfg_tdb_hash_size(lp_ctx, name);
	}

	db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size,
				     lpcfg_tdb_flags(lp_ctx, tdb_flags),
				     open_flags, mode);
	if (db_tdb->wtdb == NULL) {
		DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
		goto fail;
	}

	ZERO_STRUCT(db_tdb->id);

	if (fstat(tdb_fd(db_tdb->wtdb->tdb), &st) == -1) {
		DEBUG(3, ("fstat failed: %s\n", strerror(errno)));
		goto fail;
	}
	db_tdb->id.dev = st.st_dev;
	db_tdb->id.ino = st.st_ino;

	result->fetch_locked = db_tdb_fetch_locked;
	result->try_fetch_locked = db_tdb_try_fetch_locked;
	result->traverse = db_tdb_traverse;
	result->traverse_read = db_tdb_traverse_read;
	result->parse_record = db_tdb_parse;
	result->get_seqnum = db_tdb_get_seqnum;
	result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
	result->transaction_start = db_tdb_transaction_start;
	result->transaction_start_nonblock = db_tdb_transaction_start_nonblock;
	result->transaction_commit = db_tdb_transaction_commit;
	result->transaction_cancel = db_tdb_transaction_cancel;
	result->exists = db_tdb_exists;
	result->wipe = db_tdb_wipe;
	result->id = db_tdb_id;
	result->check = db_tdb_check;
	result->name = tdb_name(db_tdb->wtdb->tdb);
	result->hash_size = hash_size;
	return result;

 fail:
	TALLOC_FREE(result);
	return NULL;
}
Example #6
0
/* this backup function is essentially taken from lib/tdb/tools/tdbbackup.tdb
 */
static int tdb_backup(TALLOC_CTX *ctx, const char *src_path,
		      const char *dst_path, int hash_size)
{
	struct tdb_context *src_tdb = NULL;
	struct tdb_context *dst_tdb = NULL;
	char *tmp_path = NULL;
	struct stat st;
	int count1, count2;
	int saved_errno = 0;
	int ret = -1;

	if (stat(src_path, &st) != 0) {
		DEBUG(3, ("Could not stat '%s': %s\n", src_path,
			  strerror(errno)));
		goto done;
	}

	/* open old tdb RDWR - so we can lock it */
	src_tdb = tdb_open_log(src_path, 0, TDB_DEFAULT, O_RDWR, 0);
	if (src_tdb == NULL) {
		DEBUG(3, ("Failed to open tdb '%s'\n", src_path));
		goto done;
	}

	if (tdb_lockall(src_tdb) != 0) {
		DEBUG(3, ("Failed to lock tdb '%s'\n", src_path));
		goto done;
	}

	tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp");
	unlink(tmp_path);
	dst_tdb = tdb_open_log(tmp_path,
			       hash_size ? hash_size : tdb_hash_size(src_tdb),
			       TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL,
			       st.st_mode & 0777);
	if (dst_tdb == NULL) {
		DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path,
			  strerror(errno)));
		saved_errno = errno;
		unlink(tmp_path);
		goto done;
	}

	count1 = tdb_copy(src_tdb, dst_tdb);
	if (count1 < 0) {
		DEBUG(3, ("Failed to copy tdb '%s': %s\n", src_path,
			  strerror(errno)));
		tdb_close(dst_tdb);
		goto done;
	}

	/* reopen ro and do basic verification */
	tdb_close(dst_tdb);
	dst_tdb = tdb_open_log(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0);
	if (!dst_tdb) {
		DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path,
			  strerror(errno)));
		goto done;
	}
	count2 = tdb_verify_basic(dst_tdb);
	if (count2 != count1) {
		DEBUG(3, ("Failed to verify result of copying tdb '%s'.\n",
			  src_path));
		tdb_close(dst_tdb);
		goto done;
	}

	DEBUG(10, ("tdb_backup: successfully copied %d entries\n", count1));

	/* make sure the new tdb has reached stable storage
	 * then rename it to its destination */
	fsync(tdb_fd(dst_tdb));
	tdb_close(dst_tdb);
	unlink(dst_path);
	if (rename(tmp_path, dst_path) != 0) {
		DEBUG(3, ("Failed to rename '%s' to '%s': %s\n",
			  tmp_path, dst_path, strerror(errno)));
		goto done;
	}

	/* success */
	ret = 0;

done:
	if (src_tdb != NULL) {
		tdb_close(src_tdb);
	}
	if (tmp_path != NULL) {
		unlink(tmp_path);
		TALLOC_FREE(tmp_path);
	}
	if (saved_errno != 0) {
		errno = saved_errno;
	}
	return ret;
}
Example #7
0
/*
  carefully backup a tdb, validating the contents and
  only doing the backup if its OK
  this function is also used for restore
*/
int backup_tdb(const char *old_name, const char *new_name, int hash_size)
{
	TDB_CONTEXT *tdb;
	TDB_CONTEXT *tdb_new;
	char *tmp_name;
	struct stat st;
	int count1, count2;

	tmp_name = add_suffix(new_name, ".tmp");

	/* stat the old tdb to find its permissions */
	if (stat(old_name, &st) != 0) {
		perror(old_name);
		free(tmp_name);
		return 1;
	}

	/* open the old tdb */
	tdb = tdb_open(old_name, 0, 0, O_RDWR, 0);
	if (!tdb) {
		printf("Failed to open %s\n", old_name);
		free(tmp_name);
		return 1;
	}

	/* create the new tdb */
	unlink(tmp_name);
	tdb_new = tdb_open(tmp_name,
			   hash_size ? hash_size : tdb_hash_size(tdb),
			   TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL, 
			   st.st_mode & 0777);
	if (!tdb_new) {
		perror(tmp_name);
		free(tmp_name);
		return 1;
	}

	/* lock the old tdb */
	if (tdb_lockall(tdb) != 0) {
		fprintf(stderr,"Failed to lock %s\n", old_name);
		tdb_close(tdb);
		tdb_close(tdb_new);
		unlink(tmp_name);
		free(tmp_name);
		return 1;
	}

	failed = 0;

	/* traverse and copy */
	count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new);
	if (count1 < 0 || failed) {
		fprintf(stderr,"failed to copy %s\n", old_name);
		tdb_close(tdb);
		tdb_close(tdb_new);
		unlink(tmp_name);
		free(tmp_name);
		return 1;
	}

	/* close the old tdb */
	tdb_close(tdb);

	/* close the new tdb and re-open read-only */
	tdb_close(tdb_new);
	tdb_new = tdb_open(tmp_name, 0, TDB_DEFAULT, O_RDONLY, 0);
	if (!tdb_new) {
		fprintf(stderr,"failed to reopen %s\n", tmp_name);
		unlink(tmp_name);
		perror(tmp_name);
		free(tmp_name);
		return 1;
	}
	
	/* traverse the new tdb to confirm */
	count2 = tdb_traverse(tdb_new, test_fn, 0);
	if (count2 != count1) {
		fprintf(stderr,"failed to copy %s\n", old_name);
		tdb_close(tdb_new);
		unlink(tmp_name);
		free(tmp_name);
		return 1;
	}

	/* make sure the new tdb has reached stable storage */
	fsync(tdb_fd(tdb_new));

	/* close the new tdb and rename it to .bak */
	tdb_close(tdb_new);
	unlink(new_name);
	if (rename(tmp_name, new_name) != 0) {
		perror(new_name);
		free(tmp_name);
		return 1;
	}

	free(tmp_name);

	return 0;
}