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