mirror of
https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
synced 2024-12-13 11:54:31 +08:00
f404167dda
Mostly by adding static and removing excess extern qualifiers. Also convert a few remaining non-ANSI function declarations to ANSI. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
226 lines
5.0 KiB
C
226 lines
5.0 KiB
C
/*
|
|
* e2undo.c - Replay an undo log onto an ext2/3/4 filesystem
|
|
*
|
|
* Copyright IBM Corporation, 2007
|
|
* Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
|
*
|
|
* %Begin-Header%
|
|
* This file may be redistributed under the terms of the GNU Public
|
|
* License.
|
|
* %End-Header%
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#ifdef HAVE_GETOPT_H
|
|
#include <getopt.h>
|
|
#endif
|
|
#include <fcntl.h>
|
|
#if HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
#include "ext2fs/tdb.h"
|
|
#include "ext2fs/ext2fs.h"
|
|
#include "nls-enable.h"
|
|
|
|
static unsigned char mtime_key[] = "filesystem MTIME";
|
|
static unsigned char uuid_key[] = "filesystem UUID";
|
|
static unsigned char blksize_key[] = "filesystem BLKSIZE";
|
|
|
|
static char *prg_name;
|
|
|
|
static void usage(void)
|
|
{
|
|
fprintf(stderr,
|
|
_("Usage: %s <transaction file> <filesystem>\n"), prg_name);
|
|
exit(1);
|
|
}
|
|
|
|
static int check_filesystem(TDB_CONTEXT *tdb, io_channel channel)
|
|
{
|
|
__u32 s_mtime;
|
|
__u8 s_uuid[16];
|
|
errcode_t retval;
|
|
TDB_DATA tdb_key, tdb_data;
|
|
struct ext2_super_block super;
|
|
|
|
io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
|
|
retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
|
|
if (retval) {
|
|
com_err(prg_name, retval,
|
|
"%s", _("Failed to read the file system data \n"));
|
|
return retval;
|
|
}
|
|
|
|
tdb_key.dptr = mtime_key;
|
|
tdb_key.dsize = sizeof(mtime_key);
|
|
tdb_data = tdb_fetch(tdb, tdb_key);
|
|
if (!tdb_data.dptr) {
|
|
retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
|
|
com_err(prg_name, retval,
|
|
_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
|
|
return retval;
|
|
}
|
|
|
|
s_mtime = *(__u32 *)tdb_data.dptr;
|
|
if (super.s_mtime != s_mtime) {
|
|
|
|
com_err(prg_name, 0,
|
|
_("The file system Mount time didn't match %u\n"),
|
|
s_mtime);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
tdb_key.dptr = uuid_key;
|
|
tdb_key.dsize = sizeof(uuid_key);
|
|
tdb_data = tdb_fetch(tdb, tdb_key);
|
|
if (!tdb_data.dptr) {
|
|
retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
|
|
com_err(prg_name, retval,
|
|
_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
|
|
return retval;
|
|
}
|
|
memcpy(s_uuid, tdb_data.dptr, sizeof(s_uuid));
|
|
if (memcmp(s_uuid, super.s_uuid, sizeof(s_uuid))) {
|
|
com_err(prg_name, 0, "%s",
|
|
_("The file system UUID didn't match \n"));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int set_blk_size(TDB_CONTEXT *tdb, io_channel channel)
|
|
{
|
|
int block_size;
|
|
errcode_t retval;
|
|
TDB_DATA tdb_key, tdb_data;
|
|
|
|
tdb_key.dptr = blksize_key;
|
|
tdb_key.dsize = sizeof(blksize_key);
|
|
tdb_data = tdb_fetch(tdb, tdb_key);
|
|
if (!tdb_data.dptr) {
|
|
retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
|
|
com_err(prg_name, retval,
|
|
_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
|
|
return retval;
|
|
}
|
|
|
|
block_size = *(int *)tdb_data.dptr;
|
|
#ifdef DEBUG
|
|
printf("Block size %d\n", block_size);
|
|
#endif
|
|
io_channel_set_blksize(channel, block_size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int c,force = 0;
|
|
TDB_CONTEXT *tdb;
|
|
TDB_DATA key, data;
|
|
io_channel channel;
|
|
errcode_t retval;
|
|
int mount_flags;
|
|
blk64_t blk_num;
|
|
char *device_name, *tdb_file;
|
|
io_manager manager = unix_io_manager;
|
|
|
|
#ifdef ENABLE_NLS
|
|
setlocale(LC_MESSAGES, "");
|
|
setlocale(LC_CTYPE, "");
|
|
bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
|
|
textdomain(NLS_CAT_NAME);
|
|
set_com_err_gettext(gettext);
|
|
#endif
|
|
add_error_table(&et_ext2_error_table);
|
|
|
|
prg_name = argv[0];
|
|
while((c = getopt(argc, argv, "f")) != EOF) {
|
|
switch (c) {
|
|
case 'f':
|
|
force = 1;
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
}
|
|
|
|
if (argc != optind + 2)
|
|
usage();
|
|
|
|
tdb_file = argv[optind];
|
|
device_name = argv[optind+1];
|
|
|
|
tdb = tdb_open(tdb_file, 0, 0, O_RDONLY, 0600);
|
|
|
|
if (!tdb) {
|
|
com_err(prg_name, errno,
|
|
_("Failed tdb_open %s\n"), tdb_file);
|
|
exit(1);
|
|
}
|
|
|
|
retval = ext2fs_check_if_mounted(device_name, &mount_flags);
|
|
if (retval) {
|
|
com_err(prg_name, retval, _("Error while determining whether "
|
|
"%s is mounted.\n"), device_name);
|
|
exit(1);
|
|
}
|
|
|
|
if (mount_flags & EXT2_MF_MOUNTED) {
|
|
com_err(prg_name, retval, "%s", _("e2undo should only be run "
|
|
"on unmounted file system\n"));
|
|
exit(1);
|
|
}
|
|
|
|
retval = manager->open(device_name,
|
|
IO_FLAG_EXCLUSIVE | IO_FLAG_RW, &channel);
|
|
if (retval) {
|
|
com_err(prg_name, retval,
|
|
_("Failed to open %s\n"), device_name);
|
|
exit(1);
|
|
}
|
|
|
|
if (!force && check_filesystem(tdb, channel)) {
|
|
exit(1);
|
|
}
|
|
|
|
if (set_blk_size(tdb, channel)) {
|
|
exit(1);
|
|
}
|
|
|
|
for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) {
|
|
if (!strcmp((char *) key.dptr, (char *) mtime_key) ||
|
|
!strcmp((char *) key.dptr, (char *) uuid_key) ||
|
|
!strcmp((char *) key.dptr, (char *) blksize_key)) {
|
|
continue;
|
|
}
|
|
|
|
data = tdb_fetch(tdb, key);
|
|
if (!data.dptr) {
|
|
com_err(prg_name, 0,
|
|
_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
|
|
exit(1);
|
|
}
|
|
blk_num = *(blk64_t *)key.dptr;
|
|
printf(_("Replayed transaction of size %zd at location %llu\n"),
|
|
data.dsize, blk_num);
|
|
retval = io_channel_write_blk64(channel, blk_num,
|
|
-data.dsize, data.dptr);
|
|
if (retval == -1) {
|
|
com_err(prg_name, retval,
|
|
_("Failed write %s\n"),
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
}
|
|
io_channel_close(channel);
|
|
tdb_close(tdb);
|
|
|
|
return 0;
|
|
}
|