e2image: only skip writing zero blocks when writing to a new file

The e2image progam was originally intended to create image files.
However, some people have started using e2image to copy a file system
from one block device to another, since it is more efficient than
using dd because it only copies the blocks which are in use.  If we
are doing this, however, we must not skip writing blocks which are all
zero in the source device, since they may not be zero in the
destination device.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: Phillip Susi <psusi@ubuntu.com>
diff --git a/lib/ext2fs/e2image.h b/lib/ext2fs/e2image.h
index 5537980..53b20cc 100644
--- a/lib/ext2fs/e2image.h
+++ b/lib/ext2fs/e2image.h
@@ -12,15 +12,6 @@
  * %End-Header%
  */
 
-/* Image types */
-#define E2IMAGE_RAW	1
-#define E2IMAGE_QCOW2	2
-
-/* Image flags */
-#define E2IMAGE_INSTALL_FLAG	1
-#define E2IMAGE_SCRAMBLE_FLAG	2
-#define E2IMAGE_IS_QCOW2_FLAG	4
-
 struct ext2_image_hdr {
 	__u32	magic_number;	/* This must be EXT2_ET_MAGIC_E2IMAGE */
 	char	magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
diff --git a/misc/e2image.c b/misc/e2image.c
index 4d9868c..67dd3e0 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -50,6 +50,15 @@
 
 #define QCOW_OFLAG_COPIED     (1LL << 63)
 
+/* Image types */
+#define E2IMAGE_RAW	1
+#define E2IMAGE_QCOW2	2
+
+/* Image flags */
+#define E2IMAGE_INSTALL_FLAG	1
+#define E2IMAGE_SCRAMBLE_FLAG	2
+#define E2IMAGE_IS_QCOW2_FLAG	4
+#define E2IMAGE_CHECK_ZERO_FLAG	8
 
 static const char * program_name = "e2image";
 static char * device_name = NULL;
@@ -495,7 +504,7 @@
 	signal (SIGINT, SIG_DFL);
 }
 
-static void output_meta_data_blocks(ext2_filsys fs, int fd)
+static void output_meta_data_blocks(ext2_filsys fs, int fd, int flags)
 {
 	errcode_t	retval;
 	blk64_t		blk;
@@ -607,7 +616,8 @@
 			if (scramble_block_map &&
 			    ext2fs_test_block_bitmap2(scramble_block_map, blk))
 				scramble_dir_block(fs, blk, buf);
-			if ((fd != 1) && check_zero_block(buf, fs->blocksize))
+			if ((flags & E2IMAGE_CHECK_ZERO_FLAG) &&
+			    check_zero_block(buf, fs->blocksize))
 				goto sparse_write;
 			if (sparse)
 				seek_relative(fd, sparse);
@@ -1291,7 +1301,7 @@
 	if (type & E2IMAGE_QCOW2)
 		output_qcow2_meta_data_blocks(fs, fd);
 	else
-		output_meta_data_blocks(fs, fd);
+		output_meta_data_blocks(fs, fd, flags);
 
 	ext2fs_free_mem(&block_buf);
 	ext2fs_close_inode_scan(scan);
@@ -1516,6 +1526,8 @@
 
 		if (img_type != E2IMAGE_RAW)
 			o_flags |= O_TRUNC;
+		if (access(image_fn, F_OK) != 0)
+			flags |= E2IMAGE_CHECK_ZERO_FLAG;
 		fd = ext2fs_open_file(image_fn, o_flags, 0600);
 		if (fd < 0) {
 			com_err(program_name, errno,