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