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