mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
added -v and -s options
-v is used for verify/restore from backup
This commit is contained in:
parent
96299b6391
commit
1438cd8e50
@ -53,36 +53,37 @@ static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
||||
}
|
||||
|
||||
/*
|
||||
carefully backup a tdb to %s.bak, validating the contents and
|
||||
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 *fname)
|
||||
static int backup_tdb(const char *old_name, const char *new_name)
|
||||
{
|
||||
TDB_CONTEXT *tdb;
|
||||
TDB_CONTEXT *tdb_new;
|
||||
char *tmp_name = NULL;
|
||||
char *bak_name = NULL;
|
||||
struct stat st;
|
||||
int count1, count2;
|
||||
|
||||
asprintf(&tmp_name, "%s.tmp", fname);
|
||||
asprintf(&tmp_name, "%s.tmp", new_name);
|
||||
|
||||
/* stat the old tdb to find its permissions */
|
||||
if (stat(fname, &st) != 0) {
|
||||
perror(fname);
|
||||
if (stat(old_name, &st) != 0) {
|
||||
perror(old_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* open the old tdb */
|
||||
tdb = tdb_open(fname, 0, 0, O_RDWR, 0);
|
||||
tdb = tdb_open(old_name, 0, 0, O_RDWR, 0);
|
||||
if (!tdb) {
|
||||
printf("Failed to open %s\n", fname);
|
||||
printf("Failed to open %s\n", old_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create the new tdb */
|
||||
unlink(tmp_name);
|
||||
tdb_new = tdb_open(tmp_name, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL,
|
||||
tdb_new = tdb_open(tmp_name, tdb->header.hash_size,
|
||||
TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL,
|
||||
st.st_mode & 0777);
|
||||
if (!tdb_new) {
|
||||
perror(tmp_name);
|
||||
@ -92,7 +93,7 @@ static int backup_tdb(const char *fname)
|
||||
|
||||
/* lock the old tdb */
|
||||
if (tdb_lockall(tdb) != 0) {
|
||||
fprintf(stderr,"Failed to lock %s\n", fname);
|
||||
fprintf(stderr,"Failed to lock %s\n", old_name);
|
||||
tdb_close(tdb);
|
||||
tdb_close(tdb_new);
|
||||
unlink(tmp_name);
|
||||
@ -105,7 +106,7 @@ static int backup_tdb(const char *fname)
|
||||
/* traverse and copy */
|
||||
count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new);
|
||||
if (count1 < 0 || failed) {
|
||||
fprintf(stderr,"failed to backup %s\n", fname);
|
||||
fprintf(stderr,"failed to copy %s\n", old_name);
|
||||
tdb_close(tdb);
|
||||
tdb_close(tdb_new);
|
||||
unlink(tmp_name);
|
||||
@ -130,43 +131,120 @@ static int backup_tdb(const char *fname)
|
||||
/* traverse the new tdb to confirm */
|
||||
count2 = tdb_traverse(tdb_new, test_fn, 0);
|
||||
if (count2 != count1) {
|
||||
fprintf(stderr,"failed to backup %s\n", fname);
|
||||
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_new->fd);
|
||||
|
||||
/* close the new tdb and rename it to .bak */
|
||||
tdb_close(tdb_new);
|
||||
asprintf(&bak_name, "%s.bak", fname);
|
||||
unlink(bak_name);
|
||||
if (rename(tmp_name, bak_name) != 0) {
|
||||
perror(bak_name);
|
||||
unlink(new_name);
|
||||
if (rename(tmp_name, new_name) != 0) {
|
||||
perror(new_name);
|
||||
free(tmp_name);
|
||||
free(bak_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s : %d records\n", fname, count1);
|
||||
printf("%s : %d records\n", old_name, count1);
|
||||
free(tmp_name);
|
||||
free(bak_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(fname, 0, 0, O_RDONLY, 0);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
printf("%s : %d records\n", fname, count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: tdbbackup [options] <fname...>\n\n");
|
||||
printf(" -h this help message\n");
|
||||
printf(" -s suffix set the backup suffix\n");
|
||||
printf(" -v veryify mode (restore if corrupt)\n");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
int c;
|
||||
int verify = 0;
|
||||
char *suffix = ".bak";
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: tdbbackup [options] <fname...>\n");
|
||||
while ((c = getopt(argc, argv, "vhs:")) != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage();
|
||||
exit(0);
|
||||
case 'v':
|
||||
verify = 1;
|
||||
break;
|
||||
case 's':
|
||||
suffix = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i=1; i<argc; i++) {
|
||||
if (backup_tdb(argv[i]) != 0) ret = 1;
|
||||
for (i=0; i<argc; i++) {
|
||||
const char *fname = argv[i];
|
||||
char *bak_name = NULL;
|
||||
|
||||
asprintf(&bak_name, "%s%s", fname, suffix);
|
||||
|
||||
if (verify) {
|
||||
if (verify_tdb(fname, bak_name) != 0) {
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
if (backup_tdb(fname, bak_name) != 0) {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(bak_name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user