1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * image.c --- writes out the critical parts of the filesystem as a
3*6a54128fSAndroid Build Coastguard Worker * flat file.
4*6a54128fSAndroid Build Coastguard Worker *
5*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2000 Theodore Ts'o.
6*6a54128fSAndroid Build Coastguard Worker *
7*6a54128fSAndroid Build Coastguard Worker * Note: this uses the POSIX IO interfaces, unlike most of the other
8*6a54128fSAndroid Build Coastguard Worker * functions in this library. So sue me.
9*6a54128fSAndroid Build Coastguard Worker *
10*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
11*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU Library
12*6a54128fSAndroid Build Coastguard Worker * General Public License, version 2.
13*6a54128fSAndroid Build Coastguard Worker * %End-Header%
14*6a54128fSAndroid Build Coastguard Worker */
15*6a54128fSAndroid Build Coastguard Worker
16*6a54128fSAndroid Build Coastguard Worker #include "config.h"
17*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
18*6a54128fSAndroid Build Coastguard Worker #include <string.h>
19*6a54128fSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
20*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
21*6a54128fSAndroid Build Coastguard Worker #endif
22*6a54128fSAndroid Build Coastguard Worker #if HAVE_ERRNO_H
23*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
24*6a54128fSAndroid Build Coastguard Worker #endif
25*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
26*6a54128fSAndroid Build Coastguard Worker #include <time.h>
27*6a54128fSAndroid Build Coastguard Worker #if HAVE_SYS_STAT_H
28*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
29*6a54128fSAndroid Build Coastguard Worker #endif
30*6a54128fSAndroid Build Coastguard Worker #if HAVE_SYS_TYPES_H
31*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
32*6a54128fSAndroid Build Coastguard Worker #endif
33*6a54128fSAndroid Build Coastguard Worker
34*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
35*6a54128fSAndroid Build Coastguard Worker #include "ext2fs.h"
36*6a54128fSAndroid Build Coastguard Worker
37*6a54128fSAndroid Build Coastguard Worker #ifndef HAVE_TYPE_SSIZE_T
38*6a54128fSAndroid Build Coastguard Worker typedef int ssize_t;
39*6a54128fSAndroid Build Coastguard Worker #endif
40*6a54128fSAndroid Build Coastguard Worker
41*6a54128fSAndroid Build Coastguard Worker /*
42*6a54128fSAndroid Build Coastguard Worker * This function returns 1 if the specified block is all zeros
43*6a54128fSAndroid Build Coastguard Worker */
check_zero_block(char * buf,int blocksize)44*6a54128fSAndroid Build Coastguard Worker static int check_zero_block(char *buf, int blocksize)
45*6a54128fSAndroid Build Coastguard Worker {
46*6a54128fSAndroid Build Coastguard Worker char *cp = buf;
47*6a54128fSAndroid Build Coastguard Worker int left = blocksize;
48*6a54128fSAndroid Build Coastguard Worker
49*6a54128fSAndroid Build Coastguard Worker while (left > 0) {
50*6a54128fSAndroid Build Coastguard Worker if (*cp++)
51*6a54128fSAndroid Build Coastguard Worker return 0;
52*6a54128fSAndroid Build Coastguard Worker left--;
53*6a54128fSAndroid Build Coastguard Worker }
54*6a54128fSAndroid Build Coastguard Worker return 1;
55*6a54128fSAndroid Build Coastguard Worker }
56*6a54128fSAndroid Build Coastguard Worker
57*6a54128fSAndroid Build Coastguard Worker /*
58*6a54128fSAndroid Build Coastguard Worker * Write the inode table out as a single block.
59*6a54128fSAndroid Build Coastguard Worker */
60*6a54128fSAndroid Build Coastguard Worker #define BUF_BLOCKS 32
61*6a54128fSAndroid Build Coastguard Worker
ext2fs_image_inode_write(ext2_filsys fs,int fd,int flags)62*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
63*6a54128fSAndroid Build Coastguard Worker {
64*6a54128fSAndroid Build Coastguard Worker dgrp_t group;
65*6a54128fSAndroid Build Coastguard Worker ssize_t left, c, d;
66*6a54128fSAndroid Build Coastguard Worker char *buf, *cp;
67*6a54128fSAndroid Build Coastguard Worker blk64_t blk;
68*6a54128fSAndroid Build Coastguard Worker ssize_t actual;
69*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
70*6a54128fSAndroid Build Coastguard Worker ext2_loff_t r;
71*6a54128fSAndroid Build Coastguard Worker
72*6a54128fSAndroid Build Coastguard Worker buf = malloc(fs->blocksize * BUF_BLOCKS);
73*6a54128fSAndroid Build Coastguard Worker if (!buf)
74*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
75*6a54128fSAndroid Build Coastguard Worker
76*6a54128fSAndroid Build Coastguard Worker for (group = 0; group < fs->group_desc_count; group++) {
77*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_inode_table_loc(fs, group);
78*6a54128fSAndroid Build Coastguard Worker if (!blk) {
79*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_MISSING_INODE_TABLE;
80*6a54128fSAndroid Build Coastguard Worker goto errout;
81*6a54128fSAndroid Build Coastguard Worker }
82*6a54128fSAndroid Build Coastguard Worker left = fs->inode_blocks_per_group;
83*6a54128fSAndroid Build Coastguard Worker if ((blk < fs->super->s_first_data_block) ||
84*6a54128fSAndroid Build Coastguard Worker (blk + left - 1 >= ext2fs_blocks_count(fs->super))) {
85*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
86*6a54128fSAndroid Build Coastguard Worker goto errout;
87*6a54128fSAndroid Build Coastguard Worker }
88*6a54128fSAndroid Build Coastguard Worker while (left) {
89*6a54128fSAndroid Build Coastguard Worker c = BUF_BLOCKS;
90*6a54128fSAndroid Build Coastguard Worker if (c > left)
91*6a54128fSAndroid Build Coastguard Worker c = left;
92*6a54128fSAndroid Build Coastguard Worker retval = io_channel_read_blk64(fs->io, blk, c, buf);
93*6a54128fSAndroid Build Coastguard Worker if (retval)
94*6a54128fSAndroid Build Coastguard Worker goto errout;
95*6a54128fSAndroid Build Coastguard Worker cp = buf;
96*6a54128fSAndroid Build Coastguard Worker while (c) {
97*6a54128fSAndroid Build Coastguard Worker if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
98*6a54128fSAndroid Build Coastguard Worker d = c;
99*6a54128fSAndroid Build Coastguard Worker goto skip_sparse;
100*6a54128fSAndroid Build Coastguard Worker }
101*6a54128fSAndroid Build Coastguard Worker /* Skip zero blocks */
102*6a54128fSAndroid Build Coastguard Worker if (check_zero_block(cp, fs->blocksize)) {
103*6a54128fSAndroid Build Coastguard Worker c--;
104*6a54128fSAndroid Build Coastguard Worker blk++;
105*6a54128fSAndroid Build Coastguard Worker left--;
106*6a54128fSAndroid Build Coastguard Worker cp += fs->blocksize;
107*6a54128fSAndroid Build Coastguard Worker r = ext2fs_llseek(fd, fs->blocksize,
108*6a54128fSAndroid Build Coastguard Worker SEEK_CUR);
109*6a54128fSAndroid Build Coastguard Worker if (r < 0) {
110*6a54128fSAndroid Build Coastguard Worker retval = errno;
111*6a54128fSAndroid Build Coastguard Worker goto errout;
112*6a54128fSAndroid Build Coastguard Worker }
113*6a54128fSAndroid Build Coastguard Worker continue;
114*6a54128fSAndroid Build Coastguard Worker }
115*6a54128fSAndroid Build Coastguard Worker /* Find non-zero blocks */
116*6a54128fSAndroid Build Coastguard Worker for (d = 1; d < c; d++) {
117*6a54128fSAndroid Build Coastguard Worker if (check_zero_block(cp +
118*6a54128fSAndroid Build Coastguard Worker d * fs->blocksize,
119*6a54128fSAndroid Build Coastguard Worker fs->blocksize))
120*6a54128fSAndroid Build Coastguard Worker break;
121*6a54128fSAndroid Build Coastguard Worker }
122*6a54128fSAndroid Build Coastguard Worker skip_sparse:
123*6a54128fSAndroid Build Coastguard Worker actual = write(fd, cp, d * fs->blocksize);
124*6a54128fSAndroid Build Coastguard Worker if (actual == -1) {
125*6a54128fSAndroid Build Coastguard Worker retval = errno;
126*6a54128fSAndroid Build Coastguard Worker goto errout;
127*6a54128fSAndroid Build Coastguard Worker }
128*6a54128fSAndroid Build Coastguard Worker if (actual != d * fs->blocksize) {
129*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_SHORT_WRITE;
130*6a54128fSAndroid Build Coastguard Worker goto errout;
131*6a54128fSAndroid Build Coastguard Worker }
132*6a54128fSAndroid Build Coastguard Worker blk += d;
133*6a54128fSAndroid Build Coastguard Worker left -= d;
134*6a54128fSAndroid Build Coastguard Worker cp += d * fs->blocksize;
135*6a54128fSAndroid Build Coastguard Worker c -= d;
136*6a54128fSAndroid Build Coastguard Worker }
137*6a54128fSAndroid Build Coastguard Worker }
138*6a54128fSAndroid Build Coastguard Worker }
139*6a54128fSAndroid Build Coastguard Worker retval = 0;
140*6a54128fSAndroid Build Coastguard Worker
141*6a54128fSAndroid Build Coastguard Worker errout:
142*6a54128fSAndroid Build Coastguard Worker free(buf);
143*6a54128fSAndroid Build Coastguard Worker return retval;
144*6a54128fSAndroid Build Coastguard Worker }
145*6a54128fSAndroid Build Coastguard Worker
146*6a54128fSAndroid Build Coastguard Worker /*
147*6a54128fSAndroid Build Coastguard Worker * Read in the inode table and stuff it into place
148*6a54128fSAndroid Build Coastguard Worker */
ext2fs_image_inode_read(ext2_filsys fs,int fd,int flags EXT2FS_ATTR ((unused)))149*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
150*6a54128fSAndroid Build Coastguard Worker int flags EXT2FS_ATTR((unused)))
151*6a54128fSAndroid Build Coastguard Worker {
152*6a54128fSAndroid Build Coastguard Worker dgrp_t group;
153*6a54128fSAndroid Build Coastguard Worker ssize_t c, left;
154*6a54128fSAndroid Build Coastguard Worker char *buf;
155*6a54128fSAndroid Build Coastguard Worker blk64_t blk;
156*6a54128fSAndroid Build Coastguard Worker ssize_t actual;
157*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
158*6a54128fSAndroid Build Coastguard Worker
159*6a54128fSAndroid Build Coastguard Worker buf = malloc(fs->blocksize * BUF_BLOCKS);
160*6a54128fSAndroid Build Coastguard Worker if (!buf)
161*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
162*6a54128fSAndroid Build Coastguard Worker
163*6a54128fSAndroid Build Coastguard Worker for (group = 0; group < fs->group_desc_count; group++) {
164*6a54128fSAndroid Build Coastguard Worker blk = ext2fs_inode_table_loc(fs, group);
165*6a54128fSAndroid Build Coastguard Worker if (!blk) {
166*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_MISSING_INODE_TABLE;
167*6a54128fSAndroid Build Coastguard Worker goto errout;
168*6a54128fSAndroid Build Coastguard Worker }
169*6a54128fSAndroid Build Coastguard Worker left = fs->inode_blocks_per_group;
170*6a54128fSAndroid Build Coastguard Worker while (left) {
171*6a54128fSAndroid Build Coastguard Worker c = BUF_BLOCKS;
172*6a54128fSAndroid Build Coastguard Worker if (c > left)
173*6a54128fSAndroid Build Coastguard Worker c = left;
174*6a54128fSAndroid Build Coastguard Worker actual = read(fd, buf, fs->blocksize * c);
175*6a54128fSAndroid Build Coastguard Worker if (actual == -1) {
176*6a54128fSAndroid Build Coastguard Worker retval = errno;
177*6a54128fSAndroid Build Coastguard Worker goto errout;
178*6a54128fSAndroid Build Coastguard Worker }
179*6a54128fSAndroid Build Coastguard Worker if (actual != fs->blocksize * c) {
180*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_SHORT_READ;
181*6a54128fSAndroid Build Coastguard Worker goto errout;
182*6a54128fSAndroid Build Coastguard Worker }
183*6a54128fSAndroid Build Coastguard Worker retval = io_channel_write_blk64(fs->io, blk, c, buf);
184*6a54128fSAndroid Build Coastguard Worker if (retval)
185*6a54128fSAndroid Build Coastguard Worker goto errout;
186*6a54128fSAndroid Build Coastguard Worker
187*6a54128fSAndroid Build Coastguard Worker blk += c;
188*6a54128fSAndroid Build Coastguard Worker left -= c;
189*6a54128fSAndroid Build Coastguard Worker }
190*6a54128fSAndroid Build Coastguard Worker }
191*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_flush_icache(fs);
192*6a54128fSAndroid Build Coastguard Worker
193*6a54128fSAndroid Build Coastguard Worker errout:
194*6a54128fSAndroid Build Coastguard Worker free(buf);
195*6a54128fSAndroid Build Coastguard Worker return retval;
196*6a54128fSAndroid Build Coastguard Worker }
197*6a54128fSAndroid Build Coastguard Worker
198*6a54128fSAndroid Build Coastguard Worker /*
199*6a54128fSAndroid Build Coastguard Worker * Write out superblock and group descriptors
200*6a54128fSAndroid Build Coastguard Worker */
ext2fs_image_super_write(ext2_filsys fs,int fd,int flags EXT2FS_ATTR ((unused)))201*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
202*6a54128fSAndroid Build Coastguard Worker int flags EXT2FS_ATTR((unused)))
203*6a54128fSAndroid Build Coastguard Worker {
204*6a54128fSAndroid Build Coastguard Worker char *buf, *cp;
205*6a54128fSAndroid Build Coastguard Worker ssize_t actual;
206*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
207*6a54128fSAndroid Build Coastguard Worker #ifdef WORDS_BIGENDIAN
208*6a54128fSAndroid Build Coastguard Worker unsigned int groups_per_block;
209*6a54128fSAndroid Build Coastguard Worker struct ext2_group_desc *gdp;
210*6a54128fSAndroid Build Coastguard Worker int j;
211*6a54128fSAndroid Build Coastguard Worker #endif
212*6a54128fSAndroid Build Coastguard Worker
213*6a54128fSAndroid Build Coastguard Worker if (fs->group_desc == NULL)
214*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_NO_GDESC;
215*6a54128fSAndroid Build Coastguard Worker
216*6a54128fSAndroid Build Coastguard Worker buf = malloc(fs->blocksize);
217*6a54128fSAndroid Build Coastguard Worker if (!buf)
218*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
219*6a54128fSAndroid Build Coastguard Worker
220*6a54128fSAndroid Build Coastguard Worker /*
221*6a54128fSAndroid Build Coastguard Worker * Write out the superblock
222*6a54128fSAndroid Build Coastguard Worker */
223*6a54128fSAndroid Build Coastguard Worker memset(buf, 0, fs->blocksize);
224*6a54128fSAndroid Build Coastguard Worker #ifdef WORDS_BIGENDIAN
225*6a54128fSAndroid Build Coastguard Worker /*
226*6a54128fSAndroid Build Coastguard Worker * We're writing out superblock so let's convert
227*6a54128fSAndroid Build Coastguard Worker * it to little endian and then back if needed
228*6a54128fSAndroid Build Coastguard Worker */
229*6a54128fSAndroid Build Coastguard Worker ext2fs_swap_super(fs->super);
230*6a54128fSAndroid Build Coastguard Worker memcpy(buf, fs->super, SUPERBLOCK_SIZE);
231*6a54128fSAndroid Build Coastguard Worker ext2fs_swap_super(fs->super);
232*6a54128fSAndroid Build Coastguard Worker #else
233*6a54128fSAndroid Build Coastguard Worker memcpy(buf, fs->super, SUPERBLOCK_SIZE);
234*6a54128fSAndroid Build Coastguard Worker #endif
235*6a54128fSAndroid Build Coastguard Worker actual = write(fd, buf, fs->blocksize);
236*6a54128fSAndroid Build Coastguard Worker if (actual == -1) {
237*6a54128fSAndroid Build Coastguard Worker retval = errno;
238*6a54128fSAndroid Build Coastguard Worker goto errout;
239*6a54128fSAndroid Build Coastguard Worker }
240*6a54128fSAndroid Build Coastguard Worker if (actual != (ssize_t) fs->blocksize) {
241*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_SHORT_WRITE;
242*6a54128fSAndroid Build Coastguard Worker goto errout;
243*6a54128fSAndroid Build Coastguard Worker }
244*6a54128fSAndroid Build Coastguard Worker
245*6a54128fSAndroid Build Coastguard Worker /*
246*6a54128fSAndroid Build Coastguard Worker * Now write out the block group descriptors
247*6a54128fSAndroid Build Coastguard Worker */
248*6a54128fSAndroid Build Coastguard Worker
249*6a54128fSAndroid Build Coastguard Worker cp = (char *) fs->group_desc;
250*6a54128fSAndroid Build Coastguard Worker
251*6a54128fSAndroid Build Coastguard Worker #ifdef WORDS_BIGENDIAN
252*6a54128fSAndroid Build Coastguard Worker /*
253*6a54128fSAndroid Build Coastguard Worker * Convert group descriptors to little endian and back
254*6a54128fSAndroid Build Coastguard Worker * if needed
255*6a54128fSAndroid Build Coastguard Worker */
256*6a54128fSAndroid Build Coastguard Worker groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
257*6a54128fSAndroid Build Coastguard Worker for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
258*6a54128fSAndroid Build Coastguard Worker gdp = ext2fs_group_desc(fs, fs->group_desc, j);
259*6a54128fSAndroid Build Coastguard Worker if (gdp)
260*6a54128fSAndroid Build Coastguard Worker ext2fs_swap_group_desc2(fs, gdp);
261*6a54128fSAndroid Build Coastguard Worker }
262*6a54128fSAndroid Build Coastguard Worker #endif
263*6a54128fSAndroid Build Coastguard Worker
264*6a54128fSAndroid Build Coastguard Worker actual = write(fd, cp, (ssize_t)fs->blocksize * fs->desc_blocks);
265*6a54128fSAndroid Build Coastguard Worker
266*6a54128fSAndroid Build Coastguard Worker
267*6a54128fSAndroid Build Coastguard Worker #ifdef WORDS_BIGENDIAN
268*6a54128fSAndroid Build Coastguard Worker groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
269*6a54128fSAndroid Build Coastguard Worker for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
270*6a54128fSAndroid Build Coastguard Worker gdp = ext2fs_group_desc(fs, fs->group_desc, j);
271*6a54128fSAndroid Build Coastguard Worker if (gdp)
272*6a54128fSAndroid Build Coastguard Worker ext2fs_swap_group_desc2(fs, gdp);
273*6a54128fSAndroid Build Coastguard Worker }
274*6a54128fSAndroid Build Coastguard Worker #endif
275*6a54128fSAndroid Build Coastguard Worker
276*6a54128fSAndroid Build Coastguard Worker if (actual == -1) {
277*6a54128fSAndroid Build Coastguard Worker retval = errno;
278*6a54128fSAndroid Build Coastguard Worker goto errout;
279*6a54128fSAndroid Build Coastguard Worker }
280*6a54128fSAndroid Build Coastguard Worker if (actual != (ssize_t)(fs->blocksize * fs->desc_blocks)) {
281*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_SHORT_WRITE;
282*6a54128fSAndroid Build Coastguard Worker goto errout;
283*6a54128fSAndroid Build Coastguard Worker }
284*6a54128fSAndroid Build Coastguard Worker
285*6a54128fSAndroid Build Coastguard Worker retval = 0;
286*6a54128fSAndroid Build Coastguard Worker
287*6a54128fSAndroid Build Coastguard Worker errout:
288*6a54128fSAndroid Build Coastguard Worker free(buf);
289*6a54128fSAndroid Build Coastguard Worker return retval;
290*6a54128fSAndroid Build Coastguard Worker }
291*6a54128fSAndroid Build Coastguard Worker
292*6a54128fSAndroid Build Coastguard Worker /*
293*6a54128fSAndroid Build Coastguard Worker * Read the superblock and group descriptors and overwrite them.
294*6a54128fSAndroid Build Coastguard Worker */
ext2fs_image_super_read(ext2_filsys fs,int fd,int flags EXT2FS_ATTR ((unused)))295*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
296*6a54128fSAndroid Build Coastguard Worker int flags EXT2FS_ATTR((unused)))
297*6a54128fSAndroid Build Coastguard Worker {
298*6a54128fSAndroid Build Coastguard Worker char *buf;
299*6a54128fSAndroid Build Coastguard Worker ssize_t actual, size;
300*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
301*6a54128fSAndroid Build Coastguard Worker
302*6a54128fSAndroid Build Coastguard Worker size = (ssize_t)fs->blocksize * (fs->group_desc_count + 1);
303*6a54128fSAndroid Build Coastguard Worker buf = malloc(size);
304*6a54128fSAndroid Build Coastguard Worker if (!buf)
305*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
306*6a54128fSAndroid Build Coastguard Worker
307*6a54128fSAndroid Build Coastguard Worker /*
308*6a54128fSAndroid Build Coastguard Worker * Read it all in.
309*6a54128fSAndroid Build Coastguard Worker */
310*6a54128fSAndroid Build Coastguard Worker actual = read(fd, buf, size);
311*6a54128fSAndroid Build Coastguard Worker if (actual == -1) {
312*6a54128fSAndroid Build Coastguard Worker retval = errno;
313*6a54128fSAndroid Build Coastguard Worker goto errout;
314*6a54128fSAndroid Build Coastguard Worker }
315*6a54128fSAndroid Build Coastguard Worker if (actual != size) {
316*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_SHORT_READ;
317*6a54128fSAndroid Build Coastguard Worker goto errout;
318*6a54128fSAndroid Build Coastguard Worker }
319*6a54128fSAndroid Build Coastguard Worker
320*6a54128fSAndroid Build Coastguard Worker /*
321*6a54128fSAndroid Build Coastguard Worker * Now copy in the superblock and group descriptors
322*6a54128fSAndroid Build Coastguard Worker */
323*6a54128fSAndroid Build Coastguard Worker memcpy(fs->super, buf, SUPERBLOCK_SIZE);
324*6a54128fSAndroid Build Coastguard Worker
325*6a54128fSAndroid Build Coastguard Worker memcpy(fs->group_desc, buf + fs->blocksize,
326*6a54128fSAndroid Build Coastguard Worker (ssize_t)fs->blocksize * fs->group_desc_count);
327*6a54128fSAndroid Build Coastguard Worker
328*6a54128fSAndroid Build Coastguard Worker retval = 0;
329*6a54128fSAndroid Build Coastguard Worker
330*6a54128fSAndroid Build Coastguard Worker errout:
331*6a54128fSAndroid Build Coastguard Worker free(buf);
332*6a54128fSAndroid Build Coastguard Worker return retval;
333*6a54128fSAndroid Build Coastguard Worker }
334*6a54128fSAndroid Build Coastguard Worker
335*6a54128fSAndroid Build Coastguard Worker /*
336*6a54128fSAndroid Build Coastguard Worker * Write the block/inode bitmaps.
337*6a54128fSAndroid Build Coastguard Worker */
ext2fs_image_bitmap_write(ext2_filsys fs,int fd,int flags)338*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
339*6a54128fSAndroid Build Coastguard Worker {
340*6a54128fSAndroid Build Coastguard Worker ext2fs_generic_bitmap bmap;
341*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
342*6a54128fSAndroid Build Coastguard Worker ssize_t actual;
343*6a54128fSAndroid Build Coastguard Worker size_t c;
344*6a54128fSAndroid Build Coastguard Worker __u64 itr, cnt, size, total_size;
345*6a54128fSAndroid Build Coastguard Worker char buf[1024];
346*6a54128fSAndroid Build Coastguard Worker
347*6a54128fSAndroid Build Coastguard Worker if (flags & IMAGER_FLAG_INODEMAP) {
348*6a54128fSAndroid Build Coastguard Worker if (!fs->inode_map) {
349*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_read_inode_bitmap(fs);
350*6a54128fSAndroid Build Coastguard Worker if (retval)
351*6a54128fSAndroid Build Coastguard Worker return retval;
352*6a54128fSAndroid Build Coastguard Worker }
353*6a54128fSAndroid Build Coastguard Worker bmap = fs->inode_map;
354*6a54128fSAndroid Build Coastguard Worker itr = 1;
355*6a54128fSAndroid Build Coastguard Worker cnt = (__u64)EXT2_INODES_PER_GROUP(fs->super) *
356*6a54128fSAndroid Build Coastguard Worker fs->group_desc_count;
357*6a54128fSAndroid Build Coastguard Worker size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
358*6a54128fSAndroid Build Coastguard Worker } else {
359*6a54128fSAndroid Build Coastguard Worker if (!fs->block_map) {
360*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_read_block_bitmap(fs);
361*6a54128fSAndroid Build Coastguard Worker if (retval)
362*6a54128fSAndroid Build Coastguard Worker return retval;
363*6a54128fSAndroid Build Coastguard Worker }
364*6a54128fSAndroid Build Coastguard Worker bmap = fs->block_map;
365*6a54128fSAndroid Build Coastguard Worker itr = fs->super->s_first_data_block;
366*6a54128fSAndroid Build Coastguard Worker cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count);
367*6a54128fSAndroid Build Coastguard Worker size = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
368*6a54128fSAndroid Build Coastguard Worker }
369*6a54128fSAndroid Build Coastguard Worker total_size = size * fs->group_desc_count;
370*6a54128fSAndroid Build Coastguard Worker
371*6a54128fSAndroid Build Coastguard Worker while (cnt > 0) {
372*6a54128fSAndroid Build Coastguard Worker size = sizeof(buf);
373*6a54128fSAndroid Build Coastguard Worker if (size > (cnt >> 3))
374*6a54128fSAndroid Build Coastguard Worker size = (cnt >> 3);
375*6a54128fSAndroid Build Coastguard Worker if (size == 0)
376*6a54128fSAndroid Build Coastguard Worker break;
377*6a54128fSAndroid Build Coastguard Worker
378*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_generic_bmap_range(bmap, itr,
379*6a54128fSAndroid Build Coastguard Worker size << 3, buf);
380*6a54128fSAndroid Build Coastguard Worker if (retval)
381*6a54128fSAndroid Build Coastguard Worker return retval;
382*6a54128fSAndroid Build Coastguard Worker
383*6a54128fSAndroid Build Coastguard Worker actual = write(fd, buf, size);
384*6a54128fSAndroid Build Coastguard Worker if (actual == -1)
385*6a54128fSAndroid Build Coastguard Worker return errno;
386*6a54128fSAndroid Build Coastguard Worker if (actual != (int) size)
387*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_SHORT_READ;
388*6a54128fSAndroid Build Coastguard Worker
389*6a54128fSAndroid Build Coastguard Worker itr += size << 3;
390*6a54128fSAndroid Build Coastguard Worker cnt -= size << 3;
391*6a54128fSAndroid Build Coastguard Worker }
392*6a54128fSAndroid Build Coastguard Worker
393*6a54128fSAndroid Build Coastguard Worker size = total_size % fs->blocksize;
394*6a54128fSAndroid Build Coastguard Worker memset(buf, 0, sizeof(buf));
395*6a54128fSAndroid Build Coastguard Worker if (size) {
396*6a54128fSAndroid Build Coastguard Worker size = fs->blocksize - size;
397*6a54128fSAndroid Build Coastguard Worker while (size) {
398*6a54128fSAndroid Build Coastguard Worker c = size;
399*6a54128fSAndroid Build Coastguard Worker if (c > (int) sizeof(buf))
400*6a54128fSAndroid Build Coastguard Worker c = sizeof(buf);
401*6a54128fSAndroid Build Coastguard Worker actual = write(fd, buf, c);
402*6a54128fSAndroid Build Coastguard Worker if (actual < 0)
403*6a54128fSAndroid Build Coastguard Worker return errno;
404*6a54128fSAndroid Build Coastguard Worker if ((size_t) actual != c)
405*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_SHORT_WRITE;
406*6a54128fSAndroid Build Coastguard Worker size -= c;
407*6a54128fSAndroid Build Coastguard Worker }
408*6a54128fSAndroid Build Coastguard Worker }
409*6a54128fSAndroid Build Coastguard Worker return 0;
410*6a54128fSAndroid Build Coastguard Worker }
411*6a54128fSAndroid Build Coastguard Worker
412*6a54128fSAndroid Build Coastguard Worker
413*6a54128fSAndroid Build Coastguard Worker /*
414*6a54128fSAndroid Build Coastguard Worker * Read the block/inode bitmaps.
415*6a54128fSAndroid Build Coastguard Worker */
ext2fs_image_bitmap_read(ext2_filsys fs,int fd,int flags)416*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
417*6a54128fSAndroid Build Coastguard Worker {
418*6a54128fSAndroid Build Coastguard Worker ext2fs_generic_bitmap bmap;
419*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
420*6a54128fSAndroid Build Coastguard Worker __u64 itr, cnt;
421*6a54128fSAndroid Build Coastguard Worker char buf[1024];
422*6a54128fSAndroid Build Coastguard Worker unsigned int size;
423*6a54128fSAndroid Build Coastguard Worker ssize_t actual;
424*6a54128fSAndroid Build Coastguard Worker
425*6a54128fSAndroid Build Coastguard Worker if (flags & IMAGER_FLAG_INODEMAP) {
426*6a54128fSAndroid Build Coastguard Worker if (!fs->inode_map) {
427*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_read_inode_bitmap(fs);
428*6a54128fSAndroid Build Coastguard Worker if (retval)
429*6a54128fSAndroid Build Coastguard Worker return retval;
430*6a54128fSAndroid Build Coastguard Worker }
431*6a54128fSAndroid Build Coastguard Worker bmap = fs->inode_map;
432*6a54128fSAndroid Build Coastguard Worker itr = 1;
433*6a54128fSAndroid Build Coastguard Worker cnt = (__u64)EXT2_INODES_PER_GROUP(fs->super) *
434*6a54128fSAndroid Build Coastguard Worker fs->group_desc_count;
435*6a54128fSAndroid Build Coastguard Worker size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
436*6a54128fSAndroid Build Coastguard Worker } else {
437*6a54128fSAndroid Build Coastguard Worker if (!fs->block_map) {
438*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_read_block_bitmap(fs);
439*6a54128fSAndroid Build Coastguard Worker if (retval)
440*6a54128fSAndroid Build Coastguard Worker return retval;
441*6a54128fSAndroid Build Coastguard Worker }
442*6a54128fSAndroid Build Coastguard Worker bmap = fs->block_map;
443*6a54128fSAndroid Build Coastguard Worker itr = fs->super->s_first_data_block;
444*6a54128fSAndroid Build Coastguard Worker cnt = EXT2_GROUPS_TO_BLOCKS(fs->super, fs->group_desc_count);
445*6a54128fSAndroid Build Coastguard Worker size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
446*6a54128fSAndroid Build Coastguard Worker }
447*6a54128fSAndroid Build Coastguard Worker
448*6a54128fSAndroid Build Coastguard Worker while (cnt > 0) {
449*6a54128fSAndroid Build Coastguard Worker size = sizeof(buf);
450*6a54128fSAndroid Build Coastguard Worker if (size > (cnt >> 3))
451*6a54128fSAndroid Build Coastguard Worker size = (cnt >> 3);
452*6a54128fSAndroid Build Coastguard Worker if (size == 0)
453*6a54128fSAndroid Build Coastguard Worker break;
454*6a54128fSAndroid Build Coastguard Worker
455*6a54128fSAndroid Build Coastguard Worker actual = read(fd, buf, size);
456*6a54128fSAndroid Build Coastguard Worker if (actual == -1)
457*6a54128fSAndroid Build Coastguard Worker return errno;
458*6a54128fSAndroid Build Coastguard Worker if (actual != (int) size)
459*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_SHORT_READ;
460*6a54128fSAndroid Build Coastguard Worker
461*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_set_generic_bmap_range(bmap, itr,
462*6a54128fSAndroid Build Coastguard Worker size << 3, buf);
463*6a54128fSAndroid Build Coastguard Worker if (retval)
464*6a54128fSAndroid Build Coastguard Worker return retval;
465*6a54128fSAndroid Build Coastguard Worker
466*6a54128fSAndroid Build Coastguard Worker itr += size << 3;
467*6a54128fSAndroid Build Coastguard Worker cnt -= size << 3;
468*6a54128fSAndroid Build Coastguard Worker }
469*6a54128fSAndroid Build Coastguard Worker return 0;
470*6a54128fSAndroid Build Coastguard Worker }
471