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