e2image.c revision 80fe25a2d7d8461ac17b21659885f1b4ec6fecd7
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 */ 59blk64_t source_offset, dest_offset; 60char move_mode; 61char show_progress; 62 63static blk64_t align_offset(blk64_t offset, int n) 64{ 65 return (offset + n - 1) & ~(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 %lu: " 452 "bad rec_len (%d)\n", (unsigned 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 %lu: " 464 "bad name_len (%d)\n", (unsigned 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 unsused) 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; 508 time_t start_time; 509 blk64_t total_written = 0; 510 int bscount; 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 last_update = time(NULL); 576 while (bscount--) 577 printf("\b"); 578 bscount = printf("%llu / %llu blocks (%llu%%)", 579 total_written, 580 meta_blocks_count, 581 (total_written + 50) / 582 ((meta_blocks_count + 50) / 100)); 583 time_t duration = time(NULL) - start_time; 584 if (duration > 5) { 585 time_t est = (duration * 586 meta_blocks_count / total_written) - 587 (duration); 588 char buff[30]; 589 strftime(buff, 30, "%T", gmtime(&est)); 590 bscount += printf(" %s remaining at %.2f MB/s", 591 buff, 592 ((float)total_written / 593 ((1024 * 1024) / fs->blocksize)) / 594 duration); 595 } 596 fflush (stdout); 597 } 598 if ((blk >= fs->super->s_first_data_block) && 599 ext2fs_test_block_bitmap2(meta_block_map, blk)) { 600 retval = io_channel_read_blk64(fs->io, blk, 1, buf); 601 if (retval) { 602 com_err(program_name, retval, 603 "error reading block %llu", blk); 604 } 605 total_written++; 606 if (scramble_block_map && 607 ext2fs_test_block_bitmap2(scramble_block_map, blk)) 608 scramble_dir_block(fs, blk, buf); 609 if ((fd != 1) && check_zero_block(buf, fs->blocksize)) 610 goto sparse_write; 611 if (sparse) 612 seek_relative(fd, sparse); 613 generic_write(fd, buf, fs->blocksize, blk); 614 sparse = 0; 615 } else { 616 sparse_write: 617 if (fd == 1) { 618 generic_write(fd, zero_buf, fs->blocksize, blk); 619 continue; 620 } 621 sparse += fs->blocksize; 622 if (sparse > 1024*1024) { 623 seek_relative(fd, 1024*1024); 624 sparse -= 1024*1024; 625 } 626 } 627 } 628 if (distance && start) { 629 if (start < distance) { 630 end = start; 631 start = 0; 632 } else { 633 end -= distance; 634 start -= distance; 635 if (end < distance) { 636 /* past overlap, do rest in one go */ 637 end = start; 638 start = 0; 639 } 640 } 641 sparse = 0; 642 goto more_blocks; 643 } 644 signal (SIGINT, SIG_DFL); 645 if (show_progress) { 646 while (bscount--) 647 printf("\b"); 648 time_t duration = time(NULL) - start_time; 649 char buff[30]; 650 strftime(buff, 30, "%T", gmtime(&duration)); 651 printf("\b\b\b\b\b\b\b\bCopied %llu / %llu blocks (%llu%%) in " 652 "%s at %.2f MB/s \n", 653 total_written, 654 meta_blocks_count, 655 (total_written + 50) / ((meta_blocks_count + 50) / 100), 656 buff, 657 ((float)total_written / 658 ((1024 * 1024) / fs->blocksize)) / 659 duration); 660 661 } 662#ifdef HAVE_FTRUNCATE64 663 if (sparse) { 664 ext2_loff_t offset; 665 if (distance) 666 offset = seek_set(fd, 667 fs->blocksize * ext2fs_blocks_count(fs->super) + dest_offset); 668 else 669 offset = seek_relative(fd, sparse); 670 671 if (ftruncate64(fd, offset) < 0) { 672 seek_relative(fd, -1); 673 generic_write(fd, zero_buf, 1, -1); 674 } 675 } 676#else 677 if (sparse && !distance) { 678 seek_relative(fd, sparse-1); 679 generic_write(fd, zero_buf, 1, -1); 680 } 681#endif 682 ext2fs_free_mem(&zero_buf); 683 ext2fs_free_mem(&buf); 684} 685 686static void init_l1_table(struct ext2_qcow2_image *image) 687{ 688 __u64 *l1_table; 689 errcode_t ret; 690 691 ret = ext2fs_get_arrayzero(image->l1_size, sizeof(__u64), &l1_table); 692 if (ret) { 693 com_err(program_name, ret, "while allocating l1 table"); 694 exit(1); 695 } 696 697 image->l1_table = l1_table; 698} 699 700static void init_l2_cache(struct ext2_qcow2_image *image) 701{ 702 unsigned int count, i; 703 struct ext2_qcow2_l2_cache *cache; 704 struct ext2_qcow2_l2_table *table; 705 errcode_t ret; 706 707 ret = ext2fs_get_arrayzero(1, sizeof(struct ext2_qcow2_l2_cache), 708 &cache); 709 if (ret) 710 goto alloc_err; 711 712 count = (image->l1_size > L2_CACHE_PREALLOC) ? L2_CACHE_PREALLOC : 713 image->l1_size; 714 715 cache->count = count; 716 cache->free = count; 717 cache->next_offset = image->l2_offset; 718 719 for (i = 0; i < count; i++) { 720 ret = ext2fs_get_arrayzero(1, 721 sizeof(struct ext2_qcow2_l2_table), &table); 722 if (ret) 723 goto alloc_err; 724 725 ret = ext2fs_get_arrayzero(image->l2_size, 726 sizeof(__u64), &table->data); 727 if (ret) 728 goto alloc_err; 729 730 table->next = cache->free_head; 731 cache->free_head = table; 732 } 733 734 image->l2_cache = cache; 735 return; 736 737alloc_err: 738 com_err(program_name, ret, "while allocating l2 cache"); 739 exit(1); 740} 741 742static void put_l2_cache(struct ext2_qcow2_image *image) 743{ 744 struct ext2_qcow2_l2_cache *cache = image->l2_cache; 745 struct ext2_qcow2_l2_table *tmp, *table; 746 747 if (!cache) 748 return; 749 750 table = cache->free_head; 751 cache->free_head = NULL; 752again: 753 while (table) { 754 tmp = table; 755 table = table->next; 756 ext2fs_free_mem(&tmp->data); 757 ext2fs_free_mem(&tmp); 758 } 759 760 if (cache->free != cache->count) { 761 fprintf(stderr, "Warning: There are still tables in the " 762 "cache while putting the cache, data will " 763 "be lost so the image may not be valid.\n"); 764 table = cache->used_head; 765 cache->used_head = NULL; 766 goto again; 767 } 768 769 ext2fs_free_mem(&cache); 770} 771 772static int init_refcount(struct ext2_qcow2_image *img, blk64_t table_offset) 773{ 774 struct ext2_qcow2_refcount *ref; 775 blk64_t table_clusters; 776 errcode_t ret; 777 778 ref = &(img->refcount); 779 780 /* 781 * One refcount block addresses 2048 clusters, one refcount table 782 * addresses cluster/sizeof(__u64) refcount blocks, and we need 783 * to address meta_blocks_count clusters + qcow2 metadata clusters 784 * in the worst case. 785 */ 786 table_clusters = meta_blocks_count + (table_offset >> 787 img->cluster_bits); 788 table_clusters >>= (img->cluster_bits + 6 - 1); 789 table_clusters = (table_clusters == 0) ? 1 : table_clusters; 790 791 ref->refcount_table_offset = table_offset; 792 ref->refcount_table_clusters = table_clusters; 793 ref->refcount_table_index = 0; 794 ref->refcount_block_index = 0; 795 796 /* Allocate refcount table */ 797 ret = ext2fs_get_arrayzero(ref->refcount_table_clusters, 798 img->cluster_size, &ref->refcount_table); 799 if (ret) 800 return ret; 801 802 /* Allocate refcount block */ 803 ret = ext2fs_get_arrayzero(1, img->cluster_size, &ref->refcount_block); 804 if (ret) 805 ext2fs_free_mem(&ref->refcount_table); 806 807 return ret; 808} 809 810static int initialize_qcow2_image(int fd, ext2_filsys fs, 811 struct ext2_qcow2_image *image) 812{ 813 struct ext2_qcow2_hdr *header; 814 blk64_t total_size, offset; 815 int shift, l2_bits, header_size, l1_size, ret; 816 int cluster_bits = get_bits_from_size(fs->blocksize); 817 struct ext2_super_block *sb = fs->super; 818 819 /* Allocate header */ 820 ret = ext2fs_get_memzero(sizeof(struct ext2_qcow2_hdr), &header); 821 if (ret) 822 return ret; 823 824 total_size = ext2fs_blocks_count(sb) << cluster_bits; 825 image->cluster_size = fs->blocksize; 826 image->l2_size = 1 << (cluster_bits - 3); 827 image->cluster_bits = cluster_bits; 828 image->fd = fd; 829 830 header->magic = ext2fs_cpu_to_be32(QCOW_MAGIC); 831 header->version = ext2fs_cpu_to_be32(QCOW_VERSION); 832 header->size = ext2fs_cpu_to_be64(total_size); 833 header->cluster_bits = ext2fs_cpu_to_be32(cluster_bits); 834 835 header_size = (sizeof(struct ext2_qcow2_hdr) + 7) & ~7; 836 offset = align_offset(header_size, image->cluster_size); 837 838 header->l1_table_offset = ext2fs_cpu_to_be64(offset); 839 image->l1_offset = offset; 840 841 l2_bits = cluster_bits - 3; 842 shift = cluster_bits + l2_bits; 843 l1_size = ((total_size + (1LL << shift) - 1) >> shift); 844 header->l1_size = ext2fs_cpu_to_be32(l1_size); 845 image->l1_size = l1_size; 846 847 /* Make space for L1 table */ 848 offset += align_offset(l1_size * sizeof(blk64_t), image->cluster_size); 849 850 /* Initialize refcounting */ 851 ret = init_refcount(image, offset); 852 if (ret) { 853 ext2fs_free_mem(&header); 854 return ret; 855 } 856 header->refcount_table_offset = ext2fs_cpu_to_be64(offset); 857 header->refcount_table_clusters = 858 ext2fs_cpu_to_be32(image->refcount.refcount_table_clusters); 859 offset += image->cluster_size; 860 offset += image->refcount.refcount_table_clusters << 861 image->cluster_bits; 862 863 /* Make space for L2 tables */ 864 image->l2_offset = offset; 865 offset += image->cluster_size; 866 867 /* Make space for first refcount block */ 868 image->refcount.refcount_block_offset = offset; 869 870 image->hdr = header; 871 /* Initialize l1 and l2 tables */ 872 init_l1_table(image); 873 init_l2_cache(image); 874 875 return 0; 876} 877 878static void free_qcow2_image(struct ext2_qcow2_image *img) 879{ 880 if (!img) 881 return; 882 883 if (img->hdr) 884 ext2fs_free_mem(&img->hdr); 885 886 if (img->l1_table) 887 ext2fs_free_mem(&img->l1_table); 888 889 if (img->refcount.refcount_table) 890 ext2fs_free_mem(&img->refcount.refcount_table); 891 if (img->refcount.refcount_block) 892 ext2fs_free_mem(&img->refcount.refcount_block); 893 894 put_l2_cache(img); 895 896 ext2fs_free_mem(&img); 897} 898 899/** 900 * Put table from used list (used_head) into free list (free_head). 901 * l2_table is used to return pointer to the next used table (used_head). 902 */ 903static void put_used_table(struct ext2_qcow2_image *img, 904 struct ext2_qcow2_l2_table **l2_table) 905{ 906 struct ext2_qcow2_l2_cache *cache = img->l2_cache; 907 struct ext2_qcow2_l2_table *table; 908 909 table = cache->used_head; 910 cache->used_head = table->next; 911 912 assert(table); 913 if (!table->next) 914 cache->used_tail = NULL; 915 916 /* Clean the table for case we will need to use it again */ 917 memset(table->data, 0, img->cluster_size); 918 table->next = cache->free_head; 919 cache->free_head = table; 920 921 cache->free++; 922 923 *l2_table = cache->used_head; 924} 925 926static void flush_l2_cache(struct ext2_qcow2_image *image) 927{ 928 blk64_t seek = 0; 929 ext2_loff_t offset; 930 struct ext2_qcow2_l2_cache *cache = image->l2_cache; 931 struct ext2_qcow2_l2_table *table = cache->used_head; 932 int fd = image->fd; 933 934 /* Store current position */ 935 offset = seek_relative(fd, 0); 936 937 assert(table); 938 while (cache->free < cache->count) { 939 if (seek != table->offset) { 940 seek_set(fd, table->offset); 941 seek = table->offset; 942 } 943 944 generic_write(fd, (char *)table->data, image->cluster_size , 0); 945 put_used_table(image, &table); 946 seek += image->cluster_size; 947 } 948 949 /* Restore previous position */ 950 seek_set(fd, offset); 951} 952 953/** 954 * Get first free table (from free_head) and put it into tail of used list 955 * (to used_tail). 956 * l2_table is used to return pointer to moved table. 957 * Returns 1 if the cache is full, 0 otherwise. 958 */ 959static void get_free_table(struct ext2_qcow2_image *image, 960 struct ext2_qcow2_l2_table **l2_table) 961{ 962 struct ext2_qcow2_l2_table *table; 963 struct ext2_qcow2_l2_cache *cache = image->l2_cache; 964 965 if (0 == cache->free) 966 flush_l2_cache(image); 967 968 table = cache->free_head; 969 assert(table); 970 cache->free_head = table->next; 971 972 if (cache->used_tail) 973 cache->used_tail->next = table; 974 else 975 /* First item in the used list */ 976 cache->used_head = table; 977 978 cache->used_tail = table; 979 cache->free--; 980 981 *l2_table = table; 982} 983 984static int add_l2_item(struct ext2_qcow2_image *img, blk64_t blk, 985 blk64_t data, blk64_t next) 986{ 987 struct ext2_qcow2_l2_cache *cache = img->l2_cache; 988 struct ext2_qcow2_l2_table *table = cache->used_tail; 989 blk64_t l1_index = blk / img->l2_size; 990 blk64_t l2_index = blk & (img->l2_size - 1); 991 int ret = 0; 992 993 /* 994 * Need to create new table if it does not exist, 995 * or if it is full 996 */ 997 if (!table || (table->l1_index != l1_index)) { 998 get_free_table(img, &table); 999 table->l1_index = l1_index; 1000 table->offset = cache->next_offset; 1001 cache->next_offset = next; 1002 img->l1_table[l1_index] = 1003 ext2fs_cpu_to_be64(table->offset | QCOW_OFLAG_COPIED); 1004 ret++; 1005 } 1006 1007 table->data[l2_index] = ext2fs_cpu_to_be64(data | QCOW_OFLAG_COPIED); 1008 return ret; 1009} 1010 1011static int update_refcount(int fd, struct ext2_qcow2_image *img, 1012 blk64_t offset, blk64_t rfblk_pos) 1013{ 1014 struct ext2_qcow2_refcount *ref; 1015 __u32 table_index; 1016 int ret = 0; 1017 1018 ref = &(img->refcount); 1019 table_index = offset >> (2 * img->cluster_bits - 1); 1020 1021 /* 1022 * Need to create new refcount block when the offset addresses 1023 * another item in the refcount table 1024 */ 1025 if (table_index != ref->refcount_table_index) { 1026 1027 seek_set(fd, ref->refcount_block_offset); 1028 1029 generic_write(fd, (char *)ref->refcount_block, 1030 img->cluster_size, 0); 1031 memset(ref->refcount_block, 0, img->cluster_size); 1032 1033 ref->refcount_table[ref->refcount_table_index] = 1034 ext2fs_cpu_to_be64(ref->refcount_block_offset); 1035 ref->refcount_block_offset = rfblk_pos; 1036 ref->refcount_block_index = 0; 1037 ref->refcount_table_index = table_index; 1038 ret++; 1039 } 1040 1041 /* 1042 * We are relying on the fact that we are creating the qcow2 1043 * image sequentially, hence we will always allocate refcount 1044 * block items sequentialy. 1045 */ 1046 ref->refcount_block[ref->refcount_block_index] = ext2fs_cpu_to_be16(1); 1047 ref->refcount_block_index++; 1048 return ret; 1049} 1050 1051static int sync_refcount(int fd, struct ext2_qcow2_image *img) 1052{ 1053 struct ext2_qcow2_refcount *ref; 1054 1055 ref = &(img->refcount); 1056 1057 ref->refcount_table[ref->refcount_table_index] = 1058 ext2fs_cpu_to_be64(ref->refcount_block_offset); 1059 seek_set(fd, ref->refcount_table_offset); 1060 generic_write(fd, (char *)ref->refcount_table, 1061 ref->refcount_table_clusters << img->cluster_bits, 0); 1062 1063 seek_set(fd, ref->refcount_block_offset); 1064 generic_write(fd, (char *)ref->refcount_block, img->cluster_size, 0); 1065 return 0; 1066} 1067 1068static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd) 1069{ 1070 errcode_t retval; 1071 blk64_t blk, offset, size, end; 1072 char *buf; 1073 struct ext2_qcow2_image *img; 1074 unsigned int header_size; 1075 1076 /* allocate struct ext2_qcow2_image */ 1077 retval = ext2fs_get_mem(sizeof(struct ext2_qcow2_image), &img); 1078 if (retval) { 1079 com_err(program_name, retval, 1080 "while allocating ext2_qcow2_image"); 1081 exit(1); 1082 } 1083 1084 retval = initialize_qcow2_image(fd, fs, img); 1085 if (retval) { 1086 com_err(program_name, retval, 1087 "while initializing ext2_qcow2_image"); 1088 exit(1); 1089 } 1090 header_size = align_offset(sizeof(struct ext2_qcow2_hdr), 1091 img->cluster_size); 1092 write_header(fd, img->hdr, sizeof(struct ext2_qcow2_hdr), header_size); 1093 1094 /* Refcount all qcow2 related metadata up to refcount_block_offset */ 1095 end = img->refcount.refcount_block_offset; 1096 seek_set(fd, end); 1097 blk = end + img->cluster_size; 1098 for (offset = 0; offset <= end; offset += img->cluster_size) { 1099 if (update_refcount(fd, img, offset, blk)) { 1100 blk += img->cluster_size; 1101 /* 1102 * If we create new refcount block, we need to refcount 1103 * it as well. 1104 */ 1105 end += img->cluster_size; 1106 } 1107 } 1108 seek_set(fd, offset); 1109 1110 retval = ext2fs_get_mem(fs->blocksize, &buf); 1111 if (retval) { 1112 com_err(program_name, retval, "while allocating buffer"); 1113 exit(1); 1114 } 1115 /* Write qcow2 data blocks */ 1116 for (blk = 0; blk < ext2fs_blocks_count(fs->super); blk++) { 1117 if ((blk >= fs->super->s_first_data_block) && 1118 ext2fs_test_block_bitmap2(meta_block_map, blk)) { 1119 retval = io_channel_read_blk64(fs->io, blk, 1, buf); 1120 if (retval) { 1121 com_err(program_name, retval, 1122 "error reading block %llu", blk); 1123 continue; 1124 } 1125 if (scramble_block_map && 1126 ext2fs_test_block_bitmap2(scramble_block_map, blk)) 1127 scramble_dir_block(fs, blk, buf); 1128 if (check_zero_block(buf, fs->blocksize)) 1129 continue; 1130 1131 if (update_refcount(fd, img, offset, offset)) { 1132 /* Make space for another refcount block */ 1133 offset += img->cluster_size; 1134 seek_set(fd, offset); 1135 /* 1136 * We have created the new refcount block, this 1137 * means that we need to refcount it as well. 1138 * So the previous update_refcount refcounted 1139 * the block itself and now we are going to 1140 * create refcount for data. New refcount 1141 * block should not be created! 1142 */ 1143 if (update_refcount(fd, img, offset, offset)) { 1144 fprintf(stderr, "Programming error: " 1145 "multiple sequential refcount " 1146 "blocks created!\n"); 1147 exit(1); 1148 } 1149 } 1150 1151 generic_write(fd, buf, fs->blocksize, 0); 1152 1153 if (add_l2_item(img, blk, offset, 1154 offset + img->cluster_size)) { 1155 offset += img->cluster_size; 1156 if (update_refcount(fd, img, offset, 1157 offset + img->cluster_size)) { 1158 offset += img->cluster_size; 1159 if (update_refcount(fd, img, offset, 1160 offset)) { 1161 fprintf(stderr, 1162 "Programming error: multiple sequential refcount " 1163 "blocks created!\n"); 1164 exit(1); 1165 } 1166 } 1167 offset += img->cluster_size; 1168 seek_set(fd, offset); 1169 continue; 1170 } 1171 1172 offset += img->cluster_size; 1173 } 1174 } 1175 update_refcount(fd, img, offset, offset); 1176 flush_l2_cache(img); 1177 sync_refcount(fd, img); 1178 1179 /* Write l1_table*/ 1180 seek_set(fd, img->l1_offset); 1181 size = img->l1_size * sizeof(__u64); 1182 generic_write(fd, (char *)img->l1_table, size, 0); 1183 1184 ext2fs_free_mem(&buf); 1185 free_qcow2_image(img); 1186} 1187 1188static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags) 1189{ 1190 struct process_block_struct pb; 1191 struct ext2_inode inode; 1192 ext2_inode_scan scan; 1193 ext2_ino_t ino; 1194 errcode_t retval; 1195 char * block_buf; 1196 1197 meta_blocks_count = 0; 1198 retval = ext2fs_allocate_block_bitmap(fs, "in-use block map", 1199 &meta_block_map); 1200 if (retval) { 1201 com_err(program_name, retval, "while allocating block bitmap"); 1202 exit(1); 1203 } 1204 1205 if (flags & E2IMAGE_SCRAMBLE_FLAG) { 1206 retval = ext2fs_allocate_block_bitmap(fs, "scramble block map", 1207 &scramble_block_map); 1208 if (retval) { 1209 com_err(program_name, retval, 1210 "while allocating scramble block bitmap"); 1211 exit(1); 1212 } 1213 } 1214 1215 mark_table_blocks(fs); 1216 if (show_progress) 1217 printf("Scanning inodes...\n"); 1218 1219 retval = ext2fs_open_inode_scan(fs, 0, &scan); 1220 if (retval) { 1221 com_err(program_name, retval,"%s", 1222 _("while opening inode scan")); 1223 exit(1); 1224 } 1225 1226 retval = ext2fs_get_mem(fs->blocksize * 3, &block_buf); 1227 if (retval) { 1228 com_err(program_name, 0, "%s", 1229 _("Can't allocate block buffer")); 1230 exit(1); 1231 } 1232 1233 use_inode_shortcuts(fs, 1); 1234 stashed_inode = &inode; 1235 while (1) { 1236 retval = ext2fs_get_next_inode(scan, &ino, &inode); 1237 if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) 1238 continue; 1239 if (retval) { 1240 com_err(program_name, retval, "%s", 1241 _("while getting next inode")); 1242 exit(1); 1243 } 1244 if (ino == 0) 1245 break; 1246 if (!inode.i_links_count) 1247 continue; 1248 if (ext2fs_file_acl_block(fs, &inode)) { 1249 ext2fs_mark_block_bitmap2(meta_block_map, 1250 ext2fs_file_acl_block(fs, &inode)); 1251 meta_blocks_count++; 1252 } 1253 if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) 1254 continue; 1255 1256 stashed_ino = ino; 1257 pb.ino = ino; 1258 pb.is_dir = LINUX_S_ISDIR(inode.i_mode); 1259 if (LINUX_S_ISDIR(inode.i_mode) || 1260 (LINUX_S_ISLNK(inode.i_mode) && 1261 ext2fs_inode_has_valid_blocks2(fs, &inode)) || 1262 ino == fs->super->s_journal_inum) { 1263 retval = ext2fs_block_iterate3(fs, ino, 1264 BLOCK_FLAG_READ_ONLY, block_buf, 1265 process_dir_block, &pb); 1266 if (retval) { 1267 com_err(program_name, retval, 1268 "while iterating over inode %u", 1269 ino); 1270 exit(1); 1271 } 1272 } else { 1273 if ((inode.i_flags & EXT4_EXTENTS_FL) || 1274 inode.i_block[EXT2_IND_BLOCK] || 1275 inode.i_block[EXT2_DIND_BLOCK] || 1276 inode.i_block[EXT2_TIND_BLOCK] || all_data) { 1277 retval = ext2fs_block_iterate3(fs, 1278 ino, BLOCK_FLAG_READ_ONLY, block_buf, 1279 process_file_block, &pb); 1280 if (retval) { 1281 com_err(program_name, retval, 1282 "while iterating over inode %u", ino); 1283 exit(1); 1284 } 1285 } 1286 } 1287 } 1288 use_inode_shortcuts(fs, 0); 1289 1290 if (type & E2IMAGE_QCOW2) 1291 output_qcow2_meta_data_blocks(fs, fd); 1292 else 1293 output_meta_data_blocks(fs, fd); 1294 1295 ext2fs_free_mem(&block_buf); 1296 ext2fs_close_inode_scan(scan); 1297 ext2fs_free_block_bitmap(meta_block_map); 1298 if (type & E2IMAGE_SCRAMBLE_FLAG) 1299 ext2fs_free_block_bitmap(scramble_block_map); 1300} 1301 1302static void install_image(char *device, char *image_fn, int type) 1303{ 1304 errcode_t retval; 1305 ext2_filsys fs; 1306 int open_flag = EXT2_FLAG_IMAGE_FILE | EXT2_FLAG_64BITS; 1307 int fd = 0; 1308 io_manager io_ptr; 1309 io_channel io; 1310 1311 if (type) { 1312 com_err(program_name, 0, "Raw and qcow2 images cannot" 1313 "be installed"); 1314 exit(1); 1315 } 1316 1317#ifdef CONFIG_TESTIO_DEBUG 1318 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { 1319 io_ptr = test_io_manager; 1320 test_io_backing_manager = unix_io_manager; 1321 } else 1322#endif 1323 io_ptr = unix_io_manager; 1324 1325 retval = ext2fs_open (image_fn, open_flag, 0, 0, 1326 io_ptr, &fs); 1327 if (retval) { 1328 com_err (program_name, retval, _("while trying to open %s"), 1329 image_fn); 1330 exit(1); 1331 } 1332 1333 retval = ext2fs_read_bitmaps (fs); 1334 if (retval) { 1335 com_err(program_name, retval, "error reading bitmaps"); 1336 exit(1); 1337 } 1338 1339 fd = ext2fs_open_file(image_fn, O_RDONLY, 0); 1340 if (fd < 0) { 1341 perror(image_fn); 1342 exit(1); 1343 } 1344 1345 retval = io_ptr->open(device, IO_FLAG_RW, &io); 1346 if (retval) { 1347 com_err(device, 0, "while opening device file"); 1348 exit(1); 1349 } 1350 1351 ext2fs_rewrite_to_io(fs, io); 1352 1353 seek_set(fd, fs->image_header->offset_inode); 1354 1355 retval = ext2fs_image_inode_read(fs, fd, 0); 1356 if (retval) { 1357 com_err(image_fn, 0, "while restoring the image table"); 1358 exit(1); 1359 } 1360 1361 close(fd); 1362 ext2fs_close (fs); 1363} 1364 1365static struct ext2_qcow2_hdr *check_qcow2_image(int *fd, char *name) 1366{ 1367 1368 *fd = ext2fs_open_file(name, O_RDONLY, 0600); 1369 if (*fd < 0) 1370 return NULL; 1371 1372 return qcow2_read_header(*fd); 1373} 1374 1375int main (int argc, char ** argv) 1376{ 1377 int c; 1378 errcode_t retval; 1379 ext2_filsys fs; 1380 char *image_fn; 1381 struct ext2_qcow2_hdr *header = NULL; 1382 int open_flag = EXT2_FLAG_64BITS; 1383 int img_type = 0; 1384 int flags = 0; 1385 int mount_flags = 0; 1386 int qcow2_fd = 0; 1387 int fd = 0; 1388 int ret = 0; 1389 int ignore_rw_mount = 0; 1390 struct stat st; 1391 1392#ifdef ENABLE_NLS 1393 setlocale(LC_MESSAGES, ""); 1394 setlocale(LC_CTYPE, ""); 1395 bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 1396 textdomain(NLS_CAT_NAME); 1397 set_com_err_gettext(gettext); 1398#endif 1399 fprintf (stderr, "e2image %s (%s)\n", E2FSPROGS_VERSION, 1400 E2FSPROGS_DATE); 1401 if (argc && *argv) 1402 program_name = *argv; 1403 add_error_table(&et_ext2_error_table); 1404 while ((c = getopt(argc, argv, "rsIQafo:O:p")) != EOF) 1405 switch (c) { 1406 case 'I': 1407 flags |= E2IMAGE_INSTALL_FLAG; 1408 break; 1409 case 'Q': 1410 if (img_type) 1411 usage(); 1412 img_type |= E2IMAGE_QCOW2; 1413 break; 1414 case 'r': 1415 if (img_type) 1416 usage(); 1417 img_type |= E2IMAGE_RAW; 1418 break; 1419 case 's': 1420 flags |= E2IMAGE_SCRAMBLE_FLAG; 1421 break; 1422 case 'a': 1423 all_data = 1; 1424 break; 1425 case 'f': 1426 ignore_rw_mount = 1; 1427 break; 1428 case 'o': 1429 source_offset = strtoull(optarg, NULL, 0); 1430 break; 1431 case 'O': 1432 dest_offset = strtoull(optarg, NULL, 0); 1433 break; 1434 case 'p': 1435 show_progress = 1; 1436 break; 1437 default: 1438 usage(); 1439 } 1440 if (optind == argc - 1 && 1441 (source_offset || dest_offset)) 1442 move_mode = 1; 1443 else if (optind != argc - 2 ) 1444 usage(); 1445 1446 if (all_data && !img_type) { 1447 com_err(program_name, 0, "-a option can only be used " 1448 "with raw or QCOW2 images."); 1449 exit(1); 1450 } 1451 if ((source_offset || dest_offset) && img_type != E2IMAGE_RAW) { 1452 com_err(program_name, 0, 1453 "Offsets are only allowed with raw images."); 1454 exit(1); 1455 } 1456 if (move_mode && img_type != E2IMAGE_RAW) { 1457 com_err(program_name, 0, 1458 "Move mode is only allowed with raw images."); 1459 exit(1); 1460 } 1461 if (move_mode && !all_data) { 1462 com_err(program_name, 0, 1463 "Move mode requires all data mode."); 1464 exit(1); 1465 } 1466 device_name = argv[optind]; 1467 if (move_mode) 1468 image_fn = device_name; 1469 else image_fn = argv[optind+1]; 1470 1471 retval = ext2fs_check_if_mounted(device_name, &mount_flags); 1472 if (retval) { 1473 com_err(program_name, retval, "checking if mounted"); 1474 exit(1); 1475 } 1476 1477 if (img_type && !ignore_rw_mount && 1478 (mount_flags & EXT2_MF_MOUNTED) && 1479 !(mount_flags & EXT2_MF_READONLY)) { 1480 fprintf(stderr, "\nRunning e2image on a R/W mounted " 1481 "filesystem can result in an\n" 1482 "inconsistent image which will not be useful " 1483 "for debugging purposes.\n" 1484 "Use -f option if you really want to do that.\n"); 1485 exit(1); 1486 } 1487 1488 if (flags & E2IMAGE_INSTALL_FLAG) { 1489 install_image(device_name, image_fn, img_type); 1490 exit (0); 1491 } 1492 1493 if (img_type & E2IMAGE_RAW) { 1494 header = check_qcow2_image(&qcow2_fd, device_name); 1495 if (header) { 1496 flags |= E2IMAGE_IS_QCOW2_FLAG; 1497 goto skip_device; 1498 } 1499 } 1500 char *options; 1501 asprintf (&options, "offset=%llu", source_offset); 1502 retval = ext2fs_open2 (device_name, options, open_flag, 0, 0, 1503 unix_io_manager, &fs); 1504 free (options); 1505 if (retval) { 1506 com_err (program_name, retval, _("while trying to open %s"), 1507 device_name); 1508 fputs(_("Couldn't find valid filesystem superblock.\n"), stdout); 1509 exit(1); 1510 } 1511 1512skip_device: 1513 if (strcmp(image_fn, "-") == 0) 1514 fd = 1; 1515 else { 1516 int o_flags = O_CREAT|O_WRONLY; 1517 1518 if (img_type != E2IMAGE_RAW) 1519 o_flags |= O_TRUNC; 1520 fd = ext2fs_open_file(image_fn, o_flags, 0600); 1521 if (fd < 0) { 1522 com_err(program_name, errno, 1523 _("while trying to open %s"), image_fn); 1524 exit(1); 1525 } 1526 } 1527 if (dest_offset) 1528 seek_set(fd, dest_offset); 1529 1530 if ((img_type & E2IMAGE_QCOW2) && (fd == 1)) { 1531 com_err(program_name, 0, "QCOW2 image can not be written to " 1532 "the stdout!\n"); 1533 exit(1); 1534 } 1535 if (fd != 1) { 1536 if (fstat(fd, &st)) { 1537 com_err(program_name, 0, "Can not stat output\n"); 1538 exit(1); 1539 } 1540 if (S_ISBLK(st.st_mode)) 1541 output_is_blk = 1; 1542 } 1543 if (flags & E2IMAGE_IS_QCOW2_FLAG) { 1544 ret = qcow2_write_raw_image(qcow2_fd, fd, header); 1545 if (ret) { 1546 if (ret == -QCOW_COMPRESSED) 1547 fprintf(stderr, "Image (%s) is compressed\n", 1548 image_fn); 1549 if (ret == -QCOW_ENCRYPTED) 1550 fprintf(stderr, "Image (%s) is encrypted\n", 1551 image_fn); 1552 com_err(program_name, ret, 1553 _("while trying to convert qcow2 image" 1554 " (%s) into raw image (%s)"), 1555 device_name, image_fn); 1556 } 1557 goto out; 1558 } 1559 1560 1561 if (img_type) 1562 write_raw_image_file(fs, fd, img_type, flags); 1563 else 1564 write_image_file(fs, fd); 1565 1566 ext2fs_close (fs); 1567out: 1568 if (header) 1569 free(header); 1570 if (qcow2_fd) 1571 close(qcow2_fd); 1572 remove_error_table(&et_ext2_error_table); 1573 return ret; 1574} 1575