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