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