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