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