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