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