2 * image.c --- writes out the critical parts of the filesystem as a
5 * Copyright (C) 2000 Theodore Ts'o.
7 * Note: this uses the POSIX IO interfaces, unlike most of the other
8 * functions in this library. So sue me.
11 * This file may be redistributed under the terms of the GNU Library
12 * General Public License, version 2.
31 #include <sys/types.h>
37 #ifndef HAVE_TYPE_SSIZE_T
42 * This function returns 1 if the specified block is all zeros
44 static int check_zero_block(char *buf
, int blocksize
)
58 * Write the inode table out as a single block.
62 errcode_t
ext2fs_image_inode_write(ext2_filsys fs
, int fd
, int flags
)
64 unsigned int group
, left
, c
, d
;
71 buf
= malloc(fs
->blocksize
* BUF_BLOCKS
);
75 for (group
= 0; group
< fs
->group_desc_count
; group
++) {
76 blk
= ext2fs_inode_table_loc(fs
, (unsigned)group
);
78 retval
= EXT2_ET_MISSING_INODE_TABLE
;
81 left
= fs
->inode_blocks_per_group
;
86 retval
= io_channel_read_blk64(fs
->io
, blk
, c
, buf
);
91 if (!(flags
& IMAGER_FLAG_SPARSEWRITE
)) {
95 /* Skip zero blocks */
96 if (check_zero_block(cp
, fs
->blocksize
)) {
101 r
= lseek(fd
, fs
->blocksize
, SEEK_CUR
);
108 /* Find non-zero blocks */
109 for (d
=1; d
< c
; d
++) {
110 if (check_zero_block(cp
+ d
*fs
->blocksize
, fs
->blocksize
))
114 actual
= write(fd
, cp
, fs
->blocksize
* d
);
119 if (actual
!= (ssize_t
) (fs
->blocksize
* d
)) {
120 retval
= EXT2_ET_SHORT_WRITE
;
125 cp
+= fs
->blocksize
* d
;
138 * Read in the inode table and stuff it into place
140 errcode_t
ext2fs_image_inode_read(ext2_filsys fs
, int fd
,
141 int flags
EXT2FS_ATTR((unused
)))
143 unsigned int group
, c
, left
;
149 buf
= malloc(fs
->blocksize
* BUF_BLOCKS
);
153 for (group
= 0; group
< fs
->group_desc_count
; group
++) {
154 blk
= ext2fs_inode_table_loc(fs
, (unsigned)group
);
156 retval
= EXT2_ET_MISSING_INODE_TABLE
;
159 left
= fs
->inode_blocks_per_group
;
164 actual
= read(fd
, buf
, fs
->blocksize
* c
);
169 if (actual
!= (ssize_t
) (fs
->blocksize
* c
)) {
170 retval
= EXT2_ET_SHORT_READ
;
173 retval
= io_channel_write_blk64(fs
->io
, blk
, c
, buf
);
181 retval
= ext2fs_flush_icache(fs
);
189 * Write out superblock and group descriptors
191 errcode_t
ext2fs_image_super_write(ext2_filsys fs
, int fd
,
192 int flags
EXT2FS_ATTR((unused
)))
198 buf
= malloc(fs
->blocksize
);
203 * Write out the superblock
205 memset(buf
, 0, fs
->blocksize
);
206 memcpy(buf
, fs
->super
, SUPERBLOCK_SIZE
);
207 actual
= write(fd
, buf
, fs
->blocksize
);
212 if (actual
!= (ssize_t
) fs
->blocksize
) {
213 retval
= EXT2_ET_SHORT_WRITE
;
218 * Now write out the block group descriptors
220 cp
= (char *) fs
->group_desc
;
221 actual
= write(fd
, cp
, fs
->blocksize
* fs
->desc_blocks
);
226 if (actual
!= (ssize_t
) (fs
->blocksize
* fs
->desc_blocks
)) {
227 retval
= EXT2_ET_SHORT_WRITE
;
239 * Read the superblock and group descriptors and overwrite them.
241 errcode_t
ext2fs_image_super_read(ext2_filsys fs
, int fd
,
242 int flags
EXT2FS_ATTR((unused
)))
245 ssize_t actual
, size
;
248 size
= fs
->blocksize
* (fs
->group_desc_count
+ 1);
256 actual
= read(fd
, buf
, size
);
261 if (actual
!= size
) {
262 retval
= EXT2_ET_SHORT_READ
;
267 * Now copy in the superblock and group descriptors
269 memcpy(fs
->super
, buf
, SUPERBLOCK_SIZE
);
271 memcpy(fs
->group_desc
, buf
+ fs
->blocksize
,
272 fs
->blocksize
* fs
->group_desc_count
);
282 * Write the block/inode bitmaps.
284 errcode_t
ext2fs_image_bitmap_write(ext2_filsys fs
, int fd
, int flags
)
286 ext2fs_generic_bitmap bmap
;
289 __u32 itr
, cnt
, size
;
293 if (flags
& IMAGER_FLAG_INODEMAP
) {
294 if (!fs
->inode_map
) {
295 retval
= ext2fs_read_inode_bitmap(fs
);
299 bmap
= fs
->inode_map
;
301 cnt
= EXT2_INODES_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
302 size
= (EXT2_INODES_PER_GROUP(fs
->super
) / 8);
304 if (!fs
->block_map
) {
305 retval
= ext2fs_read_block_bitmap(fs
);
309 bmap
= fs
->block_map
;
310 itr
= fs
->super
->s_first_data_block
;
311 cnt
= EXT2_BLOCKS_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
312 size
= EXT2_BLOCKS_PER_GROUP(fs
->super
) / 8;
314 total_size
= size
* fs
->group_desc_count
;
318 if (size
> (cnt
>> 3))
321 retval
= ext2fs_get_generic_bmap_range(bmap
, itr
,
326 actual
= write(fd
, buf
, size
);
329 if (actual
!= (int) size
)
330 return EXT2_ET_SHORT_READ
;
336 size
= total_size
% fs
->blocksize
;
337 memset(buf
, 0, sizeof(buf
));
339 size
= fs
->blocksize
- size
;
342 if (c
> (int) sizeof(buf
))
344 actual
= write(fd
, buf
, c
);
348 return EXT2_ET_SHORT_WRITE
;
357 * Read the block/inode bitmaps.
359 errcode_t
ext2fs_image_bitmap_read(ext2_filsys fs
, int fd
, int flags
)
361 ext2fs_generic_bitmap bmap
;
368 if (flags
& IMAGER_FLAG_INODEMAP
) {
369 if (!fs
->inode_map
) {
370 retval
= ext2fs_read_inode_bitmap(fs
);
374 bmap
= fs
->inode_map
;
376 cnt
= EXT2_INODES_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
377 size
= (EXT2_INODES_PER_GROUP(fs
->super
) / 8);
379 if (!fs
->block_map
) {
380 retval
= ext2fs_read_block_bitmap(fs
);
384 bmap
= fs
->block_map
;
385 itr
= fs
->super
->s_first_data_block
;
386 cnt
= EXT2_BLOCKS_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
387 size
= EXT2_BLOCKS_PER_GROUP(fs
->super
) / 8;
392 if (size
> (cnt
>> 3))
395 actual
= read(fd
, buf
, size
);
398 if (actual
!= (int) size
)
399 return EXT2_ET_SHORT_READ
;
401 retval
= ext2fs_set_generic_bmap_range(bmap
, itr
,