e2image.c revision c40c7ceffe5ca88ec43b853e4a908f1cbb8c0f15
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
22extern char *optarg;
23extern 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
53static const char * program_name = "e2image";
54static char * device_name = NULL;
55static char all_data;
56static char output_is_blk;
57/* writing to blk device: don't skip zeroed blocks */
58blk64_t source_offset, dest_offset;
59char move_mode;
60char show_progress;
61
62static void lseek_error_and_exit(int errnum)
63{
64	fprintf(stderr, "seek: %s\n", error_message(errnum));
65	exit(1);
66}
67
68static blk64_t align_offset(blk64_t offset, int n)
69{
70	return (offset + n - 1) & ~(n - 1);
71}
72
73static 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
91static 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
98static 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
134static 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
165static 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 */
230static ext2fs_block_bitmap meta_block_map;
231static ext2fs_block_bitmap scramble_block_map;	/* Directory blocks to be scrambled */
232static blk64_t meta_blocks_count;
233
234struct 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 */
245static ino_t stashed_ino = 0;
246static struct ext2_inode *stashed_inode;
247
248static 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
262static 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
273static 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
283static 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
297static 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
315static 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
329static 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 */
397static 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
412static 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
425static int name_id[256];
426
427#define EXT4_MAX_REC_LEN		((1<<16)-1)
428
429static 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
491static 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	}
534more_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
647static 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
661static 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
698alloc_err:
699	com_err(program_name, ret, "while allocating l2 cache");
700	exit(1);
701}
702
703static 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;
713again:
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
733static 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
771static 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
839static 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 */
864static 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
887static 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 */
923static 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
948static 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
975static 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
1016static 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
1035static 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
1160static 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
1274static 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
1340static 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
1350int 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
1487skip_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);
1545out:
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}
1553