mirror of https://github.com/vitalif/e2fsprogs
debugfs: optionally create undo file
Provide the user with an option to create an undo file so that they can roll back a failed debugfs expedition. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>debian
parent
2d291b3c6b
commit
491cc33ac6
|
@ -31,6 +31,10 @@ request
|
|||
data_source_device
|
||||
]
|
||||
[
|
||||
.B \-z
|
||||
.I undo_file
|
||||
]
|
||||
[
|
||||
device
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
|
@ -130,6 +134,16 @@ and then exit.
|
|||
print the version number of
|
||||
.B debugfs
|
||||
and exit.
|
||||
.TP
|
||||
.BI \-z " undo_file"
|
||||
Before overwriting a file system block, write the old contents of the block to
|
||||
an undo file. This undo file can be used with e2undo(8) to restore the old
|
||||
contents of the file system should something go wrong. If the empty string is
|
||||
passed as the undo_file argument, the undo file will be written to a file named
|
||||
resize2fs-\fIdevice\fR.e2undo in the directory specified via the
|
||||
\fIE2FSPROGS_UNDO_DIR\fR environment variable.
|
||||
|
||||
WARNING: The undo file cannot be used to recover from a power or system crash.
|
||||
.SH SPECIFYING FILES
|
||||
Many
|
||||
.B debugfs
|
||||
|
@ -535,7 +549,7 @@ to those inodes. The
|
|||
flag will enable checking the file type information in the directory
|
||||
entry to make sure it matches the inode's type.
|
||||
.TP
|
||||
.BI open " [-weficD] [-b blocksize] [-s superblock] device"
|
||||
.BI open " [-weficD] [-b blocksize] [-s superblock] [-z undo_file] device"
|
||||
Open a filesystem for editing. The
|
||||
.I -f
|
||||
flag forces the filesystem to be opened even if there are some unknown
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <libgen.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#else
|
||||
|
@ -48,12 +49,88 @@ ext2_filsys current_fs;
|
|||
quota_ctx_t current_qctx;
|
||||
ext2_ino_t root, cwd;
|
||||
|
||||
static int debugfs_setup_tdb(const char *device_name, char *undo_file,
|
||||
io_manager *io_ptr)
|
||||
{
|
||||
errcode_t retval = ENOMEM;
|
||||
char *tdb_dir = NULL, *tdb_file = NULL;
|
||||
char *dev_name, *tmp_name;
|
||||
int free_tdb_dir = 0;
|
||||
|
||||
/* (re)open a specific undo file */
|
||||
if (undo_file && undo_file[0] != 0) {
|
||||
set_undo_io_backing_manager(*io_ptr);
|
||||
*io_ptr = undo_io_manager;
|
||||
retval = set_undo_io_backup_file(undo_file);
|
||||
if (retval)
|
||||
goto err;
|
||||
printf("Overwriting existing filesystem; this can be undone "
|
||||
"using the command:\n"
|
||||
" e2undo %s %s\n\n",
|
||||
undo_file, device_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configuration via a conf file would be
|
||||
* nice
|
||||
*/
|
||||
tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
|
||||
|
||||
if (tdb_dir == NULL || !strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
|
||||
access(tdb_dir, W_OK)) {
|
||||
if (free_tdb_dir)
|
||||
free(tdb_dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp_name = strdup(device_name);
|
||||
if (!tmp_name)
|
||||
goto errout;
|
||||
dev_name = basename(tmp_name);
|
||||
tdb_file = malloc(strlen(tdb_dir) + 8 + strlen(dev_name) + 7 + 1);
|
||||
if (!tdb_file) {
|
||||
free(tmp_name);
|
||||
goto errout;
|
||||
}
|
||||
sprintf(tdb_file, "%s/debugfs-%s.e2undo", tdb_dir, dev_name);
|
||||
free(tmp_name);
|
||||
|
||||
if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
|
||||
retval = errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
set_undo_io_backing_manager(*io_ptr);
|
||||
*io_ptr = undo_io_manager;
|
||||
retval = set_undo_io_backup_file(tdb_file);
|
||||
if (retval)
|
||||
goto errout;
|
||||
printf("Overwriting existing filesystem; this can be undone "
|
||||
"using the command:\n"
|
||||
" e2undo %s %s\n\n", tdb_file, device_name);
|
||||
|
||||
if (free_tdb_dir)
|
||||
free(tdb_dir);
|
||||
free(tdb_file);
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
if (free_tdb_dir)
|
||||
free(tdb_dir);
|
||||
free(tdb_file);
|
||||
err:
|
||||
com_err("debugfs", retval, "while trying to setup undo file\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void open_filesystem(char *device, int open_flags, blk64_t superblock,
|
||||
blk64_t blocksize, int catastrophic,
|
||||
char *data_filename)
|
||||
char *data_filename, char *undo_file)
|
||||
{
|
||||
int retval;
|
||||
io_channel data_io = 0;
|
||||
io_manager io_ptr = unix_io_manager;
|
||||
|
||||
if (superblock != 0 && blocksize == 0) {
|
||||
com_err(device, 0, "if you specify the superblock, you must also specify the block size");
|
||||
|
@ -84,8 +161,14 @@ static void open_filesystem(char *device, int open_flags, blk64_t superblock,
|
|||
if (catastrophic)
|
||||
open_flags |= EXT2_FLAG_SKIP_MMP;
|
||||
|
||||
if (undo_file) {
|
||||
retval = debugfs_setup_tdb(device, undo_file, &io_ptr);
|
||||
if (retval)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
retval = ext2fs_open(device, open_flags, superblock, blocksize,
|
||||
unix_io_manager, ¤t_fs);
|
||||
io_ptr, ¤t_fs);
|
||||
if (retval) {
|
||||
com_err(device, retval, "while opening filesystem");
|
||||
if (retval == EXT2_ET_BAD_MAGIC)
|
||||
|
@ -136,9 +219,10 @@ void do_open_filesys(int argc, char **argv)
|
|||
blk64_t blocksize = 0;
|
||||
int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS;
|
||||
char *data_filename = 0;
|
||||
char *undo_file = NULL;
|
||||
|
||||
reset_getopt();
|
||||
while ((c = getopt (argc, argv, "iwfecb:s:d:D")) != EOF) {
|
||||
while ((c = getopt(argc, argv, "iwfecb:s:d:Dz:")) != EOF) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
open_flags |= EXT2_FLAG_IMAGE_FILE;
|
||||
|
@ -177,6 +261,9 @@ void do_open_filesys(int argc, char **argv)
|
|||
if (err)
|
||||
return;
|
||||
break;
|
||||
case 'z':
|
||||
undo_file = optarg;
|
||||
break;
|
||||
default:
|
||||
goto print_usage;
|
||||
}
|
||||
|
@ -188,7 +275,7 @@ void do_open_filesys(int argc, char **argv)
|
|||
return;
|
||||
open_filesystem(argv[optind], open_flags,
|
||||
superblock, blocksize, catastrophic,
|
||||
data_filename);
|
||||
data_filename, undo_file);
|
||||
return;
|
||||
|
||||
print_usage:
|
||||
|
@ -2219,7 +2306,7 @@ int main(int argc, char **argv)
|
|||
"Usage: %s [-b blocksize] [-s superblock] [-f cmd_file] "
|
||||
"[-R request] [-V] ["
|
||||
#ifndef READ_ONLY
|
||||
"[-w] "
|
||||
"[-w] [-z undo_file] "
|
||||
#endif
|
||||
"[-c] device]";
|
||||
int c;
|
||||
|
@ -2234,7 +2321,8 @@ int main(int argc, char **argv)
|
|||
#ifdef READ_ONLY
|
||||
const char *opt_string = "nicR:f:b:s:Vd:D";
|
||||
#else
|
||||
const char *opt_string = "niwcR:f:b:s:Vd:D";
|
||||
const char *opt_string = "niwcR:f:b:s:Vd:Dz:";
|
||||
char *undo_file = NULL;
|
||||
#endif
|
||||
|
||||
if (debug_prog_name == 0)
|
||||
|
@ -2291,6 +2379,9 @@ int main(int argc, char **argv)
|
|||
fprintf(stderr, "\tUsing %s\n",
|
||||
error_message(EXT2_ET_BASE));
|
||||
exit(0);
|
||||
case 'z':
|
||||
undo_file = optarg;
|
||||
break;
|
||||
default:
|
||||
com_err(argv[0], 0, usage, debug_prog_name);
|
||||
return 1;
|
||||
|
@ -2299,7 +2390,7 @@ int main(int argc, char **argv)
|
|||
if (optind < argc)
|
||||
open_filesystem(argv[optind], open_flags,
|
||||
superblock, blocksize, catastrophic,
|
||||
data_filename);
|
||||
data_filename, undo_file);
|
||||
|
||||
sci_idx = ss_create_invocation(debug_prog_name, "0.0", (char *) NULL,
|
||||
&debug_cmds, &retval);
|
||||
|
|
Loading…
Reference in New Issue