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