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