blob: d51537376d98d65f16caf3c03ab19bf32ef9886a [file] [log] [blame]
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +05301/*
2 * e2undo.c - Replay an undo log onto an ext2/3/4 filesystem
3 *
4 * Copyright IBM Corporation, 2007
5 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#ifdef HAVE_GETOPT_H
16#include <getopt.h>
17#endif
18#include <fcntl.h>
19#if HAVE_ERRNO_H
20#include <errno.h>
21#endif
22#include "ext2fs/tdb.h"
23#include "ext2fs/ext2fs.h"
24#include "nls-enable.h"
25
JP Abgralle0ed7402014-03-19 19:08:39 -070026static unsigned char mtime_key[] = "filesystem MTIME";
27static unsigned char uuid_key[] = "filesystem UUID";
28static unsigned char blksize_key[] = "filesystem BLKSIZE";
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053029
JP Abgralle0ed7402014-03-19 19:08:39 -070030static char *prg_name;
Theodore Ts'o38dd11f2008-07-13 15:44:32 -040031
JP Abgralle0ed7402014-03-19 19:08:39 -070032static void usage(void)
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053033{
34 fprintf(stderr,
35 _("Usage: %s <transaction file> <filesystem>\n"), prg_name);
36 exit(1);
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053037}
38
39static int check_filesystem(TDB_CONTEXT *tdb, io_channel channel)
40{
41 __u32 s_mtime;
42 __u8 s_uuid[16];
43 errcode_t retval;
44 TDB_DATA tdb_key, tdb_data;
45 struct ext2_super_block super;
46
47 io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
JP Abgralle0ed7402014-03-19 19:08:39 -070048 retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053049 if (retval) {
JP Abgralle0ed7402014-03-19 19:08:39 -070050 com_err(prg_name, retval,
51 "%s", _("Failed to read the file system data \n"));
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053052 return retval;
53 }
54
55 tdb_key.dptr = mtime_key;
56 tdb_key.dsize = sizeof(mtime_key);
57 tdb_data = tdb_fetch(tdb, tdb_key);
58 if (!tdb_data.dptr) {
59 retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
Theodore Ts'o38dd11f2008-07-13 15:44:32 -040060 com_err(prg_name, retval,
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053061 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
62 return retval;
63 }
64
65 s_mtime = *(__u32 *)tdb_data.dptr;
66 if (super.s_mtime != s_mtime) {
67
Theodore Ts'o38dd11f2008-07-13 15:44:32 -040068 com_err(prg_name, 0,
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053069 _("The file system Mount time didn't match %u\n"),
70 s_mtime);
71
72 return -1;
73 }
74
75
76 tdb_key.dptr = uuid_key;
77 tdb_key.dsize = sizeof(uuid_key);
78 tdb_data = tdb_fetch(tdb, tdb_key);
79 if (!tdb_data.dptr) {
80 retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
Theodore Ts'o38dd11f2008-07-13 15:44:32 -040081 com_err(prg_name, retval,
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053082 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
83 return retval;
84 }
85 memcpy(s_uuid, tdb_data.dptr, sizeof(s_uuid));
86 if (memcmp(s_uuid, super.s_uuid, sizeof(s_uuid))) {
JP Abgralle0ed7402014-03-19 19:08:39 -070087 com_err(prg_name, 0, "%s",
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +053088 _("The file system UUID didn't match \n"));
89 return -1;
90 }
91
92 return 0;
93}
94
95static int set_blk_size(TDB_CONTEXT *tdb, io_channel channel)
96{
97 int block_size;
98 errcode_t retval;
99 TDB_DATA tdb_key, tdb_data;
100
101 tdb_key.dptr = blksize_key;
102 tdb_key.dsize = sizeof(blksize_key);
103 tdb_data = tdb_fetch(tdb, tdb_key);
104 if (!tdb_data.dptr) {
105 retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
Theodore Ts'o38dd11f2008-07-13 15:44:32 -0400106 com_err(prg_name, retval,
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530107 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
108 return retval;
109 }
110
111 block_size = *(int *)tdb_data.dptr;
112#ifdef DEBUG
113 printf("Block size %d\n", block_size);
114#endif
115 io_channel_set_blksize(channel, block_size);
116
117 return 0;
118}
119
120int main(int argc, char *argv[])
121{
122 int c,force = 0;
123 TDB_CONTEXT *tdb;
124 TDB_DATA key, data;
125 io_channel channel;
126 errcode_t retval;
127 int mount_flags;
JP Abgralle0ed7402014-03-19 19:08:39 -0700128 blk64_t blk_num;
Theodore Ts'o38dd11f2008-07-13 15:44:32 -0400129 char *device_name, *tdb_file;
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530130 io_manager manager = unix_io_manager;
131
Theodore Ts'o11d4f302008-06-07 22:16:48 -0400132#ifdef ENABLE_NLS
133 setlocale(LC_MESSAGES, "");
134 setlocale(LC_CTYPE, "");
135 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
136 textdomain(NLS_CAT_NAME);
JP Abgralle0ed7402014-03-19 19:08:39 -0700137 set_com_err_gettext(gettext);
Theodore Ts'o11d4f302008-06-07 22:16:48 -0400138#endif
Theodore Ts'o1d4a4932009-09-08 21:29:21 -0400139 add_error_table(&et_ext2_error_table);
Theodore Ts'o11d4f302008-06-07 22:16:48 -0400140
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530141 prg_name = argv[0];
142 while((c = getopt(argc, argv, "f")) != EOF) {
143 switch (c) {
144 case 'f':
145 force = 1;
146 break;
147 default:
JP Abgralle0ed7402014-03-19 19:08:39 -0700148 usage();
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530149 }
150 }
151
JP Abgralle0ed7402014-03-19 19:08:39 -0700152 if (argc != optind + 2)
153 usage();
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530154
155 tdb_file = argv[optind];
156 device_name = argv[optind+1];
157
158 tdb = tdb_open(tdb_file, 0, 0, O_RDONLY, 0600);
159
160 if (!tdb) {
161 com_err(prg_name, errno,
162 _("Failed tdb_open %s\n"), tdb_file);
163 exit(1);
164 }
165
166 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
167 if (retval) {
168 com_err(prg_name, retval, _("Error while determining whether "
169 "%s is mounted.\n"), device_name);
170 exit(1);
171 }
172
173 if (mount_flags & EXT2_MF_MOUNTED) {
JP Abgralle0ed7402014-03-19 19:08:39 -0700174 com_err(prg_name, retval, "%s", _("e2undo should only be run "
175 "on unmounted file system\n"));
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530176 exit(1);
177 }
178
179 retval = manager->open(device_name,
180 IO_FLAG_EXCLUSIVE | IO_FLAG_RW, &channel);
181 if (retval) {
182 com_err(prg_name, retval,
183 _("Failed to open %s\n"), device_name);
184 exit(1);
185 }
186
187 if (!force && check_filesystem(tdb, channel)) {
188 exit(1);
189 }
190
191 if (set_blk_size(tdb, channel)) {
192 exit(1);
193 }
194
195 for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) {
196 if (!strcmp((char *) key.dptr, (char *) mtime_key) ||
197 !strcmp((char *) key.dptr, (char *) uuid_key) ||
198 !strcmp((char *) key.dptr, (char *) blksize_key)) {
199 continue;
200 }
201
202 data = tdb_fetch(tdb, key);
203 if (!data.dptr) {
204 com_err(prg_name, 0,
205 _("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
206 exit(1);
207 }
JP Abgralle0ed7402014-03-19 19:08:39 -0700208 blk_num = *(blk64_t *)key.dptr;
209 printf(_("Replayed transaction of size %zd at location %llu\n"),
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530210 data.dsize, blk_num);
JP Abgralle0ed7402014-03-19 19:08:39 -0700211 retval = io_channel_write_blk64(channel, blk_num,
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530212 -data.dsize, data.dptr);
213 if (retval == -1) {
214 com_err(prg_name, retval,
215 _("Failed write %s\n"),
216 strerror(errno));
217 exit(1);
218 }
219 }
220 io_channel_close(channel);
221 tdb_close(tdb);
222
Eric Sandeen79e62402008-07-06 18:36:56 -0400223 return 0;
Aneesh Kumar K.V5f8a5ae2007-08-13 15:56:22 +0530224}