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