e2image.c, e2image.8.in: Add support for the -s option which

scrambles directory entries for raw image files.
This commit is contained in:
Theodore Ts'o 2005-01-19 00:26:43 -05:00
parent 8800c73835
commit d851ed3983
3 changed files with 163 additions and 39 deletions

View File

@ -1,3 +1,8 @@
2005-01-18 Theodore Ts'o <tytso@mit.edu>
* e2image.c, e2image.8.in: Add support for the -s option which
scrambles directory entries for raw image files.
2005-01-17 Theodore Ts'o <tytso@mit.edu>
* tune2fs.c: On Solaris, defining _XOPEN_SOURCE inexplicably

View File

@ -8,7 +8,7 @@ e2image \- Save critical ext2/ext3 filesystem data to a file
.SH SYNOPSIS
.B e2image
[
.B \-rI
.B \-rsI
]
.I device
.I image-file
@ -45,38 +45,6 @@ requires random-access access to the file, which can not be done using a
pipe. This restriction will hopefully be lifted in a future version of
.BR e2image .)
.PP
The
.B \-I
option will cause e2image to install the metadata stored in the image
file to the device. It can be used to restore the filesystem metadata
back to the device in emergency situations.
.PP
.B WARNING!!!!
The
.B \-I
option should only be used as desperation measure when other
alternatives have failed. If the filesystem has changed since the image
file was created, data
.B will
be lost. In general, you should make a full image
backup of the filesystem first, in case you wish to try other recovery
strategies afterwards.
.PP
The
.B \-r
option will create a raw image file instead of a normal image file.
A raw image file differs
from a normal image file in two ways. First, the filesystem metadata is
placed in the proper position so that e2fsck, dumpe2fs, debugfs,
etc. can be run directly on the raw image file. In order to minimize
the amount of disk space consumed by a raw image file, the file is
created as a sparse file. (Beware of copying or
compressing/decompressing this file with utilities that don't understand
how to create sparse files; the file will become as large as the
filesystem itself!) Secondly, the raw image file also includes indirect
blocks and data blocks, which the current image file does not have,
although this may change in the future.
.PP
It is a very good idea to periodically (at boot time and
every week or so) to create image files for all of
filesystems on a system, as well as saving the partition
@ -106,6 +74,58 @@ image file. Image files tend to be quite
compressible; an image file taking up 32 megabytes of space on
disk will generally compress down to 3 or 4 megabytes.
.PP
.SH RESTORING FILESYSTEM METADATA USING AN IMAGE FILE
.PP
The
.B \-I
option will cause e2image to install the metadata stored in the image
file back to the device. It can be used to restore the filesystem metadata
back to the device in emergency situations.
.PP
.B WARNING!!!!
The
.B \-I
option should only be used as desperation measure when other
alternatives have failed. If the filesystem has changed since the image
file was created, data
.B will
be lost. In general, you should make a full image
backup of the filesystem first, in case you wish to try other recovery
strategies afterwards.
.PP
.SH RAW IMAGE FILES
The
.B \-r
option will create a raw image file instead of a normal image file.
A raw image file differs
from a normal image file in two ways. First, the filesystem metadata is
placed in the proper position so that e2fsck, dumpe2fs, debugfs,
etc. can be run directly on the raw image file. In order to minimize
the amount of disk space consumed by a raw image file, the file is
created as a sparse file. (Beware of copying or
compressing/decompressing this file with utilities that don't understand
how to create sparse files; the file will become as large as the
filesystem itself!) Secondly, the raw image file also includes indirect
blocks and directory blocks, which the standard image file does not have,
although this may change in the future.
.PP
Raw image files are sometimes used when sending filesystems to as part
of bug reports to e2fsprogs. When used in this capacity, the
recommended command is (replace hda1 with appropriate device):
.PP
.br
\ \fBe2image -r /dev/hda1 - | bzip2 > hda1.e2i.bz2\fR
.PP
This will only send the metadata information, without any data blocks.
However, the filenames in the directory blocks can still reveal
information about the contents of the filesystem that the bug reporter
may wish to keep confidential. To address this concern, the
.B \-s
option can be specified. This will cause
.B e2image
to scramble directory entries and zero out any unused portions
of the directory blocks before writing them to the image file.
.PP
.SH AUTHOR
.B e2image
was written by Theodore Ts'o (tytso@mit.edu).

View File

@ -47,7 +47,8 @@ char * device_name = NULL;
static void usage(void)
{
fprintf(stderr, _("Usage: %s [-r] device image_file\n"), program_name);
fprintf(stderr, _("Usage: %s [-rsI] device image_file\n"),
program_name);
exit (1);
}
@ -146,9 +147,11 @@ static void write_image_file(ext2_filsys fs, int fd)
* These set of functions are used to write a RAW image file.
*/
ext2fs_block_bitmap meta_block_map;
ext2fs_block_bitmap scramble_block_map; /* Directory blocks to be scrambled */
struct process_block_struct {
ext2_ino_t ino;
int is_dir;
};
/*
@ -216,7 +219,15 @@ static int process_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data EXT2FS_ATTR((unused)))
{
struct process_block_struct *p;
p = (struct process_block_struct *) priv_data;
printf("block %d, ino %d, is_dir=%d\n", *block_nr, p->ino, p->is_dir);
ext2fs_mark_block_bitmap(meta_block_map, *block_nr);
if (scramble_block_map && p->is_dir && blockcnt >= 0)
ext2fs_mark_block_bitmap(scramble_block_map, *block_nr);
return 0;
}
@ -326,14 +337,83 @@ static void write_block(int fd, char *buf, int sparse_offset,
}
}
int name_id[256];
static void scramble_dir_block(ext2_filsys fs, blk_t blk, char *buf)
{
char *p, *end, *cp;
struct ext2_dir_entry_2 *dirent;
int rec_len, id, len;
printf("Scrambling directory block %d\n", blk);
end = buf + fs->blocksize;
for (p = buf; p < end-8; p += rec_len) {
dirent = (struct ext2_dir_entry_2 *) p;
rec_len = dirent->rec_len;
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & EXT2_FLAG_SWAP_BYTES)
rec_len = ext2fs_swab16(rec_len);
#endif
#if 0
printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len);
#endif
if (rec_len < 8 || (rec_len % 4) ||
(p+rec_len > end)) {
printf("Corrupt directory block %lu: "
"bad rec_len (%d)\n", blk, rec_len);
rec_len = end - p;
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & EXT2_FLAG_SWAP_BYTES)
dirent->rec_len = ext2fs_swab16(rec_len);
#endif
continue;
}
if (dirent->name_len + 8 > rec_len) {
printf("Corrupt directory block %lu: "
"bad name_len (%d)\n", blk, dirent->name_len);
dirent->name_len = rec_len - 8;
continue;
}
if (dirent->name_len==1 && p[8] == '.')
continue;
if (dirent->name_len==2 && p[8] == '.' && p[9] == '.')
continue;
cp = p+8;
memset(cp, 'A', dirent->name_len);
len = rec_len - dirent->name_len - 8;
if (len > 0)
memset(cp+dirent->name_len, 0, len);
len = dirent->name_len;
id = name_id[len]++;
while ((len > 0) && (id > 0)) {
*cp += id % 26;
id = id / 26;
cp++;
len--;
}
}
}
static void output_meta_data_blocks(ext2_filsys fs, int fd)
{
errcode_t retval;
blk_t blk;
char buf[8192], zero_buf[8192];
char *buf, *zero_buf;
int sparse = 0;
memset(zero_buf, 0, sizeof(zero_buf));
buf = malloc(fs->blocksize);
if (!buf) {
com_err(program_name, ENOMEM, "while allocating buffer");
exit(1);
}
zero_buf = malloc(fs->blocksize);
if (!zero_buf) {
com_err(program_name, ENOMEM, "while allocating buffer");
exit(1);
}
memset(zero_buf, 0, fs->blocksize);
for (blk = 0; blk < fs->super->s_blocks_count; blk++) {
if ((blk >= fs->super->s_first_data_block) &&
ext2fs_test_block_bitmap(meta_block_map, blk)) {
@ -342,6 +422,9 @@ static void output_meta_data_blocks(ext2_filsys fs, int fd)
com_err(program_name, retval,
"error reading block %d", blk);
}
if (scramble_block_map &&
ext2fs_test_block_bitmap(scramble_block_map, blk))
scramble_dir_block(fs, blk, buf);
if ((fd != 1) && check_zero_block(buf, fs->blocksize))
goto sparse_write;
write_block(fd, buf, sparse, fs->blocksize, blk);
@ -363,7 +446,7 @@ static void output_meta_data_blocks(ext2_filsys fs, int fd)
write_block(fd, zero_buf, sparse, 1, -1);
}
static void write_raw_image_file(ext2_filsys fs, int fd)
static void write_raw_image_file(ext2_filsys fs, int fd, int scramble_flag)
{
struct process_block_struct pb;
struct ext2_inode inode;
@ -378,6 +461,16 @@ static void write_raw_image_file(ext2_filsys fs, int fd)
com_err(program_name, retval, "while allocating block bitmap");
exit(1);
}
if (scramble_flag) {
retval = ext2fs_allocate_block_bitmap(fs, "scramble block map",
&scramble_block_map);
if (retval) {
com_err(program_name, retval,
"while allocating scramble block bitmap");
exit(1);
}
}
mark_table_blocks(fs);
@ -416,6 +509,8 @@ static void write_raw_image_file(ext2_filsys fs, int fd)
continue;
stashed_ino = ino;
pb.ino = ino;
pb.is_dir = LINUX_S_ISDIR(inode.i_mode);
if (LINUX_S_ISDIR(inode.i_mode) ||
(LINUX_S_ISLNK(inode.i_mode) &&
ext2fs_inode_has_valid_blocks(&inode)) ||
@ -523,6 +618,7 @@ int main (int argc, char ** argv)
int open_flag = 0;
int raw_flag = 0;
int install_flag = 0;
int scramble_flag = 0;
int fd = 0;
#ifdef ENABLE_NLS
@ -536,11 +632,14 @@ int main (int argc, char ** argv)
if (argc && *argv)
program_name = *argv;
initialize_ext2_error_table();
while ((c = getopt (argc, argv, "rI")) != EOF)
while ((c = getopt (argc, argv, "rsI")) != EOF)
switch (c) {
case 'r':
raw_flag++;
break;
case 's':
scramble_flag++;
break;
case 'I':
install_flag++;
break;
@ -582,7 +681,7 @@ int main (int argc, char ** argv)
}
if (raw_flag)
write_raw_image_file(fs, fd);
write_raw_image_file(fs, fd, scramble_flag);
else
write_image_file(fs, fd);