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