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