X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=misc%2Fe2image.c;h=83ae6335b27ee3caaa3e7af744436a9ba68548b8;hb=a691f8d844faca28524b7c55780873244a070be7;hp=5e38bb07f846a297266f6d0fe20e6f56c715b069;hpb=737a88673d709d5b1375d589f790367121a59a42;p=tools%2Fe2fsprogs.git diff --git a/misc/e2image.c b/misc/e2image.c index 5e38bb0..83ae633 100644 --- a/misc/e2image.c +++ b/misc/e2image.c @@ -10,8 +10,12 @@ * %End-Header% */ +#ifndef _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE +#endif #include "config.h" #include @@ -39,14 +43,16 @@ extern int optind; #include "ext2fs/ext2_fs.h" #include "ext2fs/ext2fs.h" +#include "ext2fs/ext2fsP.h" #include "et/com_err.h" #include "uuid/uuid.h" #include "e2p/e2p.h" #include "ext2fs/e2image.h" #include "ext2fs/qcow2.h" +#include "support/nls-enable.h" +#include "support/plausible.h" #include "../version.h" -#include "nls-enable.h" #define QCOW_OFLAG_COPIED (1LL << 63) #define NO_BLK ((blk64_t) -1) @@ -98,8 +104,11 @@ static int get_bits_from_size(size_t size) static void usage(void) { - fprintf(stderr, _("Usage: %s [-acfnprsIQ] [-o src_offset] " - "[-O dest_offset] \\\n\tdevice image_file\n"), + fprintf(stderr, _("Usage: %s [ -r|Q ] [ -f ] device image-file\n"), + program_name); + fprintf(stderr, _(" %s -I device image-file\n"), program_name); + fprintf(stderr, _(" %s -ra [ -cfnp ] [ -o src_offset ] " + "[ -O dest_offset ] src_fs [ dest_fs ]\n"), program_name); exit (1); } @@ -162,15 +171,16 @@ static void generic_write(int fd, void *buf, int blocksize, blk64_t block) free_buf = 1; err = ext2fs_get_arrayzero(1, blocksize, &buf); if (err) { - com_err(program_name, err, + com_err(program_name, err, "%s", _("while allocating buffer")); exit(1); } } if (nop_flag) { printf(_("Writing block %llu\n"), (unsigned long long) block); - seek_relative(fd, blocksize); - return; + if (fd != 1) + seek_relative(fd, blocksize); + goto free_and_return; } count = write(fd, buf, blocksize); if (count != blocksize) { @@ -183,10 +193,12 @@ static void generic_write(int fd, void *buf, int blocksize, blk64_t block) com_err(program_name, err, _("error writing block %llu"), block); else - com_err(program_name, err, _("error in write()")); + com_err(program_name, err, "%s", + _("error in generic_write()")); exit(1); } +free_and_return: if (free_buf) ext2fs_free_mem(&buf); } @@ -228,7 +240,7 @@ static void write_image_file(ext2_filsys fs, int fd) write_header(fd, NULL, sizeof(struct ext2_image_hdr), fs->blocksize); memset(&hdr, 0, sizeof(struct ext2_image_hdr)); - hdr.offset_super = seek_relative(fd, 0); + hdr.offset_super = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_super_write(fs, fd, 0); if (retval) { com_err(program_name, retval, "%s", @@ -236,7 +248,7 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.offset_inode = seek_relative(fd, 0); + hdr.offset_inode = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_inode_write(fs, fd, (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0); if (retval) { @@ -245,7 +257,7 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.offset_blockmap = seek_relative(fd, 0); + hdr.offset_blockmap = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_bitmap_write(fs, fd, 0); if (retval) { com_err(program_name, retval, "%s", @@ -253,7 +265,7 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.offset_inodemap = seek_relative(fd, 0); + hdr.offset_inodemap = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP); if (retval) { com_err(program_name, retval, "%s", @@ -261,23 +273,23 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE; + hdr.magic_number = ext2fs_cpu_to_le32(EXT2_ET_MAGIC_E2IMAGE); strcpy(hdr.magic_descriptor, "Ext2 Image 1.0"); gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname)); strncpy(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name)-1); hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0; - hdr.fs_blocksize = fs->blocksize; + hdr.fs_blocksize = ext2fs_cpu_to_le32(fs->blocksize); if (stat(device_name, &st) == 0) - hdr.fs_device = st.st_rdev; + hdr.fs_device = ext2fs_cpu_to_le32(st.st_rdev); if (fstat(fd, &st) == 0) { - hdr.image_device = st.st_dev; - hdr.image_inode = st.st_ino; + hdr.image_device = ext2fs_cpu_to_le32(st.st_dev); + hdr.image_inode = ext2fs_cpu_to_le32(st.st_ino); } memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid)); - hdr.image_time = time(0); + hdr.image_time = ext2fs_cpu_to_le32(time(0)); write_header(fd, &hdr, sizeof(struct ext2_image_hdr), fs->blocksize); } @@ -413,9 +425,7 @@ static void mark_table_blocks(ext2_filsys fs) ext2fs_inode_table_loc(fs, i)) { unsigned int end = (unsigned) fs->inode_blocks_per_group; /* skip unused blocks */ - if (!output_is_blk && - EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) + if (!output_is_blk && ext2fs_has_group_desc_csum(fs)) end -= (ext2fs_bg_itable_unused(fs, i) / EXT2_INODES_PER_BLOCK(fs->super)); for (j = 0, b = ext2fs_inode_table_loc(fs, i); @@ -540,6 +550,16 @@ static void sigint_handler(int unused EXT2FS_ATTR((unused))) signal (SIGINT, SIG_DFL); } +#define calc_percent(a, b) ((int) ((100.0 * (((float) (a)) / \ + ((float) (b)))) + 0.5)) +#define calc_rate(t, b, d) (((float)(t) / ((1024 * 1024) / (b))) / (d)) + +static int print_progress(blk64_t num, blk64_t total) +{ + return fprintf(stderr, _("%llu / %llu blocks (%d%%)"), num, total, + calc_percent(num, total)); +} + static void output_meta_data_blocks(ext2_filsys fs, int fd, int flags) { errcode_t retval; @@ -556,21 +576,20 @@ static void output_meta_data_blocks(ext2_filsys fs, int fd, int flags) retval = ext2fs_get_mem(fs->blocksize, &buf); if (retval) { - com_err(program_name, retval, _("while allocating buffer")); + com_err(program_name, retval, "%s", + _("while allocating buffer")); exit(1); } retval = ext2fs_get_memzero(fs->blocksize, &zero_buf); if (retval) { - com_err(program_name, retval, _("while allocating buffer")); + com_err(program_name, retval, "%s", + _("while allocating buffer")); exit(1); } if (show_progress) { - printf(_("Copying ")); - bscount = printf(_("%llu / %llu blocks (%llu%%)"), - total_written, - meta_blocks_count, - (total_written + 50) / ((meta_blocks_count + 50) / 100)); - fflush(stdout); + fprintf(stderr, "%s", _("Copying ")); + bscount = print_progress(total_written, meta_blocks_count); + fflush(stderr); last_update = time(NULL); start_time = time(NULL); } @@ -592,26 +611,26 @@ more_blocks: if (got_sigint) { if (distance) { /* moving to the right */ - if (distance >= ext2fs_blocks_count(fs->super) || - start == ext2fs_blocks_count(fs->super) - distance) - kill (getpid(), SIGINT); + if (distance >= ext2fs_blocks_count(fs->super)|| + start == ext2fs_blocks_count(fs->super) - + distance) + kill(getpid(), SIGINT); } else { /* moving to the left */ - if (blk < (source_offset - dest_offset) / fs->blocksize) - kill (getpid(), SIGINT); + if (blk < (source_offset - dest_offset) / + fs->blocksize) + kill(getpid(), SIGINT); } if (show_progress) - printf ("\r"); - printf(_("Stopping now will destroy the filesystem, " + fputc('\r', stderr); + fprintf(stderr, "%s", + _("Stopping now will destroy the filesystem, " "interrupt again if you are sure\n")); if (show_progress) { - printf(_("Copying ")); - bscount = printf(_("%llu / %llu blocks (%llu%%)"), - total_written, - meta_blocks_count, - (total_written + 50) / ((meta_blocks_count + 50) - / 100)); - fflush(stdout); + fprintf(stderr, "%s", _("Copying ")); + bscount = print_progress(total_written, + meta_blocks_count); + fflush(stderr); } got_sigint = 0; @@ -620,26 +639,23 @@ more_blocks: time_t duration; last_update = time(NULL); while (bscount--) - printf("\b"); - bscount = printf(_("%llu / %llu blocks (%llu%%)"), - total_written, - meta_blocks_count, - (total_written + 50) / - ((meta_blocks_count + 50) / 100)); + fputc('\b', stderr); + bscount = print_progress(total_written, + meta_blocks_count); duration = time(NULL) - start_time; - if (duration > 5) { - time_t est = (duration * - meta_blocks_count / total_written) - - (duration); + if (duration > 5 && total_written) { + time_t est = (duration * meta_blocks_count / + total_written) - duration; char buff[30]; strftime(buff, 30, "%T", gmtime(&est)); - bscount += printf(_(" %s remaining at %.2f MB/s"), - buff, - ((float)total_written / - ((1024 * 1024) / fs->blocksize)) / - duration); + bscount += + fprintf(stderr, + _(" %s remaining at %.2f MB/s"), + buff, calc_rate(total_written, + fs->blocksize, + duration)); } - fflush (stdout); + fflush (stderr); } if ((blk >= fs->super->s_first_data_block) && ext2fs_test_block_bitmap2(meta_block_map, blk)) { @@ -666,7 +682,9 @@ more_blocks: } else { sparse_write: if (fd == 1) { - generic_write(fd, zero_buf, fs->blocksize, blk); + if (!nop_flag) + generic_write(fd, zero_buf, + fs->blocksize, blk); continue; } sparse += fs->blocksize; @@ -696,19 +714,15 @@ more_blocks: if (show_progress) { time_t duration = time(NULL) - start_time; char buff[30]; - while (bscount--) - printf("\b"); + fputc('\r', stderr); strftime(buff, 30, "%T", gmtime(&duration)); - printf(_("\b\b\b\b\b\b\b\bCopied %llu / %llu blocks (%llu%%) " - "in %s at %.2f MB/s \n"), - total_written, - meta_blocks_count, - (total_written + 50) / ((meta_blocks_count + 50) / 100), - buff, - ((float)total_written / - ((1024 * 1024) / fs->blocksize)) / - duration); - + fprintf(stderr, _("Copied %llu / %llu blocks (%d%%) in %s "), + total_written, meta_blocks_count, + calc_percent(total_written, meta_blocks_count), buff); + if (duration) + fprintf(stderr, _("at %.2f MB/s"), + calc_rate(total_written, fs->blocksize, duration)); + fputs(" \n", stderr); } #ifdef HAVE_FTRUNCATE64 if (sparse) { @@ -741,7 +755,8 @@ static void init_l1_table(struct ext2_qcow2_image *image) ret = ext2fs_get_arrayzero(image->l1_size, sizeof(__u64), &l1_table); if (ret) { - com_err(program_name, ret, _("while allocating l1 table")); + com_err(program_name, ret, "%s", + _("while allocating l1 table")); exit(1); } @@ -786,7 +801,7 @@ static void init_l2_cache(struct ext2_qcow2_image *image) return; alloc_err: - com_err(program_name, ret, _("while allocating l2 cache")); + com_err(program_name, ret, "%s", _("while allocating l2 cache")); exit(1); } @@ -809,9 +824,10 @@ again: } if (cache->free != cache->count) { - fprintf(stderr, _("Warning: There are still tables in the " - "cache while putting the cache, data will " - "be lost so the image may not be valid.\n")); + fprintf(stderr, "%s", _("Warning: There are still tables in " + "the cache while putting the cache, " + "data will be lost so the image may " + "not be valid.\n")); table = cache->used_head; cache->used_head = NULL; goto again; @@ -1093,7 +1109,7 @@ static int update_refcount(int fd, struct ext2_qcow2_image *img, /* * We are relying on the fact that we are creating the qcow2 * image sequentially, hence we will always allocate refcount - * block items sequentialy. + * block items sequentially. */ ref->refcount_block[ref->refcount_block_index] = ext2fs_cpu_to_be16(1); ref->refcount_block_index++; @@ -1129,14 +1145,14 @@ static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd) /* allocate struct ext2_qcow2_image */ retval = ext2fs_get_mem(sizeof(struct ext2_qcow2_image), &img); if (retval) { - com_err(program_name, retval, + com_err(program_name, retval, "%s", _("while allocating ext2_qcow2_image")); exit(1); } retval = initialize_qcow2_image(fd, fs, img); if (retval) { - com_err(program_name, retval, + com_err(program_name, retval, "%s", _("while initializing ext2_qcow2_image")); exit(1); } @@ -1162,7 +1178,8 @@ static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd) retval = ext2fs_get_mem(fs->blocksize, &buf); if (retval) { - com_err(program_name, retval, _("while allocating buffer")); + com_err(program_name, retval, "%s", + _("while allocating buffer")); exit(1); } /* Write qcow2 data blocks */ @@ -1194,9 +1211,10 @@ static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd) * block should not be created! */ if (update_refcount(fd, img, offset, offset)) { - fprintf(stderr, _("Programming error: " - "multiple sequential refcount " - "blocks created!\n")); + fprintf(stderr, "%s", + _("Programming error: multiple " + "sequential refcount blocks " + "created!\n")); exit(1); } } @@ -1211,7 +1229,7 @@ static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd) offset += img->cluster_size; if (update_refcount(fd, img, offset, offset)) { - fprintf(stderr, + fprintf(stderr, "%s", _("Programming error: multiple sequential refcount " "blocks created!\n")); exit(1); @@ -1251,7 +1269,7 @@ static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags) retval = ext2fs_allocate_block_bitmap(fs, _("in-use block map"), &meta_block_map); if (retval) { - com_err(program_name, retval, + com_err(program_name, retval, "%s", _("while allocating block bitmap")); exit(1); } @@ -1260,7 +1278,7 @@ static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags) retval = ext2fs_allocate_block_bitmap(fs, "scramble block map", &scramble_block_map); if (retval) { - com_err(program_name, retval, + com_err(program_name, retval, "%s", _("while allocating scramble block bitmap")); exit(1); } @@ -1268,11 +1286,11 @@ static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags) mark_table_blocks(fs); if (show_progress) - printf(_("Scanning inodes...\n")); + fprintf(stderr, "%s", _("Scanning inodes...\n")); retval = ext2fs_open_inode_scan(fs, 0, &scan); if (retval) { - com_err(program_name, retval,"%s", + com_err(program_name, retval, "%s", _("while opening inode scan")); exit(1); } @@ -1357,14 +1375,15 @@ static void install_image(char *device, char *image_fn, int type) { errcode_t retval; ext2_filsys fs; - int open_flag = EXT2_FLAG_IMAGE_FILE | EXT2_FLAG_64BITS; + int open_flag = EXT2_FLAG_IMAGE_FILE | EXT2_FLAG_64BITS | + EXT2_FLAG_IGNORE_CSUM_ERRORS; int fd = 0; io_manager io_ptr; io_channel io; if (type) { - com_err(program_name, 0, _("Raw and qcow2 images cannot" - "be installed")); + com_err(program_name, 0, "%s", + _("Raw and qcow2 images cannot be installed")); exit(1); } @@ -1379,14 +1398,14 @@ static void install_image(char *device, char *image_fn, int type) retval = ext2fs_open (image_fn, open_flag, 0, 0, io_ptr, &fs); if (retval) { - com_err (program_name, retval, _("while trying to open %s"), - image_fn); + com_err(program_name, retval, _("while trying to open %s"), + image_fn); exit(1); } retval = ext2fs_read_bitmaps (fs); if (retval) { - com_err(program_name, retval, _("error reading bitmaps")); + com_err(program_name, retval, "%s", _("error reading bitmaps")); exit(1); } @@ -1398,22 +1417,23 @@ static void install_image(char *device, char *image_fn, int type) retval = io_ptr->open(device, IO_FLAG_RW, &io); if (retval) { - com_err(device, 0, _("while opening device file")); + com_err(device, 0, "%s", _("while opening device file")); exit(1); } ext2fs_rewrite_to_io(fs, io); - seek_set(fd, fs->image_header->offset_inode); + seek_set(fd, ext2fs_le32_to_cpu(fs->image_header->offset_inode)); retval = ext2fs_image_inode_read(fs, fd, 0); if (retval) { - com_err(image_fn, 0, "while restoring the image table"); + com_err(image_fn, 0, "%s", + _("while restoring the image table")); exit(1); } close(fd); - ext2fs_close (fs); + ext2fs_close_free(&fs); } static struct ext2_qcow2_hdr *check_qcow2_image(int *fd, char *name) @@ -1433,7 +1453,7 @@ int main (int argc, char ** argv) ext2_filsys fs; char *image_fn, offset_opt[64]; struct ext2_qcow2_hdr *header = NULL; - int open_flag = EXT2_FLAG_64BITS; + int open_flag = EXT2_FLAG_64BITS | EXT2_FLAG_IGNORE_CSUM_ERRORS; int img_type = 0; int flags = 0; int mount_flags = 0; @@ -1505,22 +1525,22 @@ int main (int argc, char ** argv) usage(); if (all_data && !img_type) { - com_err(program_name, 0, _("-a option can only be used " - "with raw or QCOW2 images.")); + com_err(program_name, 0, "%s", _("-a option can only be used " + "with raw or QCOW2 images.")); exit(1); } if ((source_offset || dest_offset) && img_type != E2IMAGE_RAW) { - com_err(program_name, 0, + com_err(program_name, 0, "%s", _("Offsets are only allowed with raw images.")); exit(1); } if (move_mode && img_type != E2IMAGE_RAW) { - com_err(program_name, 0, + com_err(program_name, 0, "%s", _("Move mode is only allowed with raw images.")); exit(1); } if (move_mode && !all_data) { - com_err(program_name, 0, + com_err(program_name, 0, "%s", _("Move mode requires all data mode.")); exit(1); } @@ -1531,14 +1551,14 @@ int main (int argc, char ** argv) retval = ext2fs_check_if_mounted(device_name, &mount_flags); if (retval) { - com_err(program_name, retval, _("checking if mounted")); + com_err(program_name, retval, "%s", _("checking if mounted")); exit(1); } if (img_type && !ignore_rw_mount && (mount_flags & EXT2_MF_MOUNTED) && !(mount_flags & EXT2_MF_READONLY)) { - fprintf(stderr, _("\nRunning e2image on a R/W mounted " + fprintf(stderr, "%s", _("\nRunning e2image on a R/W mounted " "filesystem can result in an\n" "inconsistent image which will not be useful " "for debugging purposes.\n" @@ -1565,6 +1585,8 @@ int main (int argc, char ** argv) com_err (program_name, retval, _("while trying to open %s"), device_name); fputs(_("Couldn't find valid filesystem superblock.\n"), stdout); + if (retval == EXT2_ET_BAD_MAGIC) + check_plausibility(device_name, CHECK_FS_EXIST, NULL); exit(1); } @@ -1589,16 +1611,17 @@ skip_device: seek_set(fd, dest_offset); if ((img_type & E2IMAGE_QCOW2) && (fd == 1)) { - com_err(program_name, 0, _("QCOW2 image can not be written to " - "the stdout!\n")); + com_err(program_name, 0, "%s", + _("QCOW2 image can not be written to the stdout!\n")); exit(1); } if (fd != 1) { if (fstat(fd, &st)) { - com_err(program_name, 0, "Can not stat output\n"); + com_err(program_name, 0, "%s", + _("Can not stat output\n")); exit(1); } - if (S_ISBLK(st.st_mode)) + if (ext2fsP_is_disk_device(st.st_mode)) output_is_blk = 1; } if (flags & E2IMAGE_IS_QCOW2_FLAG) { @@ -1620,31 +1643,35 @@ skip_device: if (check) { if (img_type != E2IMAGE_RAW) { - fprintf(stderr, _("The -c option only supported " - "in raw mode\n")); + fprintf(stderr, "%s", _("The -c option only supported " + "in raw mode\n")); exit(1); } if (fd == 1) { - fprintf(stderr, _("The -c option is not supported " - "when writing to stdout\n")); + fprintf(stderr, "%s", _("The -c option not supported " + "when writing to stdout\n")); exit(1); } retval = ext2fs_get_mem(fs->blocksize, &check_buf); if (retval) { - com_err(program_name, retval, + com_err(program_name, retval, "%s", _("while allocating check_buf")); exit(1); } } - + if (show_progress && (img_type != E2IMAGE_RAW)) { + fprintf(stderr, "%s", + _("The -p option only supported in raw mode\n")); + exit(1); + } if (img_type) write_raw_image_file(fs, fd, img_type, flags); else write_image_file(fs, fd); - ext2fs_close (fs); + ext2fs_close_free(&fs); if (check) - printf(_("%d blocks already contained the data to be copied.\n"), + printf(_("%d blocks already contained the data to be copied\n"), skipped_blocks); out: