summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/lib/util_tdb.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c
index cc10e4c9ad..471a8c7da9 100644
--- a/source3/lib/util_tdb.c
+++ b/source3/lib/util_tdb.c
@@ -1183,6 +1183,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path,
char *tmp_path = NULL;
struct stat st;
int count1, count2;
+ int saved_errno = 0;
int ret = -1;
if (stat(src_path, &st) != 0) {
@@ -1212,6 +1213,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path,
if (dst_tdb == NULL) {
DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path,
strerror(errno)));
+ saved_errno = errno;
unlink(tmp_path);
goto done;
}
@@ -1264,6 +1266,9 @@ done:
unlink(tmp_path);
TALLOC_FREE(tmp_path);
}
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
return ret;
}
@@ -1296,17 +1301,45 @@ static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path,
*/
static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path,
const char *dst_path, int hash_size,
- const char *rotate_suffix)
+ const char *rotate_suffix,
+ BOOL retry_norotate_if_nospc,
+ BOOL rename_as_last_resort_if_nospc)
{
int ret;
- ret = rename_file_with_suffix(ctx, dst_path, rotate_suffix);
+ rename_file_with_suffix(ctx, dst_path, rotate_suffix);
- /* ignore return value of rename here:
- * the more important thing is to do the backup */
- ret = tdb_backup(ctx, src_path, dst_path, hash_size);
+ ret = tdb_backup(ctx, src_path, dst_path, hash_size);
- return ret;
+ if (ret != 0) {
+ DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno)));
+ }
+ if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc)
+ {
+ char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path,
+ rotate_suffix);
+ DEBUG(10, ("backup of %s failed due to lack of space\n",
+ src_path));
+ DEBUGADD(10, ("trying to free some space by removing rotated "
+ "dst %s\n", rotate_path));
+ if (unlink(rotate_path) == -1) {
+ DEBUG(10, ("unlink of %s failed: %s\n", rotate_path,
+ strerror(errno)));
+ } else {
+ ret = tdb_backup(ctx, src_path, dst_path, hash_size);
+ }
+ TALLOC_FREE(rotate_path);
+ }
+
+ if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc)
+ {
+ DEBUG(10, ("backup of %s failed due to lack of space\n",
+ src_path));
+ DEBUGADD(10, ("using 'rename' as a last resort\n"));
+ ret = rename(src_path, dst_path);
+ }
+
+ return ret;
}
/*
@@ -1347,7 +1380,7 @@ int tdb_validate_and_backup(const char *tdb_path,
if (ret == 0) {
DEBUG(1, ("tdb '%s' is valid\n", tdb_path));
ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0,
- rotate_suffix);
+ rotate_suffix, True, False);
if (ret != 0) {
DEBUG(1, ("Error creating backup of tdb '%s'\n",
tdb_path));
@@ -1360,32 +1393,36 @@ int tdb_validate_and_backup(const char *tdb_path,
} else {
DEBUG(1, ("tdb '%s' is invalid\n", tdb_path));
- /* move corrupt tdb away first, but don't return on error*/
- ret = rename_file_with_suffix(ctx, tdb_path, corrupt_suffix);
+ ret =stat(tdb_path_backup, &st);
if (ret != 0) {
- DEBUG(1, ("Error moving tdb to '%s%s'\n", tdb_path,
- corrupt_suffix));
- } else {
- DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", tdb_path,
- corrupt_suffix));
- }
-
- if (stat(tdb_path_backup, &st) != 0) {
DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup,
strerror(errno)));
DEBUG(1, ("No backup found.\n"));
- ret = -1;
- goto done;
+ } else {
+ DEBUG(1, ("backup '%s' found.\n", tdb_path_backup));
+ ret = tdb_validate(tdb_path_backup, validate_fn);
+ if (ret != 0) {
+ DEBUG(1, ("Backup '%s' is invalid.\n",
+ tdb_path_backup));
+ }
}
- DEBUG(1, ("backup '%s' found.\n", tdb_path_backup));
- ret = tdb_validate(tdb_path_backup, validate_fn);
+
if (ret != 0) {
- DEBUG(1, ("Backup '%s' is invalid.\n",tdb_path_backup));
+ int renamed = rename_file_with_suffix(ctx, tdb_path,
+ corrupt_suffix);
+ if (renamed != 0) {
+ DEBUG(1, ("Error moving tdb to '%s%s'\n",
+ tdb_path, corrupt_suffix));
+ } else {
+ DEBUG(1, ("Corrupt tdb stored as '%s%s'\n",
+ tdb_path, corrupt_suffix));
+ }
goto done;
}
DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup));
- ret = tdb_backup(ctx, tdb_path_backup, tdb_path, 0);
+ ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0,
+ corrupt_suffix, True, True);
if (ret != 0) {
DEBUG(1, ("Error restoring backup from '%s'\n",
tdb_path_backup));