]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - misc/e2image.c
tests: add test for handling an invalid symlink in an inline directory
[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 retval = ext2fs_block_iterate3(fs, ino,
1375 BLOCK_FLAG_READ_ONLY, block_buf,
1376 process_dir_block, &pb);
1377 if (retval) {
1378 com_err(program_name, retval,
1379 _("while iterating over inode %u"),
1380 ino);
1381 exit(1);
1382 }
1383 } else {
1384 if ((inode.i_flags & EXT4_EXTENTS_FL) ||
1385 inode.i_block[EXT2_IND_BLOCK] ||
1386 inode.i_block[EXT2_DIND_BLOCK] ||
1387 inode.i_block[EXT2_TIND_BLOCK] || all_data) {
1388 retval = ext2fs_block_iterate3(fs,
1389 ino, BLOCK_FLAG_READ_ONLY, block_buf,
1390 process_file_block, &pb);
1391 if (retval) {
1392 com_err(program_name, retval,
1393 _("while iterating over inode %u"), ino);
1394 exit(1);
1395 }
1396 }
1397 }
1398 }
1399 use_inode_shortcuts(fs, 0);
1400
1401 if (type & E2IMAGE_QCOW2)
1402 output_qcow2_meta_data_blocks(fs, fd);
1403 else
1404 output_meta_data_blocks(fs, fd, flags);
1405
1406 ext2fs_free_mem(&block_buf);
1407 ext2fs_close_inode_scan(scan);
1408 ext2fs_free_block_bitmap(meta_block_map);
1409 if (type & E2IMAGE_SCRAMBLE_FLAG)
1410 ext2fs_free_block_bitmap(scramble_block_map);
1411 }
1412
1413 static void install_image(char *device, char *image_fn, int type)
1414 {
1415 errcode_t retval;
1416 ext2_filsys fs;
1417 int open_flag = EXT2_FLAG_IMAGE_FILE | EXT2_FLAG_64BITS |
1418 EXT2_FLAG_IGNORE_CSUM_ERRORS;
1419 int fd = 0;
1420 io_manager io_ptr;
1421 io_channel io;
1422
1423 if (type) {
1424 com_err(program_name, 0, "%s",
1425 _("Raw and qcow2 images cannot be installed"));
1426 exit(1);
1427 }
1428
1429 #ifdef CONFIG_TESTIO_DEBUG
1430 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
1431 io_ptr = test_io_manager;
1432 test_io_backing_manager = unix_io_manager;
1433 } else
1434 #endif
1435 io_ptr = unix_io_manager;
1436
1437 retval = ext2fs_open (image_fn, open_flag, 0, 0,
1438 io_ptr, &fs);
1439 if (retval) {
1440 com_err(program_name, retval, _("while trying to open %s"),
1441 image_fn);
1442 exit(1);
1443 }
1444
1445 retval = ext2fs_read_bitmaps (fs);
1446 if (retval) {
1447 com_err(program_name, retval, "%s", _("error reading bitmaps"));
1448 exit(1);
1449 }
1450
1451 fd = ext2fs_open_file(image_fn, O_RDONLY, 0);
1452 if (fd < 0) {
1453 perror(image_fn);
1454 exit(1);
1455 }
1456
1457 retval = io_ptr->open(device, IO_FLAG_RW, &io);
1458 if (retval) {
1459 com_err(device, 0, "%s", _("while opening device file"));
1460 exit(1);
1461 }
1462
1463 ext2fs_rewrite_to_io(fs, io);
1464
1465 seek_set(fd, ext2fs_le32_to_cpu(fs->image_header->offset_inode));
1466
1467 retval = ext2fs_image_inode_read(fs, fd, 0);
1468 if (retval) {
1469 com_err(image_fn, 0, "%s",
1470 _("while restoring the image table"));
1471 exit(1);
1472 }
1473
1474 close(fd);
1475 ext2fs_close_free(&fs);
1476 }
1477
1478 static struct ext2_qcow2_hdr *check_qcow2_image(int *fd, char *name)
1479 {
1480
1481 *fd = ext2fs_open_file(name, O_RDONLY, 0600);
1482 if (*fd < 0)
1483 return NULL;
1484
1485 return qcow2_read_header(*fd);
1486 }
1487
1488 int main (int argc, char ** argv)
1489 {
1490 int c;
1491 errcode_t retval;
1492 ext2_filsys fs;
1493 char *image_fn, offset_opt[64];
1494 struct ext2_qcow2_hdr *header = NULL;
1495 int open_flag = EXT2_FLAG_64BITS | EXT2_FLAG_THREADS |
1496 EXT2_FLAG_IGNORE_CSUM_ERRORS;
1497 int img_type = 0;
1498 int flags = 0;
1499 int mount_flags = 0;
1500 int qcow2_fd = 0;
1501 int fd = 0;
1502 int ret = 0;
1503 int ignore_rw_mount = 0;
1504 int check = 0;
1505 struct stat st;
1506 blk64_t superblock = 0;
1507 int blocksize = 0;
1508
1509 #ifdef ENABLE_NLS
1510 setlocale(LC_MESSAGES, "");
1511 setlocale(LC_CTYPE, "");
1512 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
1513 textdomain(NLS_CAT_NAME);
1514 set_com_err_gettext(gettext);
1515 #endif
1516 fprintf (stderr, "e2image %s (%s)\n", E2FSPROGS_VERSION,
1517 E2FSPROGS_DATE);
1518 if (argc && *argv)
1519 program_name = *argv;
1520 else
1521 usage();
1522 add_error_table(&et_ext2_error_table);
1523 while ((c = getopt(argc, argv, "b:B:nrsIQafo:O:pc")) != EOF)
1524 switch (c) {
1525 case 'b':
1526 superblock = strtoull(optarg, NULL, 0);
1527 break;
1528 case 'B':
1529 blocksize = strtoul(optarg, NULL, 0);
1530 break;
1531 case 'I':
1532 flags |= E2IMAGE_INSTALL_FLAG;
1533 break;
1534 case 'Q':
1535 if (img_type)
1536 usage();
1537 img_type |= E2IMAGE_QCOW2;
1538 break;
1539 case 'r':
1540 if (img_type)
1541 usage();
1542 img_type |= E2IMAGE_RAW;
1543 break;
1544 case 's':
1545 flags |= E2IMAGE_SCRAMBLE_FLAG;
1546 break;
1547 case 'a':
1548 all_data = 1;
1549 break;
1550 case 'f':
1551 ignore_rw_mount = 1;
1552 break;
1553 case 'n':
1554 nop_flag = 1;
1555 break;
1556 case 'o':
1557 source_offset = strtoull(optarg, NULL, 0);
1558 break;
1559 case 'O':
1560 dest_offset = strtoull(optarg, NULL, 0);
1561 break;
1562 case 'p':
1563 show_progress = 1;
1564 break;
1565 case 'c':
1566 check = 1;
1567 break;
1568 default:
1569 usage();
1570 }
1571 if (optind == argc - 1 &&
1572 (source_offset || dest_offset))
1573 move_mode = 1;
1574 else if (optind != argc - 2 )
1575 usage();
1576
1577 if (all_data && !img_type) {
1578 com_err(program_name, 0, "%s", _("-a option can only be used "
1579 "with raw or QCOW2 images."));
1580 exit(1);
1581 }
1582 if (superblock && !img_type) {
1583 com_err(program_name, 0, "%s", _("-b option can only be used "
1584 "with raw or QCOW2 images."));
1585 exit(1);
1586 }
1587 if ((source_offset || dest_offset) && img_type != E2IMAGE_RAW) {
1588 com_err(program_name, 0, "%s",
1589 _("Offsets are only allowed with raw images."));
1590 exit(1);
1591 }
1592 if (move_mode && img_type != E2IMAGE_RAW) {
1593 com_err(program_name, 0, "%s",
1594 _("Move mode is only allowed with raw images."));
1595 exit(1);
1596 }
1597 if (move_mode && !all_data) {
1598 com_err(program_name, 0, "%s",
1599 _("Move mode requires all data mode."));
1600 exit(1);
1601 }
1602 device_name = argv[optind];
1603 if (move_mode)
1604 image_fn = device_name;
1605 else image_fn = argv[optind+1];
1606
1607 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
1608 if (retval) {
1609 com_err(program_name, retval, "%s", _("checking if mounted"));
1610 exit(1);
1611 }
1612
1613 if (img_type && !ignore_rw_mount &&
1614 (mount_flags & EXT2_MF_MOUNTED) &&
1615 !(mount_flags & EXT2_MF_READONLY)) {
1616 fprintf(stderr, "%s", _("\nRunning e2image on a R/W mounted "
1617 "filesystem can result in an\n"
1618 "inconsistent image which will not be useful "
1619 "for debugging purposes.\n"
1620 "Use -f option if you really want to do that.\n"));
1621 exit(1);
1622 }
1623
1624 if (flags & E2IMAGE_INSTALL_FLAG) {
1625 install_image(device_name, image_fn, img_type);
1626 exit (0);
1627 }
1628
1629 if (img_type & E2IMAGE_RAW) {
1630 header = check_qcow2_image(&qcow2_fd, device_name);
1631 if (header) {
1632 flags |= E2IMAGE_IS_QCOW2_FLAG;
1633 goto skip_device;
1634 }
1635 }
1636 sprintf(offset_opt, "offset=%llu", (unsigned long long) source_offset);
1637 retval = ext2fs_open2(device_name, offset_opt, open_flag,
1638 superblock, blocksize, unix_io_manager, &fs);
1639 if (retval) {
1640 com_err (program_name, retval, _("while trying to open %s"),
1641 device_name);
1642 fputs(_("Couldn't find valid filesystem superblock.\n"), stdout);
1643 if (retval == EXT2_ET_BAD_MAGIC)
1644 check_plausibility(device_name, CHECK_FS_EXIST, NULL);
1645 exit(1);
1646 }
1647
1648 skip_device:
1649 if (strcmp(image_fn, "-") == 0)
1650 fd = 1;
1651 else {
1652 int o_flags = O_CREAT|O_RDWR;
1653
1654 if (img_type != E2IMAGE_RAW)
1655 o_flags |= O_TRUNC;
1656 if (access(image_fn, F_OK) != 0)
1657 flags |= E2IMAGE_CHECK_ZERO_FLAG;
1658 fd = ext2fs_open_file(image_fn, o_flags, 0600);
1659 if (fd < 0) {
1660 com_err(program_name, errno,
1661 _("while trying to open %s"), image_fn);
1662 exit(1);
1663 }
1664 }
1665 if (dest_offset)
1666 seek_set(fd, dest_offset);
1667
1668 if ((img_type & E2IMAGE_QCOW2) && (fd == 1)) {
1669 com_err(program_name, 0, "%s",
1670 _("QCOW2 image can not be written to the stdout!\n"));
1671 exit(1);
1672 }
1673 if (fd != 1) {
1674 if (fstat(fd, &st)) {
1675 com_err(program_name, 0, "%s",
1676 _("Can not stat output\n"));
1677 exit(1);
1678 }
1679 if (ext2fsP_is_disk_device(st.st_mode))
1680 output_is_blk = 1;
1681 }
1682 if (flags & E2IMAGE_IS_QCOW2_FLAG) {
1683 ret = qcow2_write_raw_image(qcow2_fd, fd, header);
1684 if (ret) {
1685 if (ret == -QCOW_COMPRESSED)
1686 fprintf(stderr, _("Image (%s) is compressed\n"),
1687 image_fn);
1688 else if (ret == -QCOW_ENCRYPTED)
1689 fprintf(stderr, _("Image (%s) is encrypted\n"),
1690 image_fn);
1691 else if (ret == -QCOW_CORRUPTED)
1692 fprintf(stderr, _("Image (%s) is corrupted\n"),
1693 image_fn);
1694 else
1695 com_err(program_name, ret,
1696 _("while trying to convert qcow2 image"
1697 " (%s) into raw image (%s)"),
1698 image_fn, device_name);
1699 ret = 1;
1700 }
1701 goto out;
1702 }
1703
1704 if (check) {
1705 if (img_type != E2IMAGE_RAW) {
1706 fprintf(stderr, "%s", _("The -c option only supported "
1707 "in raw mode\n"));
1708 exit(1);
1709 }
1710 if (fd == 1) {
1711 fprintf(stderr, "%s", _("The -c option not supported "
1712 "when writing to stdout\n"));
1713 exit(1);
1714 }
1715 retval = ext2fs_get_mem(fs->blocksize, &check_buf);
1716 if (retval) {
1717 com_err(program_name, retval, "%s",
1718 _("while allocating check_buf"));
1719 exit(1);
1720 }
1721 }
1722 if (show_progress && (img_type != E2IMAGE_RAW)) {
1723 fprintf(stderr, "%s",
1724 _("The -p option only supported in raw mode\n"));
1725 exit(1);
1726 }
1727 if (img_type)
1728 write_raw_image_file(fs, fd, img_type, flags, superblock);
1729 else
1730 write_image_file(fs, fd);
1731
1732 ext2fs_close_free(&fs);
1733 if (check)
1734 printf(_("%d blocks already contained the data to be copied\n"),
1735 skipped_blocks);
1736
1737 out:
1738 if (header)
1739 free(header);
1740 if (qcow2_fd)
1741 close(qcow2_fd);
1742 remove_error_table(&et_ext2_error_table);
1743 return ret;
1744 }