diff options
author | Phillip Susi <psusi@ubuntu.com> | 2013-12-16 11:33:19 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-12-26 00:20:40 -0500 |
commit | 22b83f628080088fb901b1d001ed47f0de64cd93 (patch) | |
tree | ec8f0a38015784fbea096b0c97b4655865f0870f | |
parent | 6b5535f40974d522e827c83d02d005ac5c8b5056 (diff) | |
download | android_external_e2fsprogs-22b83f628080088fb901b1d001ed47f0de64cd93.tar.gz android_external_e2fsprogs-22b83f628080088fb901b1d001ed47f0de64cd93.tar.bz2 android_external_e2fsprogs-22b83f628080088fb901b1d001ed47f0de64cd93.zip |
e2image: perform in-place move
If given at least one offset and only one file, assume source
and dest are the same, and do an in place move.
Signed-off-by: Phillip Susi <psusi@ubuntu.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | misc/e2image.8.in | 3 | ||||
-rw-r--r-- | misc/e2image.c | 71 | ||||
-rw-r--r-- | tests/i_e2image/script | 2 |
3 files changed, 69 insertions, 7 deletions
diff --git a/misc/e2image.8.in b/misc/e2image.8.in index ba97ef80..f04dda23 100644 --- a/misc/e2image.8.in +++ b/misc/e2image.8.in @@ -237,6 +237,9 @@ MiB for a partition table with: \ \fBe2image -arO 1048576 /dev/sda1 img\fR .br .PP +If you specify at least one offset, and only one file, an in-place +move will be performed, allowing you to safely move the filesystem +from one offset to another. .SH AUTHOR .B e2image was written by Theodore Ts'o (tytso@mit.edu). diff --git a/misc/e2image.c b/misc/e2image.c index 2f80efff..bf5033a9 100644 --- a/misc/e2image.c +++ b/misc/e2image.c @@ -56,6 +56,7 @@ static char all_data; static char output_is_blk; /* writing to blk device: don't skip zeroed blocks */ blk64_t source_offset, dest_offset; +char move_mode; static void lseek_error_and_exit(int errnum) { @@ -492,6 +493,9 @@ static void output_meta_data_blocks(ext2_filsys fs, int fd) blk64_t blk; char *buf, *zero_buf; int sparse = 0; + blk64_t start = 0; + blk64_t distance = 0; + blk64_t end = ext2fs_blocks_count(fs->super); retval = ext2fs_get_mem(fs->blocksize, &buf); if (retval) { @@ -503,7 +507,19 @@ static void output_meta_data_blocks(ext2_filsys fs, int fd) com_err(program_name, retval, "while allocating buffer"); exit(1); } - for (blk = 0; blk < ext2fs_blocks_count(fs->super); blk++) { + /* when doing an in place move to the right, you can't start + at the beginning or you will overwrite data, so instead + divide the fs up into distance size chunks and write them + in reverse. */ + if (move_mode && dest_offset > source_offset) { + distance = (dest_offset - source_offset) / fs->blocksize; + if (distance < ext2fs_blocks_count(fs->super)) + start = ext2fs_blocks_count(fs->super) - distance; + } +more_blocks: + if (distance) + ext2fs_llseek (fd, (start * fs->blocksize) + dest_offset, SEEK_SET); + for (blk = start; blk < end; blk++) { if ((blk >= fs->super->s_first_data_block) && ext2fs_test_block_bitmap2(meta_block_map, blk)) { retval = io_channel_read_blk64(fs->io, blk, 1, buf); @@ -532,9 +548,31 @@ static void output_meta_data_blocks(ext2_filsys fs, int fd) } } } + if (distance && start) { + if (start < distance) { + end = start; + start = 0; + } else { + end -= distance; + start -= distance; + if (end < distance) { + /* past overlap, do rest in one go */ + end = start; + start = 0; + } + } + sparse = 0; + goto more_blocks; + } #ifdef HAVE_FTRUNCATE64 if (sparse) { - ext2_loff_t offset = ext2fs_llseek(fd, sparse, SEEK_CUR); + ext2_loff_t offset; + if (distance) + offset = ext2fs_llseek( + fd, + fs->blocksize * ext2fs_blocks_count(fs->super) + dest_offset, + SEEK_SET); + else offset = ext2fs_llseek(fd, sparse, SEEK_CUR); if (offset < 0) lseek_error_and_exit(errno); @@ -542,7 +580,7 @@ static void output_meta_data_blocks(ext2_filsys fs, int fd) write_block(fd, zero_buf, -1, 1, -1); } #else - if (sparse) + if (sparse && !distance) write_block(fd, zero_buf, sparse-1, 1, -1); #endif ext2fs_free_mem(&zero_buf); @@ -1312,7 +1350,10 @@ int main (int argc, char ** argv) default: usage(); } - if (optind != argc - 2 ) + if (optind == argc - 1 && + (source_offset || dest_offset)) + move_mode = 1; + else if (optind != argc - 2 ) usage(); if (all_data && !img_type) { @@ -1325,8 +1366,20 @@ int main (int argc, char ** argv) "Offsets are only allowed with raw images."); exit(1); } + if (move_mode && img_type != E2IMAGE_RAW) { + com_err(program_name, 0, + "Move mode is only allowed with raw images."); + exit(1); + } + if (move_mode && !all_data) { + com_err(program_name, 0, + "Move mode requires all data mode."); + exit(1); + } device_name = argv[optind]; - image_fn = argv[optind+1]; + if (move_mode) + image_fn = device_name; + else image_fn = argv[optind+1]; retval = ext2fs_check_if_mounted(device_name, &mount_flags); if (retval) { @@ -1373,10 +1426,14 @@ skip_device: if (strcmp(image_fn, "-") == 0) fd = 1; else { - fd = ext2fs_open_file(image_fn, O_CREAT|O_TRUNC|O_WRONLY, 0600); + int o_flags = O_CREAT|O_WRONLY; + + if (img_type != E2IMAGE_RAW) + o_flags |= O_TRUNC; + fd = ext2fs_open_file(image_fn, o_flags, 0600); if (fd < 0) { com_err(program_name, errno, - _("while trying to open %s"), argv[optind+1]); + _("while trying to open %s"), image_fn); exit(1); } } diff --git a/tests/i_e2image/script b/tests/i_e2image/script index 0315ae20..adf59a46 100644 --- a/tests/i_e2image/script +++ b/tests/i_e2image/script @@ -20,6 +20,7 @@ for i in $ORIG_IMAGES; do bunzip2 < $SRCDIR/$ORIG_IMG.bz2 > $i md5sum $i >> $MD5_TMP + rm -f $RAW_IMG echo "e2image -r $ORIG_IMG $RAW_IMG" $E2IMAGE -r $i $RAW_IMG md5sum $RAW_IMG >> $MD5_TMP @@ -28,6 +29,7 @@ for i in $ORIG_IMAGES; do $E2IMAGE -Q $i $QCOW2_IMG md5sum $QCOW2_IMG >> $MD5_TMP + rm -f $QCOW2_TO_RAW echo "e2image -r $QCOW2_IMG $QCOW2_TO_RAW" $E2IMAGE -r $i $QCOW2_TO_RAW md5sum $QCOW2_TO_RAW >> $MD5_TMP |