aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhillip Susi <psusi@ubuntu.com>2013-12-16 11:33:19 -0500
committerTheodore Ts'o <tytso@mit.edu>2013-12-26 00:20:40 -0500
commit22b83f628080088fb901b1d001ed47f0de64cd93 (patch)
treeec8f0a38015784fbea096b0c97b4655865f0870f
parent6b5535f40974d522e827c83d02d005ac5c8b5056 (diff)
downloadandroid_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.in3
-rw-r--r--misc/e2image.c71
-rw-r--r--tests/i_e2image/script2
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