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