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