OSDN Git Service

e2image: add -a switch to include all data
authorPhillip Susi <psusi@ubuntu.com>
Tue, 15 Jan 2013 20:31:23 +0000 (15:31 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 16 Jan 2013 19:09:20 +0000 (14:09 -0500)
Normally the raw and QCOW2 images only contain fs metadata.
Add a new switch ( -a ) to include all data.  This makes it
possible to use e2image to clone a whole filesystem.

Signed-off-by: Phillip Susi <psusi@ubuntu.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
misc/e2image.8.in
misc/e2image.c

index 8876e77..0972826 100644 (file)
@@ -8,7 +8,7 @@ e2image \- Save critical ext2/ext3/ext4 filesystem metadata to a file
 .SH SYNOPSIS
 .B e2image
 [
-.B \-rsI
+.B \-rsIQa
 ]
 .I device
 .I image-file
@@ -171,6 +171,26 @@ is regular QCOW2 image and can be processed by tools aware of QCOW2 format
 such as for example
 .BR qemu-img .
 .PP
+You can convert a qcow2 image into a raw image with:
+.PP
+.br
+\      \fBe2image \-r hda1.qcow2 hda1.raw\fR
+.br
+.PP
+This can be useful to write a qcow2 image containing all data to a
+sparse image file where it can be loop mounted, or to a disk partition.
+Note that this may not work with qcow2 images not generated by e2image.
+.PP
+.SH INCLUDING DATA
+Normally
+.B e2image
+only includes fs metadata, not regular file data.  The
+.B \-a
+option can be specified to include all data.  This will
+give an image that is suitible to use to clone the entire FS or
+for backup purposes.  Note that this option only works with the
+raw or QCOW2 formats.
+.PP
 .SH AUTHOR
 .B e2image
 was written by Theodore Ts'o (tytso@mit.edu).
index e6ea52a..b1badda 100644 (file)
@@ -52,6 +52,9 @@ extern int optind;
 
 const char * program_name = "e2image";
 char * device_name = NULL;
+char all_data;
+char output_is_blk;
+/* writing to blk device: don't skip zeroed blocks */
 
 static void lseek_error_and_exit(int errnum)
 {
@@ -84,7 +87,7 @@ static int get_bits_from_size(size_t size)
 
 static void usage(void)
 {
-       fprintf(stderr, _("Usage: %s [-rsIQ] device image_file\n"),
+       fprintf(stderr, _("Usage: %s [-rsIQa] device image_file\n"),
                program_name);
        exit (1);
 }
@@ -309,7 +312,7 @@ static int process_file_block(ext2_filsys fs EXT2FS_ATTR((unused)),
                              int ref_offset EXT2FS_ATTR((unused)),
                              void *priv_data EXT2FS_ATTR((unused)))
 {
-       if (blockcnt < 0) {
+       if (blockcnt < 0 || all_data) {
                ext2fs_mark_block_bitmap2(meta_block_map, *block_nr);
                meta_blocks_count++;
        }
@@ -341,11 +344,13 @@ static void mark_table_blocks(ext2_filsys fs)
                /*
                 * Mark the blocks used for the inode table
                 */
-               if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
+               if ((output_is_blk ||
+                    !ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)) &&
                    ext2fs_inode_table_loc(fs, i)) {
                        unsigned int end = (unsigned) fs->inode_blocks_per_group;
                        /* skip unused blocks */
-                       if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+                       if (!output_is_blk &&
+                           EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
                                                       EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
                                end -= (ext2fs_bg_itable_unused(fs, i) /
                                        EXT2_INODES_PER_BLOCK(fs->super));
@@ -387,6 +392,8 @@ static int check_zero_block(char *buf, int blocksize)
        char    *cp = buf;
        int     left = blocksize;
 
+       if (output_is_blk)
+               return 0;
        while (left > 0) {
                if (*cp++)
                        return 0;
@@ -1134,7 +1141,7 @@ static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags)
                        if ((inode.i_flags & EXT4_EXTENTS_FL) ||
                            inode.i_block[EXT2_IND_BLOCK] ||
                            inode.i_block[EXT2_DIND_BLOCK] ||
-                           inode.i_block[EXT2_TIND_BLOCK]) {
+                           inode.i_block[EXT2_TIND_BLOCK] || all_data) {
                                retval = ext2fs_block_iterate3(fs,
                                       ino, BLOCK_FLAG_READ_ONLY, block_buf,
                                       process_file_block, &pb);
@@ -1249,6 +1256,7 @@ int main (int argc, char ** argv)
        int qcow2_fd = 0;
        int fd = 0;
        int ret = 0;
+       struct stat st;
 
 #ifdef ENABLE_NLS
        setlocale(LC_MESSAGES, "");
@@ -1262,7 +1270,7 @@ int main (int argc, char ** argv)
        if (argc && *argv)
                program_name = *argv;
        add_error_table(&et_ext2_error_table);
-       while ((c = getopt(argc, argv, "rsIQ")) != EOF)
+       while ((c = getopt(argc, argv, "rsIQa")) != EOF)
                switch (c) {
                case 'I':
                        flags |= E2IMAGE_INSTALL_FLAG;
@@ -1280,6 +1288,9 @@ int main (int argc, char ** argv)
                case 's':
                        flags |= E2IMAGE_SCRAMBLE_FLAG;
                        break;
+               case 'a':
+                       all_data = 1;
+                       break;
                default:
                        usage();
                }
@@ -1327,7 +1338,14 @@ skip_device:
                                         "the stdout!\n");
                exit(1);
        }
-
+       if (fd != 1) {
+               if (fstat(fd, &st)) {
+                       com_err(program_name, 0, "Can not stat output\n");
+                       exit(1);
+               }
+               if (S_ISBLK(st.st_mode))
+                       output_is_blk = 1;
+       }
        if (flags & E2IMAGE_IS_QCOW2_FLAG) {
                ret = qcow2_write_raw_image(qcow2_fd, fd, header);
                if (ret) {