Whamcloud - gitweb
e2image.c, e2image.8.in: Add support for the -s option which
authorTheodore Ts'o <tytso@mit.edu>
Wed, 19 Jan 2005 05:26:43 +0000 (00:26 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 19 Jan 2005 05:26:43 +0000 (00:26 -0500)
scrambles directory entries for raw image files.

misc/ChangeLog
misc/e2image.8.in
misc/e2image.c

index c8356f8..5812a98 100644 (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
index 45ee272..4b75e6d 100644 (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,10 +45,41 @@ 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
+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
+layout (which can be generated using the using
+.B fdisk \-l
+command).  Ideally the image file should be stored on some filesystem
+other that
+the filesystem whose data it contains, to ensure that its data is
+accessible in the case where the filesystem has been badly damaged.
+.PP
+To save disk space, 
+.B e2image
+creates the image file as a sparse file.  
+Hence, if the image file
+needs to be copied to another location, it should
+either be compressed first or copied using the 
+.B \-\-sparse=always
+option to GNU version of 
+.BR cp .  
+.PP
+The size of an ext2 image file depends primarily on the size of the
+filesystems and how many inodes are in use.  For a typical 10 gigabyte
+filesystem, with 200,000 inodes in use out of 1.2 million inodes, the
+image file be approximately 35 megabytes; a 4 gigabyte filesystem with
+15,000 inodes in use out of 550,000 inodes will result in a 3 megabyte
+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 to the device.    It can be used to restore the filesystem metadata
+file back to the device.    It can be used to restore the filesystem metadata
 back to the device in emergency situations.
 .PP
 .B WARNING!!!!
@@ -62,6 +93,7 @@ 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.  
@@ -74,37 +106,25 @@ 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,
+blocks and directory blocks, which the standard 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
-layout (which can be generated using the using
-.B fdisk \-l
-command).  Ideally the image file should be stored on some filesystem
-other that
-the filesystem whose data it contains, to ensure that its data is
-accessible in the case where the filesystem has been badly damaged.
+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
-To save disk space, 
-.B e2image
-creates the image file as a sparse file.  
-Hence, if the image file
-needs to be copied to another location, it should
-either be compressed first or copied using the 
-.B \-\-sparse=always
-option to GNU version of 
-.BR cp .  
+.br
+\      \fBe2image -r /dev/hda1 - | bzip2 > hda1.e2i.bz2\fR
 .PP
-The size of an ext2 image file depends primarily on the size of the
-filesystems and how many inodes are in use.  For a typical 10 gigabyte
-filesystem, with 200,000 inodes in use out of 1.2 million inodes, the
-image file be approximately 35 megabytes; a 4 gigabyte filesystem with
-15,000 inodes in use out of 550,000 inodes will result in a 3 megabyte
-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.
+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 
index 9ff3510..cd71431 100644 (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);