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