2 * e2undo.c - Replay an undo log onto an ext2/3/4 filesystem
4 * Copyright IBM Corporation, 2007
5 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8 * This file may be redistributed under the terms of the GNU Public
22 #include "ext2fs/tdb.h"
23 #include "ext2fs/ext2fs.h"
24 #include "nls-enable.h"
26 unsigned char mtime_key[] = "filesystem MTIME";
27 unsigned char uuid_key[] = "filesystem UUID";
28 unsigned char blksize_key[] = "filesystem BLKSIZE";
30 static void usage(char *prg_name)
33 _("Usage: %s <transaction file> <filesystem>\n"), prg_name);
38 static int check_filesystem(TDB_CONTEXT *tdb, io_channel channel)
43 TDB_DATA tdb_key, tdb_data;
44 struct ext2_super_block super;
46 io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
47 retval = io_channel_read_blk(channel, 1, -SUPERBLOCK_SIZE, &super);
50 retval, _("Failed to read the file system data \n"));
54 tdb_key.dptr = mtime_key;
55 tdb_key.dsize = sizeof(mtime_key);
56 tdb_data = tdb_fetch(tdb, tdb_key);
58 retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
59 com_err(__FUNCTION__, retval,
60 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
64 s_mtime = *(__u32 *)tdb_data.dptr;
65 if (super.s_mtime != s_mtime) {
67 com_err(__FUNCTION__, 0,
68 _("The file system Mount time didn't match %u\n"),
75 tdb_key.dptr = uuid_key;
76 tdb_key.dsize = sizeof(uuid_key);
77 tdb_data = tdb_fetch(tdb, tdb_key);
79 retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
80 com_err(__FUNCTION__, retval,
81 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
84 memcpy(s_uuid, tdb_data.dptr, sizeof(s_uuid));
85 if (memcmp(s_uuid, super.s_uuid, sizeof(s_uuid))) {
86 com_err(__FUNCTION__, 0,
87 _("The file system UUID didn't match \n"));
94 static int set_blk_size(TDB_CONTEXT *tdb, io_channel channel)
98 TDB_DATA tdb_key, tdb_data;
100 tdb_key.dptr = blksize_key;
101 tdb_key.dsize = sizeof(blksize_key);
102 tdb_data = tdb_fetch(tdb, tdb_key);
103 if (!tdb_data.dptr) {
104 retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
105 com_err(__FUNCTION__, retval,
106 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
110 block_size = *(int *)tdb_data.dptr;
112 printf("Block size %d\n", block_size);
114 io_channel_set_blksize(channel, block_size);
119 int main(int argc, char *argv[])
127 unsigned long blk_num;
128 char *device_name, *tdb_file, *prg_name;
129 io_manager manager = unix_io_manager;
132 setlocale(LC_MESSAGES, "");
133 setlocale(LC_CTYPE, "");
134 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
135 textdomain(NLS_CAT_NAME);
139 while((c = getopt(argc, argv, "f")) != EOF) {
149 if (argc != optind+2)
152 tdb_file = argv[optind];
153 device_name = argv[optind+1];
155 tdb = tdb_open(tdb_file, 0, 0, O_RDONLY, 0600);
158 com_err(prg_name, errno,
159 _("Failed tdb_open %s\n"), tdb_file);
163 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
165 com_err(prg_name, retval, _("Error while determining whether "
166 "%s is mounted.\n"), device_name);
170 if (mount_flags & EXT2_MF_MOUNTED) {
171 com_err(prg_name, retval, _("undoe2fs should only be run on "
172 "unmounted file system\n"));
176 retval = manager->open(device_name,
177 IO_FLAG_EXCLUSIVE | IO_FLAG_RW, &channel);
179 com_err(prg_name, retval,
180 _("Failed to open %s\n"), device_name);
184 if (!force && check_filesystem(tdb, channel)) {
188 if (set_blk_size(tdb, channel)) {
192 for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) {
193 if (!strcmp((char *) key.dptr, (char *) mtime_key) ||
194 !strcmp((char *) key.dptr, (char *) uuid_key) ||
195 !strcmp((char *) key.dptr, (char *) blksize_key)) {
199 data = tdb_fetch(tdb, key);
202 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
205 blk_num = *(unsigned long *)key.dptr;
206 printf(_("Replayed transaction of size %zd at location %ld\n"),
207 data.dsize, blk_num);
208 retval = io_channel_write_blk(channel, blk_num,
209 -data.dsize, data.dptr);
211 com_err(prg_name, retval,
212 _("Failed write %s\n"),
217 io_channel_close(channel);