1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00

added -v and -s options

-v is used for verify/restore from backup
This commit is contained in:
Andrew Tridgell 0001-01-01 00:00:00 +00:00
parent 96299b6391
commit 1438cd8e50

View File

@ -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;