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