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