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