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