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