e2image.c revision 212c99488343cbc52fab3368f72853a5a3ff2e8a
1/* 2 * e2image.c --- Program which writes an image file backing up 3 * critical metadata for the filesystem. 4 * 5 * Copyright 2000, 2001 by Theodore Ts'o. 6 * 7 * %Begin-Header% 8 * This file may be redistributed under the terms of the GNU Public 9 * License. 10 * %End-Header% 11 */ 12 13#define _LARGEFILE_SOURCE 14#define _LARGEFILE64_SOURCE 15 16#include "config.h" 17#include <fcntl.h> 18#include <grp.h> 19#ifdef HAVE_GETOPT_H 20#include <getopt.h> 21#else 22extern char *optarg; 23extern int optind; 24#endif 25#include <pwd.h> 26#include <stdio.h> 27#ifdef HAVE_STDLIB_H 28#include <stdlib.h> 29#endif 30#include <string.h> 31#include <time.h> 32#include <unistd.h> 33#include <fcntl.h> 34#include <errno.h> 35#include <sys/stat.h> 36#include <sys/types.h> 37#include <assert.h> 38#include <signal.h> 39 40#include "ext2fs/ext2_fs.h" 41#include "ext2fs/ext2fs.h" 42#include "et/com_err.h" 43#include "uuid/uuid.h" 44#include "e2p/e2p.h" 45#include "ext2fs/e2image.h" 46#include "ext2fs/qcow2.h" 47 48#include "../version.h" 49#include "nls-enable.h" 50 51#define QCOW_OFLAG_COPIED (1LL << 63) 52#define NO_BLK ((blk64_t) -1) 53 54/* Image types */ 55#define E2IMAGE_RAW 1 56#define E2IMAGE_QCOW2 2 57 58/* Image flags */ 59#define E2IMAGE_INSTALL_FLAG 1 60#define E2IMAGE_SCRAMBLE_FLAG 2 61#define E2IMAGE_IS_QCOW2_FLAG 4 62#define E2IMAGE_CHECK_ZERO_FLAG 8 63 64static const char * program_name = "e2image"; 65static char * device_name = NULL; 66static char all_data; 67static char output_is_blk; 68static char nop_flag; 69/* writing to blk device: don't skip zeroed blocks */ 70static blk64_t source_offset, dest_offset; 71static char move_mode; 72static char show_progress; 73static char *check_buf; 74static int skipped_blocks; 75 76static blk64_t align_offset(blk64_t offset, unsigned int n) 77{ 78 return (offset + n - 1) & ~((blk64_t) n - 1); 79} 80 81static int get_bits_from_size(size_t size) 82{ 83 int res = 0; 84 85 if (size == 0) 86 return -1; 87 88 while (size != 1) { 89 /* Not a power of two */ 90 if (size & 1) 91 return -1; 92 93 size >>= 1; 94 res++; 95 } 96 return res; 97} 98 99static void usage(void) 100{ 101 fprintf(stderr, _("Usage: %s [-acfnprsIQ] [-o src_offset] " 102 "[-O dest_offset] \\\n\tdevice image_file\n"), 103 program_name); 104 exit (1); 105} 106 107static ext2_loff_t seek_relative(int fd, int offset) 108{ 109 ext2_loff_t ret = ext2fs_llseek(fd, offset, SEEK_CUR); 110 if (ret < 0) { 111 perror("seek_relative"); 112 exit(1); 113 } 114 return ret; 115} 116 117static ext2_loff_t seek_set(int fd, ext2_loff_t offset) 118{ 119 ext2_loff_t ret = ext2fs_llseek(fd, offset, SEEK_SET); 120 if (ret < 0) { 121 perror("seek_set"); 122 exit(1); 123 } 124 return ret; 125} 126 127/* 128 * Returns true if the block we are about to write is identical to 129 * what is already on the disk. 130 */ 131static int check_block(int fd, void *buf, void *cbuf, int blocksize) 132{ 133 char *cp = cbuf; 134 int count = blocksize, ret; 135 136 if (cbuf == NULL) 137 return 0; 138 139 while (count > 0) { 140 ret = read(fd, cp, count); 141 if (ret < 0) { 142 perror("check_block"); 143 exit(1); 144 } 145 count -= ret; 146 cp += ret; 147 } 148 ret = memcmp(buf, cbuf, blocksize); 149 seek_relative(fd, -blocksize); 150 return (ret == 0) ? 1 : 0; 151} 152 153static void generic_write(int fd, void *buf, int blocksize, blk64_t block) 154{ 155 int count, free_buf = 0; 156 errcode_t err; 157 158 if (!blocksize) 159 return; 160 161 if (!buf) { 162 free_buf = 1; 163 err = ext2fs_get_arrayzero(1, blocksize, &buf); 164 if (err) { 165 com_err(program_name, err, 166 _("while allocating buffer")); 167 exit(1); 168 } 169 } 170 if (nop_flag) { 171 printf(_("Writing block %llu\n"), (unsigned long long) block); 172 seek_relative(fd, blocksize); 173 return; 174 } 175 count = write(fd, buf, blocksize); 176 if (count != blocksize) { 177 if (count == -1) 178 err = errno; 179 else 180 err = 0; 181 182 if (block) 183 com_err(program_name, err, 184 _("error writing block %llu"), block); 185 else 186 com_err(program_name, err, _("error in write()")); 187 188 exit(1); 189 } 190 if (free_buf) 191 ext2fs_free_mem(&buf); 192} 193 194static void write_header(int fd, void *hdr, int hdr_size, int wrt_size) 195{ 196 char *header_buf; 197 int ret; 198 199 /* Sanity check */ 200 if (hdr_size > wrt_size) { 201 fprintf(stderr, "%s", 202 _("Error: header size is bigger than wrt_size\n")); 203 } 204 205 ret = ext2fs_get_mem(wrt_size, &header_buf); 206 if (ret) { 207 fputs(_("Couldn't allocate header buffer\n"), stderr); 208 exit(1); 209 } 210 211 seek_set(fd, 0); 212 memset(header_buf, 0, wrt_size); 213 214 if (hdr) 215 memcpy(header_buf, hdr, hdr_size); 216 217 generic_write(fd, header_buf, wrt_size, NO_BLK); 218 219 ext2fs_free_mem(&header_buf); 220} 221 222static void write_image_file(ext2_filsys fs, int fd) 223{ 224 struct ext2_image_hdr hdr; 225 struct stat st; 226 errcode_t retval; 227 228 write_header(fd, NULL, sizeof(struct ext2_image_hdr), fs->blocksize); 229 memset(&hdr, 0, sizeof(struct ext2_image_hdr)); 230 231 hdr.offset_super = seek_relative(fd, 0); 232 retval = ext2fs_image_super_write(fs, fd, 0); 233 if (retval) { 234 com_err(program_name, retval, "%s", 235 _("while writing superblock")); 236 exit(1); 237 } 238 239 hdr.offset_inode = seek_relative(fd, 0); 240 retval = ext2fs_image_inode_write(fs, fd, 241 (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0); 242 if (retval) { 243 com_err(program_name, retval, "%s", 244 _("while writing inode table")); 245 exit(1); 246 } 247 248 hdr.offset_blockmap = seek_relative(fd, 0); 249 retval = ext2fs_image_bitmap_write(fs, fd, 0); 250 if (retval) { 251 com_err(program_name, retval, "%s", 252 _("while writing block bitmap")); 253 exit(1); 254 } 255 256 hdr.offset_inodemap = seek_relative(fd, 0); 257 retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP); 258 if (retval) { 259 com_err(program_name, retval, "%s", 260 _("while writing inode bitmap")); 261 exit(1); 262 } 263 264 hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE; 265 strcpy(hdr.magic_descriptor, "Ext2 Image 1.0"); 266 gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname)); 267 strncpy(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name)-1); 268 hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0; 269 hdr.fs_blocksize = fs->blocksize; 270 271 if (stat(device_name, &st) == 0) 272 hdr.fs_device = st.st_rdev; 273 274 if (fstat(fd, &st) == 0) { 275 hdr.image_device = st.st_dev; 276 hdr.image_inode = st.st_ino; 277 } 278 memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid)); 279 280 hdr.image_time = time(0); 281 write_header(fd, &hdr, sizeof(struct ext2_image_hdr), fs->blocksize); 282} 283 284/* 285 * These set of functions are used to write a RAW image file. 286 */ 287static ext2fs_block_bitmap meta_block_map; 288static ext2fs_block_bitmap scramble_block_map; /* Directory blocks to be scrambled */ 289static blk64_t meta_blocks_count; 290 291struct process_block_struct { 292 ext2_ino_t ino; 293 int is_dir; 294}; 295 296/* 297 * These subroutines short circuits ext2fs_get_blocks and 298 * ext2fs_check_directory; we use them since we already have the inode 299 * structure, so there's no point in letting the ext2fs library read 300 * the inode again. 301 */ 302static ino_t stashed_ino = 0; 303static struct ext2_inode *stashed_inode; 304 305static errcode_t meta_get_blocks(ext2_filsys fs EXT2FS_ATTR((unused)), 306 ext2_ino_t ino, 307 blk_t *blocks) 308{ 309 int i; 310 311 if ((ino != stashed_ino) || !stashed_inode) 312 return EXT2_ET_CALLBACK_NOTHANDLED; 313 314 for (i=0; i < EXT2_N_BLOCKS; i++) 315 blocks[i] = stashed_inode->i_block[i]; 316 return 0; 317} 318 319static errcode_t meta_check_directory(ext2_filsys fs EXT2FS_ATTR((unused)), 320 ext2_ino_t ino) 321{ 322 if ((ino != stashed_ino) || !stashed_inode) 323 return EXT2_ET_CALLBACK_NOTHANDLED; 324 325 if (!LINUX_S_ISDIR(stashed_inode->i_mode)) 326 return EXT2_ET_NO_DIRECTORY; 327 return 0; 328} 329 330static errcode_t meta_read_inode(ext2_filsys fs EXT2FS_ATTR((unused)), 331 ext2_ino_t ino, 332 struct ext2_inode *inode) 333{ 334 if ((ino != stashed_ino) || !stashed_inode) 335 return EXT2_ET_CALLBACK_NOTHANDLED; 336 *inode = *stashed_inode; 337 return 0; 338} 339 340static void use_inode_shortcuts(ext2_filsys fs, int use_shortcuts) 341{ 342 if (use_shortcuts) { 343 fs->get_blocks = meta_get_blocks; 344 fs->check_directory = meta_check_directory; 345 fs->read_inode = meta_read_inode; 346 stashed_ino = 0; 347 } else { 348 fs->get_blocks = 0; 349 fs->check_directory = 0; 350 fs->read_inode = 0; 351 } 352} 353 354static int process_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)), 355 blk64_t *block_nr, 356 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 357 blk64_t ref_block EXT2FS_ATTR((unused)), 358 int ref_offset EXT2FS_ATTR((unused)), 359 void *priv_data EXT2FS_ATTR((unused))) 360{ 361 struct process_block_struct *p; 362 363 p = (struct process_block_struct *) priv_data; 364 365 ext2fs_mark_block_bitmap2(meta_block_map, *block_nr); 366 meta_blocks_count++; 367 if (scramble_block_map && p->is_dir && blockcnt >= 0) 368 ext2fs_mark_block_bitmap2(scramble_block_map, *block_nr); 369 return 0; 370} 371 372static int process_file_block(ext2_filsys fs EXT2FS_ATTR((unused)), 373 blk64_t *block_nr, 374 e2_blkcnt_t blockcnt, 375 blk64_t ref_block EXT2FS_ATTR((unused)), 376 int ref_offset EXT2FS_ATTR((unused)), 377 void *priv_data EXT2FS_ATTR((unused))) 378{ 379 if (blockcnt < 0 || all_data) { 380 ext2fs_mark_block_bitmap2(meta_block_map, *block_nr); 381 meta_blocks_count++; 382 } 383 return 0; 384} 385 386static void mark_table_blocks(ext2_filsys fs) 387{ 388 blk64_t first_block, b; 389 unsigned int i,j; 390 391 first_block = fs->super->s_first_data_block; 392 /* 393 * Mark primary superblock 394 */ 395 ext2fs_mark_block_bitmap2(meta_block_map, first_block); 396 meta_blocks_count++; 397 398 /* 399 * Mark the primary superblock descriptors 400 */ 401 for (j = 0; j < fs->desc_blocks; j++) { 402 ext2fs_mark_block_bitmap2(meta_block_map, 403 ext2fs_descriptor_block_loc2(fs, first_block, j)); 404 } 405 meta_blocks_count += fs->desc_blocks; 406 407 for (i = 0; i < fs->group_desc_count; i++) { 408 /* 409 * Mark the blocks used for the inode table 410 */ 411 if ((output_is_blk || 412 !ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)) && 413 ext2fs_inode_table_loc(fs, i)) { 414 unsigned int end = (unsigned) fs->inode_blocks_per_group; 415 /* skip unused blocks */ 416 if (!output_is_blk && 417 EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 418 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 419 end -= (ext2fs_bg_itable_unused(fs, i) / 420 EXT2_INODES_PER_BLOCK(fs->super)); 421 for (j = 0, b = ext2fs_inode_table_loc(fs, i); 422 j < end; 423 j++, b++) { 424 ext2fs_mark_block_bitmap2(meta_block_map, b); 425 meta_blocks_count++; 426 } 427 } 428 429 /* 430 * Mark block used for the block bitmap 431 */ 432 if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) && 433 ext2fs_block_bitmap_loc(fs, i)) { 434 ext2fs_mark_block_bitmap2(meta_block_map, 435 ext2fs_block_bitmap_loc(fs, i)); 436 meta_blocks_count++; 437 } 438 439 /* 440 * Mark block used for the inode bitmap 441 */ 442 if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) && 443 ext2fs_inode_bitmap_loc(fs, i)) { 444 ext2fs_mark_block_bitmap2(meta_block_map, 445 ext2fs_inode_bitmap_loc(fs, i)); 446 meta_blocks_count++; 447 } 448 } 449} 450 451/* 452 * This function returns 1 if the specified block is all zeros 453 */ 454static int check_zero_block(char *buf, int blocksize) 455{ 456 char *cp = buf; 457 int left = blocksize; 458 459 if (output_is_blk) 460 return 0; 461 while (left > 0) { 462 if (*cp++) 463 return 0; 464 left--; 465 } 466 return 1; 467} 468 469static int name_id[256]; 470 471#define EXT4_MAX_REC_LEN ((1<<16)-1) 472 473static void scramble_dir_block(ext2_filsys fs, blk64_t blk, char *buf) 474{ 475 char *p, *end, *cp; 476 struct ext2_dir_entry_2 *dirent; 477 unsigned int rec_len; 478 int id, len; 479 480 end = buf + fs->blocksize; 481 for (p = buf; p < end-8; p += rec_len) { 482 dirent = (struct ext2_dir_entry_2 *) p; 483 rec_len = dirent->rec_len; 484#ifdef WORDS_BIGENDIAN 485 rec_len = ext2fs_swab16(rec_len); 486#endif 487 if (rec_len == EXT4_MAX_REC_LEN || rec_len == 0) 488 rec_len = fs->blocksize; 489 else 490 rec_len = (rec_len & 65532) | ((rec_len & 3) << 16); 491#if 0 492 printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len); 493#endif 494 if (rec_len < 8 || (rec_len % 4) || 495 (p+rec_len > end)) { 496 printf(_("Corrupt directory block %llu: " 497 "bad rec_len (%d)\n"), 498 (unsigned long long) blk, rec_len); 499 rec_len = end - p; 500 (void) ext2fs_set_rec_len(fs, rec_len, 501 (struct ext2_dir_entry *) dirent); 502#ifdef WORDS_BIGENDIAN 503 dirent->rec_len = ext2fs_swab16(dirent->rec_len); 504#endif 505 continue; 506 } 507 if (dirent->name_len + 8U > rec_len) { 508 printf(_("Corrupt directory block %llu: " 509 "bad name_len (%d)\n"), 510 (unsigned long long) blk, dirent->name_len); 511 dirent->name_len = rec_len - 8; 512 continue; 513 } 514 cp = p+8; 515 len = rec_len - dirent->name_len - 8; 516 if (len > 0) 517 memset(cp+dirent->name_len, 0, len); 518 if (dirent->name_len==1 && cp[0] == '.') 519 continue; 520 if (dirent->name_len==2 && cp[0] == '.' && cp[1] == '.') 521 continue; 522 523 memset(cp, 'A', dirent->name_len); 524 len = dirent->name_len; 525 id = name_id[len]++; 526 while ((len > 0) && (id > 0)) { 527 *cp += id % 26; 528 id = id / 26; 529 cp++; 530 len--; 531 } 532 } 533} 534 535static char got_sigint; 536 537static void sigint_handler(int unused EXT2FS_ATTR((unused))) 538{ 539 got_sigint = 1; 540 signal (SIGINT, SIG_DFL); 541} 542 543#define calc_percent(a, b) ((int) ((100.0 * (((float) (a)) / \ 544 ((float) (b)))) + 0.5)) 545#define calc_rate(t, b, d) (((float)(t) / ((1024 * 1024) / (b))) / (d)) 546 547static int print_progress(blk64_t num, blk64_t total) 548{ 549 return printf(_("%llu / %llu blocks (%d%%)"), num, total, 550 calc_percent(num, total)); 551} 552 553static void output_meta_data_blocks(ext2_filsys fs, int fd, int flags) 554{ 555 errcode_t retval; 556 blk64_t blk; 557 char *buf, *zero_buf; 558 int sparse = 0; 559 blk64_t start = 0; 560 blk64_t distance = 0; 561 blk64_t end = ext2fs_blocks_count(fs->super); 562 time_t last_update = 0; 563 time_t start_time = 0; 564 blk64_t total_written = 0; 565 int bscount = 0; 566 567 retval = ext2fs_get_mem(fs->blocksize, &buf); 568 if (retval) { 569 com_err(program_name, retval, _("while allocating buffer")); 570 exit(1); 571 } 572 retval = ext2fs_get_memzero(fs->blocksize, &zero_buf); 573 if (retval) { 574 com_err(program_name, retval, _("while allocating buffer")); 575 exit(1); 576 } 577 if (show_progress) { 578 printf(_("Copying ")); 579 bscount = print_progress(total_written, meta_blocks_count); 580 fflush(stdout); 581 last_update = time(NULL); 582 start_time = time(NULL); 583 } 584 /* when doing an in place move to the right, you can't start 585 at the beginning or you will overwrite data, so instead 586 divide the fs up into distance size chunks and write them 587 in reverse. */ 588 if (move_mode && dest_offset > source_offset) { 589 distance = (dest_offset - source_offset) / fs->blocksize; 590 if (distance < ext2fs_blocks_count(fs->super)) 591 start = ext2fs_blocks_count(fs->super) - distance; 592 } 593 if (move_mode) 594 signal (SIGINT, sigint_handler); 595more_blocks: 596 if (distance) 597 seek_set(fd, (start * fs->blocksize) + dest_offset); 598 for (blk = start; blk < end; blk++) { 599 if (got_sigint) { 600 if (distance) { 601 /* moving to the right */ 602 if (distance >= ext2fs_blocks_count(fs->super) || 603 start == ext2fs_blocks_count(fs->super) - distance) 604 kill (getpid(), SIGINT); 605 } else { 606 /* moving to the left */ 607 if (blk < (source_offset - dest_offset) / fs->blocksize) 608 kill (getpid(), SIGINT); 609 } 610 if (show_progress) 611 printf ("\r"); 612 printf(_("Stopping now will destroy the filesystem, " 613 "interrupt again if you are sure\n")); 614 if (show_progress) { 615 printf(_("Copying ")); 616 bscount = print_progress(total_written, 617 meta_blocks_count); 618 fflush(stdout); 619 } 620 621 got_sigint = 0; 622 } 623 if (show_progress && last_update != time(NULL)) { 624 time_t duration; 625 last_update = time(NULL); 626 while (bscount--) 627 printf("\b"); 628 bscount = print_progress(total_written, 629 meta_blocks_count); 630 duration = time(NULL) - start_time; 631 if (duration > 5) { 632 time_t est = (duration * meta_blocks_count / 633 total_written) - duration; 634 char buff[30]; 635 strftime(buff, 30, "%T", gmtime(&est)); 636 bscount += printf(_(" %s remaining at %.2f MB/s"), 637 buff, calc_rate(total_written, 638 fs->blocksize, 639 duration)); 640 } 641 fflush (stdout); 642 } 643 if ((blk >= fs->super->s_first_data_block) && 644 ext2fs_test_block_bitmap2(meta_block_map, blk)) { 645 retval = io_channel_read_blk64(fs->io, blk, 1, buf); 646 if (retval) { 647 com_err(program_name, retval, 648 _("error reading block %llu"), blk); 649 } 650 total_written++; 651 if (scramble_block_map && 652 ext2fs_test_block_bitmap2(scramble_block_map, blk)) 653 scramble_dir_block(fs, blk, buf); 654 if ((flags & E2IMAGE_CHECK_ZERO_FLAG) && 655 check_zero_block(buf, fs->blocksize)) 656 goto sparse_write; 657 if (sparse) 658 seek_relative(fd, sparse); 659 sparse = 0; 660 if (check_block(fd, buf, check_buf, fs->blocksize)) { 661 seek_relative(fd, fs->blocksize); 662 skipped_blocks++; 663 } else 664 generic_write(fd, buf, fs->blocksize, blk); 665 } else { 666 sparse_write: 667 if (fd == 1) { 668 generic_write(fd, zero_buf, fs->blocksize, blk); 669 continue; 670 } 671 sparse += fs->blocksize; 672 if (sparse > 1024*1024) { 673 seek_relative(fd, 1024*1024); 674 sparse -= 1024*1024; 675 } 676 } 677 } 678 if (distance && start) { 679 if (start < distance) { 680 end = start; 681 start = 0; 682 } else { 683 end -= distance; 684 start -= distance; 685 if (end < distance) { 686 /* past overlap, do rest in one go */ 687 end = start; 688 start = 0; 689 } 690 } 691 sparse = 0; 692 goto more_blocks; 693 } 694 signal (SIGINT, SIG_DFL); 695 if (show_progress) { 696 time_t duration = time(NULL) - start_time; 697 char buff[30]; 698 while (bscount--) 699 printf("\b"); 700 strftime(buff, 30, "%T", gmtime(&duration)); 701 printf(_("\b\b\b\b\b\b\b\bCopied %llu / %llu blocks (%llu%%) " 702 "in %s at %.2f MB/s \n"), 703 total_written, meta_blocks_count, 704 calc_percent(total_written, meta_blocks_count), buff, 705 calc_rate(total_written, fs->blocksize, duration)); 706 } 707#ifdef HAVE_FTRUNCATE64 708 if (sparse) { 709 ext2_loff_t offset; 710 if (distance) 711 offset = seek_set(fd, 712 fs->blocksize * ext2fs_blocks_count(fs->super) + dest_offset); 713 else 714 offset = seek_relative(fd, sparse); 715 716 if (ftruncate64(fd, offset) < 0) { 717 seek_relative(fd, -1); 718 generic_write(fd, zero_buf, 1, NO_BLK); 719 } 720 } 721#else 722 if (sparse && !distance) { 723 seek_relative(fd, sparse-1); 724 generic_write(fd, zero_buf, 1, NO_BLK); 725 } 726#endif 727 ext2fs_free_mem(&zero_buf); 728 ext2fs_free_mem(&buf); 729} 730 731static void init_l1_table(struct ext2_qcow2_image *image) 732{ 733 __u64 *l1_table; 734 errcode_t ret; 735 736 ret = ext2fs_get_arrayzero(image->l1_size, sizeof(__u64), &l1_table); 737 if (ret) { 738 com_err(program_name, ret, _("while allocating l1 table")); 739 exit(1); 740 } 741 742 image->l1_table = l1_table; 743} 744 745static void init_l2_cache(struct ext2_qcow2_image *image) 746{ 747 unsigned int count, i; 748 struct ext2_qcow2_l2_cache *cache; 749 struct ext2_qcow2_l2_table *table; 750 errcode_t ret; 751 752 ret = ext2fs_get_arrayzero(1, sizeof(struct ext2_qcow2_l2_cache), 753 &cache); 754 if (ret) 755 goto alloc_err; 756 757 count = (image->l1_size > L2_CACHE_PREALLOC) ? L2_CACHE_PREALLOC : 758 image->l1_size; 759 760 cache->count = count; 761 cache->free = count; 762 cache->next_offset = image->l2_offset; 763 764 for (i = 0; i < count; i++) { 765 ret = ext2fs_get_arrayzero(1, 766 sizeof(struct ext2_qcow2_l2_table), &table); 767 if (ret) 768 goto alloc_err; 769 770 ret = ext2fs_get_arrayzero(image->l2_size, 771 sizeof(__u64), &table->data); 772 if (ret) 773 goto alloc_err; 774 775 table->next = cache->free_head; 776 cache->free_head = table; 777 } 778 779 image->l2_cache = cache; 780 return; 781 782alloc_err: 783 com_err(program_name, ret, _("while allocating l2 cache")); 784 exit(1); 785} 786 787static void put_l2_cache(struct ext2_qcow2_image *image) 788{ 789 struct ext2_qcow2_l2_cache *cache = image->l2_cache; 790 struct ext2_qcow2_l2_table *tmp, *table; 791 792 if (!cache) 793 return; 794 795 table = cache->free_head; 796 cache->free_head = NULL; 797again: 798 while (table) { 799 tmp = table; 800 table = table->next; 801 ext2fs_free_mem(&tmp->data); 802 ext2fs_free_mem(&tmp); 803 } 804 805 if (cache->free != cache->count) { 806 fprintf(stderr, _("Warning: There are still tables in the " 807 "cache while putting the cache, data will " 808 "be lost so the image may not be valid.\n")); 809 table = cache->used_head; 810 cache->used_head = NULL; 811 goto again; 812 } 813 814 ext2fs_free_mem(&cache); 815} 816 817static int init_refcount(struct ext2_qcow2_image *img, blk64_t table_offset) 818{ 819 struct ext2_qcow2_refcount *ref; 820 blk64_t table_clusters; 821 errcode_t ret; 822 823 ref = &(img->refcount); 824 825 /* 826 * One refcount block addresses 2048 clusters, one refcount table 827 * addresses cluster/sizeof(__u64) refcount blocks, and we need 828 * to address meta_blocks_count clusters + qcow2 metadata clusters 829 * in the worst case. 830 */ 831 table_clusters = meta_blocks_count + (table_offset >> 832 img->cluster_bits); 833 table_clusters >>= (img->cluster_bits + 6 - 1); 834 table_clusters = (table_clusters == 0) ? 1 : table_clusters; 835 836 ref->refcount_table_offset = table_offset; 837 ref->refcount_table_clusters = table_clusters; 838 ref->refcount_table_index = 0; 839 ref->refcount_block_index = 0; 840 841 /* Allocate refcount table */ 842 ret = ext2fs_get_arrayzero(ref->refcount_table_clusters, 843 img->cluster_size, &ref->refcount_table); 844 if (ret) 845 return ret; 846 847 /* Allocate refcount block */ 848 ret = ext2fs_get_arrayzero(1, img->cluster_size, &ref->refcount_block); 849 if (ret) 850 ext2fs_free_mem(&ref->refcount_table); 851 852 return ret; 853} 854 855static int initialize_qcow2_image(int fd, ext2_filsys fs, 856 struct ext2_qcow2_image *image) 857{ 858 struct ext2_qcow2_hdr *header; 859 blk64_t total_size, offset; 860 int shift, l2_bits, header_size, l1_size, ret; 861 int cluster_bits = get_bits_from_size(fs->blocksize); 862 struct ext2_super_block *sb = fs->super; 863 864 /* Allocate header */ 865 ret = ext2fs_get_memzero(sizeof(struct ext2_qcow2_hdr), &header); 866 if (ret) 867 return ret; 868 869 total_size = ext2fs_blocks_count(sb) << cluster_bits; 870 image->cluster_size = fs->blocksize; 871 image->l2_size = 1 << (cluster_bits - 3); 872 image->cluster_bits = cluster_bits; 873 image->fd = fd; 874 875 header->magic = ext2fs_cpu_to_be32(QCOW_MAGIC); 876 header->version = ext2fs_cpu_to_be32(QCOW_VERSION); 877 header->size = ext2fs_cpu_to_be64(total_size); 878 header->cluster_bits = ext2fs_cpu_to_be32(cluster_bits); 879 880 header_size = (sizeof(struct ext2_qcow2_hdr) + 7) & ~7; 881 offset = align_offset(header_size, image->cluster_size); 882 883 header->l1_table_offset = ext2fs_cpu_to_be64(offset); 884 image->l1_offset = offset; 885 886 l2_bits = cluster_bits - 3; 887 shift = cluster_bits + l2_bits; 888 l1_size = ((total_size + (1LL << shift) - 1) >> shift); 889 header->l1_size = ext2fs_cpu_to_be32(l1_size); 890 image->l1_size = l1_size; 891 892 /* Make space for L1 table */ 893 offset += align_offset(l1_size * sizeof(blk64_t), image->cluster_size); 894 895 /* Initialize refcounting */ 896 ret = init_refcount(image, offset); 897 if (ret) { 898 ext2fs_free_mem(&header); 899 return ret; 900 } 901 header->refcount_table_offset = ext2fs_cpu_to_be64(offset); 902 header->refcount_table_clusters = 903 ext2fs_cpu_to_be32(image->refcount.refcount_table_clusters); 904 offset += image->cluster_size; 905 offset += image->refcount.refcount_table_clusters << 906 image->cluster_bits; 907 908 /* Make space for L2 tables */ 909 image->l2_offset = offset; 910 offset += image->cluster_size; 911 912 /* Make space for first refcount block */ 913 image->refcount.refcount_block_offset = offset; 914 915 image->hdr = header; 916 /* Initialize l1 and l2 tables */ 917 init_l1_table(image); 918 init_l2_cache(image); 919 920 return 0; 921} 922 923static void free_qcow2_image(struct ext2_qcow2_image *img) 924{ 925 if (!img) 926 return; 927 928 if (img->hdr) 929 ext2fs_free_mem(&img->hdr); 930 931 if (img->l1_table) 932 ext2fs_free_mem(&img->l1_table); 933 934 if (img->refcount.refcount_table) 935 ext2fs_free_mem(&img->refcount.refcount_table); 936 if (img->refcount.refcount_block) 937 ext2fs_free_mem(&img->refcount.refcount_block); 938 939 put_l2_cache(img); 940 941 ext2fs_free_mem(&img); 942} 943 944/** 945 * Put table from used list (used_head) into free list (free_head). 946 * l2_table is used to return pointer to the next used table (used_head). 947 */ 948static void put_used_table(struct ext2_qcow2_image *img, 949 struct ext2_qcow2_l2_table **l2_table) 950{ 951 struct ext2_qcow2_l2_cache *cache = img->l2_cache; 952 struct ext2_qcow2_l2_table *table; 953 954 table = cache->used_head; 955 cache->used_head = table->next; 956 957 assert(table); 958 if (!table->next) 959 cache->used_tail = NULL; 960 961 /* Clean the table for case we will need to use it again */ 962 memset(table->data, 0, img->cluster_size); 963 table->next = cache->free_head; 964 cache->free_head = table; 965 966 cache->free++; 967 968 *l2_table = cache->used_head; 969} 970 971static void flush_l2_cache(struct ext2_qcow2_image *image) 972{ 973 blk64_t seek = 0; 974 ext2_loff_t offset; 975 struct ext2_qcow2_l2_cache *cache = image->l2_cache; 976 struct ext2_qcow2_l2_table *table = cache->used_head; 977 int fd = image->fd; 978 979 /* Store current position */ 980 offset = seek_relative(fd, 0); 981 982 assert(table); 983 while (cache->free < cache->count) { 984 if (seek != table->offset) { 985 seek_set(fd, table->offset); 986 seek = table->offset; 987 } 988 989 generic_write(fd, (char *)table->data, image->cluster_size, 990 NO_BLK); 991 put_used_table(image, &table); 992 seek += image->cluster_size; 993 } 994 995 /* Restore previous position */ 996 seek_set(fd, offset); 997} 998 999/** 1000 * Get first free table (from free_head) and put it into tail of used list 1001 * (to used_tail). 1002 * l2_table is used to return pointer to moved table. 1003 * Returns 1 if the cache is full, 0 otherwise. 1004 */ 1005static void get_free_table(struct ext2_qcow2_image *image, 1006 struct ext2_qcow2_l2_table **l2_table) 1007{ 1008 struct ext2_qcow2_l2_table *table; 1009 struct ext2_qcow2_l2_cache *cache = image->l2_cache; 1010 1011 if (0 == cache->free) 1012 flush_l2_cache(image); 1013 1014 table = cache->free_head; 1015 assert(table); 1016 cache->free_head = table->next; 1017 1018 if (cache->used_tail) 1019 cache->used_tail->next = table; 1020 else 1021 /* First item in the used list */ 1022 cache->used_head = table; 1023 1024 cache->used_tail = table; 1025 cache->free--; 1026 1027 *l2_table = table; 1028} 1029 1030static int add_l2_item(struct ext2_qcow2_image *img, blk64_t blk, 1031 blk64_t data, blk64_t next) 1032{ 1033 struct ext2_qcow2_l2_cache *cache = img->l2_cache; 1034 struct ext2_qcow2_l2_table *table = cache->used_tail; 1035 blk64_t l1_index = blk / img->l2_size; 1036 blk64_t l2_index = blk & (img->l2_size - 1); 1037 int ret = 0; 1038 1039 /* 1040 * Need to create new table if it does not exist, 1041 * or if it is full 1042 */ 1043 if (!table || (table->l1_index != l1_index)) { 1044 get_free_table(img, &table); 1045 table->l1_index = l1_index; 1046 table->offset = cache->next_offset; 1047 cache->next_offset = next; 1048 img->l1_table[l1_index] = 1049 ext2fs_cpu_to_be64(table->offset | QCOW_OFLAG_COPIED); 1050 ret++; 1051 } 1052 1053 table->data[l2_index] = ext2fs_cpu_to_be64(data | QCOW_OFLAG_COPIED); 1054 return ret; 1055} 1056 1057static int update_refcount(int fd, struct ext2_qcow2_image *img, 1058 blk64_t offset, blk64_t rfblk_pos) 1059{ 1060 struct ext2_qcow2_refcount *ref; 1061 __u32 table_index; 1062 int ret = 0; 1063 1064 ref = &(img->refcount); 1065 table_index = offset >> (2 * img->cluster_bits - 1); 1066 1067 /* 1068 * Need to create new refcount block when the offset addresses 1069 * another item in the refcount table 1070 */ 1071 if (table_index != ref->refcount_table_index) { 1072 1073 seek_set(fd, ref->refcount_block_offset); 1074 1075 generic_write(fd, (char *)ref->refcount_block, 1076 img->cluster_size, NO_BLK); 1077 memset(ref->refcount_block, 0, img->cluster_size); 1078 1079 ref->refcount_table[ref->refcount_table_index] = 1080 ext2fs_cpu_to_be64(ref->refcount_block_offset); 1081 ref->refcount_block_offset = rfblk_pos; 1082 ref->refcount_block_index = 0; 1083 ref->refcount_table_index = table_index; 1084 ret++; 1085 } 1086 1087 /* 1088 * We are relying on the fact that we are creating the qcow2 1089 * image sequentially, hence we will always allocate refcount 1090 * block items sequentialy. 1091 */ 1092 ref->refcount_block[ref->refcount_block_index] = ext2fs_cpu_to_be16(1); 1093 ref->refcount_block_index++; 1094 return ret; 1095} 1096 1097static int sync_refcount(int fd, struct ext2_qcow2_image *img) 1098{ 1099 struct ext2_qcow2_refcount *ref; 1100 1101 ref = &(img->refcount); 1102 1103 ref->refcount_table[ref->refcount_table_index] = 1104 ext2fs_cpu_to_be64(ref->refcount_block_offset); 1105 seek_set(fd, ref->refcount_table_offset); 1106 generic_write(fd, (char *)ref->refcount_table, 1107 ref->refcount_table_clusters << img->cluster_bits, NO_BLK); 1108 1109 seek_set(fd, ref->refcount_block_offset); 1110 generic_write(fd, (char *)ref->refcount_block, img->cluster_size, 1111 NO_BLK); 1112 return 0; 1113} 1114 1115static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd) 1116{ 1117 errcode_t retval; 1118 blk64_t blk, offset, size, end; 1119 char *buf; 1120 struct ext2_qcow2_image *img; 1121 unsigned int header_size; 1122 1123 /* allocate struct ext2_qcow2_image */ 1124 retval = ext2fs_get_mem(sizeof(struct ext2_qcow2_image), &img); 1125 if (retval) { 1126 com_err(program_name, retval, 1127 _("while allocating ext2_qcow2_image")); 1128 exit(1); 1129 } 1130 1131 retval = initialize_qcow2_image(fd, fs, img); 1132 if (retval) { 1133 com_err(program_name, retval, 1134 _("while initializing ext2_qcow2_image")); 1135 exit(1); 1136 } 1137 header_size = align_offset(sizeof(struct ext2_qcow2_hdr), 1138 img->cluster_size); 1139 write_header(fd, img->hdr, sizeof(struct ext2_qcow2_hdr), header_size); 1140 1141 /* Refcount all qcow2 related metadata up to refcount_block_offset */ 1142 end = img->refcount.refcount_block_offset; 1143 seek_set(fd, end); 1144 blk = end + img->cluster_size; 1145 for (offset = 0; offset <= end; offset += img->cluster_size) { 1146 if (update_refcount(fd, img, offset, blk)) { 1147 blk += img->cluster_size; 1148 /* 1149 * If we create new refcount block, we need to refcount 1150 * it as well. 1151 */ 1152 end += img->cluster_size; 1153 } 1154 } 1155 seek_set(fd, offset); 1156 1157 retval = ext2fs_get_mem(fs->blocksize, &buf); 1158 if (retval) { 1159 com_err(program_name, retval, _("while allocating buffer")); 1160 exit(1); 1161 } 1162 /* Write qcow2 data blocks */ 1163 for (blk = 0; blk < ext2fs_blocks_count(fs->super); blk++) { 1164 if ((blk >= fs->super->s_first_data_block) && 1165 ext2fs_test_block_bitmap2(meta_block_map, blk)) { 1166 retval = io_channel_read_blk64(fs->io, blk, 1, buf); 1167 if (retval) { 1168 com_err(program_name, retval, 1169 _("error reading block %llu"), blk); 1170 continue; 1171 } 1172 if (scramble_block_map && 1173 ext2fs_test_block_bitmap2(scramble_block_map, blk)) 1174 scramble_dir_block(fs, blk, buf); 1175 if (check_zero_block(buf, fs->blocksize)) 1176 continue; 1177 1178 if (update_refcount(fd, img, offset, offset)) { 1179 /* Make space for another refcount block */ 1180 offset += img->cluster_size; 1181 seek_set(fd, offset); 1182 /* 1183 * We have created the new refcount block, this 1184 * means that we need to refcount it as well. 1185 * So the previous update_refcount refcounted 1186 * the block itself and now we are going to 1187 * create refcount for data. New refcount 1188 * block should not be created! 1189 */ 1190 if (update_refcount(fd, img, offset, offset)) { 1191 fprintf(stderr, _("Programming error: " 1192 "multiple sequential refcount " 1193 "blocks created!\n")); 1194 exit(1); 1195 } 1196 } 1197 1198 generic_write(fd, buf, fs->blocksize, blk); 1199 1200 if (add_l2_item(img, blk, offset, 1201 offset + img->cluster_size)) { 1202 offset += img->cluster_size; 1203 if (update_refcount(fd, img, offset, 1204 offset + img->cluster_size)) { 1205 offset += img->cluster_size; 1206 if (update_refcount(fd, img, offset, 1207 offset)) { 1208 fprintf(stderr, 1209 _("Programming error: multiple sequential refcount " 1210 "blocks created!\n")); 1211 exit(1); 1212 } 1213 } 1214 offset += img->cluster_size; 1215 seek_set(fd, offset); 1216 continue; 1217 } 1218 1219 offset += img->cluster_size; 1220 } 1221 } 1222 update_refcount(fd, img, offset, offset); 1223 flush_l2_cache(img); 1224 sync_refcount(fd, img); 1225 1226 /* Write l1_table*/ 1227 seek_set(fd, img->l1_offset); 1228 size = img->l1_size * sizeof(__u64); 1229 generic_write(fd, (char *)img->l1_table, size, NO_BLK); 1230 1231 ext2fs_free_mem(&buf); 1232 free_qcow2_image(img); 1233} 1234 1235static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags) 1236{ 1237 struct process_block_struct pb; 1238 struct ext2_inode inode; 1239 ext2_inode_scan scan; 1240 ext2_ino_t ino; 1241 errcode_t retval; 1242 char * block_buf; 1243 1244 meta_blocks_count = 0; 1245 retval = ext2fs_allocate_block_bitmap(fs, _("in-use block map"), 1246 &meta_block_map); 1247 if (retval) { 1248 com_err(program_name, retval, 1249 _("while allocating block bitmap")); 1250 exit(1); 1251 } 1252 1253 if (flags & E2IMAGE_SCRAMBLE_FLAG) { 1254 retval = ext2fs_allocate_block_bitmap(fs, "scramble block map", 1255 &scramble_block_map); 1256 if (retval) { 1257 com_err(program_name, retval, 1258 _("while allocating scramble block bitmap")); 1259 exit(1); 1260 } 1261 } 1262 1263 mark_table_blocks(fs); 1264 if (show_progress) 1265 printf(_("Scanning inodes...\n")); 1266 1267 retval = ext2fs_open_inode_scan(fs, 0, &scan); 1268 if (retval) { 1269 com_err(program_name, retval,"%s", 1270 _("while opening inode scan")); 1271 exit(1); 1272 } 1273 1274 retval = ext2fs_get_mem(fs->blocksize * 3, &block_buf); 1275 if (retval) { 1276 com_err(program_name, 0, "%s", 1277 _("Can't allocate block buffer")); 1278 exit(1); 1279 } 1280 1281 use_inode_shortcuts(fs, 1); 1282 stashed_inode = &inode; 1283 while (1) { 1284 retval = ext2fs_get_next_inode(scan, &ino, &inode); 1285 if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) 1286 continue; 1287 if (retval) { 1288 com_err(program_name, retval, "%s", 1289 _("while getting next inode")); 1290 exit(1); 1291 } 1292 if (ino == 0) 1293 break; 1294 if (!inode.i_links_count) 1295 continue; 1296 if (ext2fs_file_acl_block(fs, &inode)) { 1297 ext2fs_mark_block_bitmap2(meta_block_map, 1298 ext2fs_file_acl_block(fs, &inode)); 1299 meta_blocks_count++; 1300 } 1301 if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) 1302 continue; 1303 1304 stashed_ino = ino; 1305 pb.ino = ino; 1306 pb.is_dir = LINUX_S_ISDIR(inode.i_mode); 1307 if (LINUX_S_ISDIR(inode.i_mode) || 1308 (LINUX_S_ISLNK(inode.i_mode) && 1309 ext2fs_inode_has_valid_blocks2(fs, &inode)) || 1310 ino == fs->super->s_journal_inum) { 1311 retval = ext2fs_block_iterate3(fs, ino, 1312 BLOCK_FLAG_READ_ONLY, block_buf, 1313 process_dir_block, &pb); 1314 if (retval) { 1315 com_err(program_name, retval, 1316 _("while iterating over inode %u"), 1317 ino); 1318 exit(1); 1319 } 1320 } else { 1321 if ((inode.i_flags & EXT4_EXTENTS_FL) || 1322 inode.i_block[EXT2_IND_BLOCK] || 1323 inode.i_block[EXT2_DIND_BLOCK] || 1324 inode.i_block[EXT2_TIND_BLOCK] || all_data) { 1325 retval = ext2fs_block_iterate3(fs, 1326 ino, BLOCK_FLAG_READ_ONLY, block_buf, 1327 process_file_block, &pb); 1328 if (retval) { 1329 com_err(program_name, retval, 1330 _("while iterating over inode %u"), ino); 1331 exit(1); 1332 } 1333 } 1334 } 1335 } 1336 use_inode_shortcuts(fs, 0); 1337 1338 if (type & E2IMAGE_QCOW2) 1339 output_qcow2_meta_data_blocks(fs, fd); 1340 else 1341 output_meta_data_blocks(fs, fd, flags); 1342 1343 ext2fs_free_mem(&block_buf); 1344 ext2fs_close_inode_scan(scan); 1345 ext2fs_free_block_bitmap(meta_block_map); 1346 if (type & E2IMAGE_SCRAMBLE_FLAG) 1347 ext2fs_free_block_bitmap(scramble_block_map); 1348} 1349 1350static void install_image(char *device, char *image_fn, int type) 1351{ 1352 errcode_t retval; 1353 ext2_filsys fs; 1354 int open_flag = EXT2_FLAG_IMAGE_FILE | EXT2_FLAG_64BITS; 1355 int fd = 0; 1356 io_manager io_ptr; 1357 io_channel io; 1358 1359 if (type) { 1360 com_err(program_name, 0, _("Raw and qcow2 images cannot" 1361 "be installed")); 1362 exit(1); 1363 } 1364 1365#ifdef CONFIG_TESTIO_DEBUG 1366 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { 1367 io_ptr = test_io_manager; 1368 test_io_backing_manager = unix_io_manager; 1369 } else 1370#endif 1371 io_ptr = unix_io_manager; 1372 1373 retval = ext2fs_open (image_fn, open_flag, 0, 0, 1374 io_ptr, &fs); 1375 if (retval) { 1376 com_err (program_name, retval, _("while trying to open %s"), 1377 image_fn); 1378 exit(1); 1379 } 1380 1381 retval = ext2fs_read_bitmaps (fs); 1382 if (retval) { 1383 com_err(program_name, retval, _("error reading bitmaps")); 1384 exit(1); 1385 } 1386 1387 fd = ext2fs_open_file(image_fn, O_RDONLY, 0); 1388 if (fd < 0) { 1389 perror(image_fn); 1390 exit(1); 1391 } 1392 1393 retval = io_ptr->open(device, IO_FLAG_RW, &io); 1394 if (retval) { 1395 com_err(device, 0, _("while opening device file")); 1396 exit(1); 1397 } 1398 1399 ext2fs_rewrite_to_io(fs, io); 1400 1401 seek_set(fd, fs->image_header->offset_inode); 1402 1403 retval = ext2fs_image_inode_read(fs, fd, 0); 1404 if (retval) { 1405 com_err(image_fn, 0, "while restoring the image table"); 1406 exit(1); 1407 } 1408 1409 close(fd); 1410 ext2fs_close (fs); 1411} 1412 1413static struct ext2_qcow2_hdr *check_qcow2_image(int *fd, char *name) 1414{ 1415 1416 *fd = ext2fs_open_file(name, O_RDONLY, 0600); 1417 if (*fd < 0) 1418 return NULL; 1419 1420 return qcow2_read_header(*fd); 1421} 1422 1423int main (int argc, char ** argv) 1424{ 1425 int c; 1426 errcode_t retval; 1427 ext2_filsys fs; 1428 char *image_fn, offset_opt[64]; 1429 struct ext2_qcow2_hdr *header = NULL; 1430 int open_flag = EXT2_FLAG_64BITS; 1431 int img_type = 0; 1432 int flags = 0; 1433 int mount_flags = 0; 1434 int qcow2_fd = 0; 1435 int fd = 0; 1436 int ret = 0; 1437 int ignore_rw_mount = 0; 1438 int check = 0; 1439 struct stat st; 1440 1441#ifdef ENABLE_NLS 1442 setlocale(LC_MESSAGES, ""); 1443 setlocale(LC_CTYPE, ""); 1444 bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 1445 textdomain(NLS_CAT_NAME); 1446 set_com_err_gettext(gettext); 1447#endif 1448 fprintf (stderr, "e2image %s (%s)\n", E2FSPROGS_VERSION, 1449 E2FSPROGS_DATE); 1450 if (argc && *argv) 1451 program_name = *argv; 1452 add_error_table(&et_ext2_error_table); 1453 while ((c = getopt(argc, argv, "nrsIQafo:O:pc")) != EOF) 1454 switch (c) { 1455 case 'I': 1456 flags |= E2IMAGE_INSTALL_FLAG; 1457 break; 1458 case 'Q': 1459 if (img_type) 1460 usage(); 1461 img_type |= E2IMAGE_QCOW2; 1462 break; 1463 case 'r': 1464 if (img_type) 1465 usage(); 1466 img_type |= E2IMAGE_RAW; 1467 break; 1468 case 's': 1469 flags |= E2IMAGE_SCRAMBLE_FLAG; 1470 break; 1471 case 'a': 1472 all_data = 1; 1473 break; 1474 case 'f': 1475 ignore_rw_mount = 1; 1476 break; 1477 case 'n': 1478 nop_flag = 1; 1479 break; 1480 case 'o': 1481 source_offset = strtoull(optarg, NULL, 0); 1482 break; 1483 case 'O': 1484 dest_offset = strtoull(optarg, NULL, 0); 1485 break; 1486 case 'p': 1487 show_progress = 1; 1488 break; 1489 case 'c': 1490 check = 1; 1491 break; 1492 default: 1493 usage(); 1494 } 1495 if (optind == argc - 1 && 1496 (source_offset || dest_offset)) 1497 move_mode = 1; 1498 else if (optind != argc - 2 ) 1499 usage(); 1500 1501 if (all_data && !img_type) { 1502 com_err(program_name, 0, _("-a option can only be used " 1503 "with raw or QCOW2 images.")); 1504 exit(1); 1505 } 1506 if ((source_offset || dest_offset) && img_type != E2IMAGE_RAW) { 1507 com_err(program_name, 0, 1508 _("Offsets are only allowed with raw images.")); 1509 exit(1); 1510 } 1511 if (move_mode && img_type != E2IMAGE_RAW) { 1512 com_err(program_name, 0, 1513 _("Move mode is only allowed with raw images.")); 1514 exit(1); 1515 } 1516 if (move_mode && !all_data) { 1517 com_err(program_name, 0, 1518 _("Move mode requires all data mode.")); 1519 exit(1); 1520 } 1521 device_name = argv[optind]; 1522 if (move_mode) 1523 image_fn = device_name; 1524 else image_fn = argv[optind+1]; 1525 1526 retval = ext2fs_check_if_mounted(device_name, &mount_flags); 1527 if (retval) { 1528 com_err(program_name, retval, _("checking if mounted")); 1529 exit(1); 1530 } 1531 1532 if (img_type && !ignore_rw_mount && 1533 (mount_flags & EXT2_MF_MOUNTED) && 1534 !(mount_flags & EXT2_MF_READONLY)) { 1535 fprintf(stderr, _("\nRunning e2image on a R/W mounted " 1536 "filesystem can result in an\n" 1537 "inconsistent image which will not be useful " 1538 "for debugging purposes.\n" 1539 "Use -f option if you really want to do that.\n")); 1540 exit(1); 1541 } 1542 1543 if (flags & E2IMAGE_INSTALL_FLAG) { 1544 install_image(device_name, image_fn, img_type); 1545 exit (0); 1546 } 1547 1548 if (img_type & E2IMAGE_RAW) { 1549 header = check_qcow2_image(&qcow2_fd, device_name); 1550 if (header) { 1551 flags |= E2IMAGE_IS_QCOW2_FLAG; 1552 goto skip_device; 1553 } 1554 } 1555 sprintf(offset_opt, "offset=%llu", source_offset); 1556 retval = ext2fs_open2(device_name, offset_opt, open_flag, 0, 0, 1557 unix_io_manager, &fs); 1558 if (retval) { 1559 com_err (program_name, retval, _("while trying to open %s"), 1560 device_name); 1561 fputs(_("Couldn't find valid filesystem superblock.\n"), stdout); 1562 exit(1); 1563 } 1564 1565skip_device: 1566 if (strcmp(image_fn, "-") == 0) 1567 fd = 1; 1568 else { 1569 int o_flags = O_CREAT|O_RDWR; 1570 1571 if (img_type != E2IMAGE_RAW) 1572 o_flags |= O_TRUNC; 1573 if (access(image_fn, F_OK) != 0) 1574 flags |= E2IMAGE_CHECK_ZERO_FLAG; 1575 fd = ext2fs_open_file(image_fn, o_flags, 0600); 1576 if (fd < 0) { 1577 com_err(program_name, errno, 1578 _("while trying to open %s"), image_fn); 1579 exit(1); 1580 } 1581 } 1582 if (dest_offset) 1583 seek_set(fd, dest_offset); 1584 1585 if ((img_type & E2IMAGE_QCOW2) && (fd == 1)) { 1586 com_err(program_name, 0, _("QCOW2 image can not be written to " 1587 "the stdout!\n")); 1588 exit(1); 1589 } 1590 if (fd != 1) { 1591 if (fstat(fd, &st)) { 1592 com_err(program_name, 0, "Can not stat output\n"); 1593 exit(1); 1594 } 1595 if (S_ISBLK(st.st_mode)) 1596 output_is_blk = 1; 1597 } 1598 if (flags & E2IMAGE_IS_QCOW2_FLAG) { 1599 ret = qcow2_write_raw_image(qcow2_fd, fd, header); 1600 if (ret) { 1601 if (ret == -QCOW_COMPRESSED) 1602 fprintf(stderr, _("Image (%s) is compressed\n"), 1603 image_fn); 1604 if (ret == -QCOW_ENCRYPTED) 1605 fprintf(stderr, _("Image (%s) is encrypted\n"), 1606 image_fn); 1607 com_err(program_name, ret, 1608 _("while trying to convert qcow2 image" 1609 " (%s) into raw image (%s)"), 1610 device_name, image_fn); 1611 } 1612 goto out; 1613 } 1614 1615 if (check) { 1616 if (img_type != E2IMAGE_RAW) { 1617 fprintf(stderr, _("The -c option only supported " 1618 "in raw mode\n")); 1619 exit(1); 1620 } 1621 if (fd == 1) { 1622 fprintf(stderr, _("The -c option is not supported " 1623 "when writing to stdout\n")); 1624 exit(1); 1625 } 1626 retval = ext2fs_get_mem(fs->blocksize, &check_buf); 1627 if (retval) { 1628 com_err(program_name, retval, 1629 _("while allocating check_buf")); 1630 exit(1); 1631 } 1632 } 1633 1634 if (img_type) 1635 write_raw_image_file(fs, fd, img_type, flags); 1636 else 1637 write_image_file(fs, fd); 1638 1639 ext2fs_close (fs); 1640 if (check) 1641 printf(_("%d blocks already contained the data to be copied.\n"), 1642 skipped_blocks); 1643 1644out: 1645 if (header) 1646 free(header); 1647 if (qcow2_fd) 1648 close(qcow2_fd); 1649 remove_error_table(&et_ext2_error_table); 1650 return ret; 1651} 1652