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