1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00
samba-mirror/source3/tdb/tdbback.c
Simo Sorce b1f610ebb1 split some security related functions in their own files.
(no need to include all of smbd files to use some basic sec functions)

also minor compile fixes
couldn't compile to test these due to some kerberos problems wirh 3.0,
but on HEAD they're working well, so I suppose it's ok to commit
(This used to be commit c78f2d0bd1)
2003-10-06 01:38:46 +00:00

212 lines
4.4 KiB
C

/*
Unix SMB/CIFS implementation.
low level tdb backup and restore utility
Copyright (C) Andrew Tridgell 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef STANDALONE
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <ctype.h>
#include <signal.h>
#else
#include "includes.h"
#endif
#include "tdb.h"
static int failed;
char *add_suffix(const char *name, const char *suffix)
{
char *ret;
int len = strlen(name) + strlen(suffix) + 1;
ret = malloc(len);
if (!ret) {
fprintf(stderr,"Out of memory!\n");
exit(1);
}
snprintf(ret, len, "%s%s", name, suffix);
return ret;
}
static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
{
TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state;
if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) {
fprintf(stderr,"Failed to insert into %s\n", tdb_new->name);
failed = 1;
return 1;
}
return 0;
}
static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
{
return 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)
{
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);
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);
return 1;
}
/* create the new tdb */
unlink(tmp_name);
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);
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_new->fd);
/* 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;
}
/*
verify a tdb and if it is corrupt then restore from *.bak
*/
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;
}