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