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