Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
0
static PyObject *obj_get_hash_size(PyTdbObject *self, void *closure)
{
	PyErr_TDB_RAISE_IF_CLOSED(self);
	return PyInt_FromLong(tdb_hash_size(self->ctx));
}