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.
30 #include <sys/types.h>
36 #ifndef HAVE_TYPE_SSIZE_T
41 * This function returns 1 if the specified block is all zeros
43 static int check_zero_block(char *buf
, int blocksize
)
57 * Write the inode table out as a single block.
61 errcode_t
ext2fs_image_inode_write(ext2_filsys fs
, int fd
, int flags
)
63 unsigned int group
, left
, c
, d
;
69 buf
= malloc(fs
->blocksize
* BUF_BLOCKS
);
73 for (group
= 0; group
< fs
->group_desc_count
; group
++) {
74 blk
= ext2fs_inode_table_loc(fs
, (unsigned)group
);
76 retval
= EXT2_ET_MISSING_INODE_TABLE
;
79 left
= fs
->inode_blocks_per_group
;
84 retval
= io_channel_read_blk64(fs
->io
, blk
, c
, buf
);
89 if (!(flags
& IMAGER_FLAG_SPARSEWRITE
)) {
93 /* Skip zero blocks */
94 if (check_zero_block(cp
, fs
->blocksize
)) {
99 lseek(fd
, fs
->blocksize
, SEEK_CUR
);
102 /* Find non-zero blocks */
103 for (d
=1; d
< c
; d
++) {
104 if (check_zero_block(cp
+ d
*fs
->blocksize
, fs
->blocksize
))
108 actual
= write(fd
, cp
, fs
->blocksize
* d
);
113 if (actual
!= (ssize_t
) (fs
->blocksize
* d
)) {
114 retval
= EXT2_ET_SHORT_WRITE
;
119 cp
+= fs
->blocksize
* d
;
132 * Read in the inode table and stuff it into place
134 errcode_t
ext2fs_image_inode_read(ext2_filsys fs
, int fd
,
135 int flags
EXT2FS_ATTR((unused
)))
137 unsigned int group
, c
, left
;
143 buf
= malloc(fs
->blocksize
* BUF_BLOCKS
);
147 for (group
= 0; group
< fs
->group_desc_count
; group
++) {
148 blk
= ext2fs_inode_table_loc(fs
, (unsigned)group
);
150 retval
= EXT2_ET_MISSING_INODE_TABLE
;
153 left
= fs
->inode_blocks_per_group
;
158 actual
= read(fd
, buf
, fs
->blocksize
* c
);
163 if (actual
!= (ssize_t
) (fs
->blocksize
* c
)) {
164 retval
= EXT2_ET_SHORT_READ
;
167 retval
= io_channel_write_blk64(fs
->io
, blk
, c
, buf
);
175 retval
= ext2fs_flush_icache(fs
);
183 * Write out superblock and group descriptors
185 errcode_t
ext2fs_image_super_write(ext2_filsys fs
, int fd
,
186 int flags
EXT2FS_ATTR((unused
)))
192 buf
= malloc(fs
->blocksize
);
197 * Write out the superblock
199 memset(buf
, 0, fs
->blocksize
);
200 memcpy(buf
, fs
->super
, SUPERBLOCK_SIZE
);
201 actual
= write(fd
, buf
, fs
->blocksize
);
206 if (actual
!= (ssize_t
) fs
->blocksize
) {
207 retval
= EXT2_ET_SHORT_WRITE
;
212 * Now write out the block group descriptors
214 cp
= (char *) fs
->group_desc
;
215 actual
= write(fd
, cp
, fs
->blocksize
* fs
->desc_blocks
);
220 if (actual
!= (ssize_t
) (fs
->blocksize
* fs
->desc_blocks
)) {
221 retval
= EXT2_ET_SHORT_WRITE
;
233 * Read the superblock and group descriptors and overwrite them.
235 errcode_t
ext2fs_image_super_read(ext2_filsys fs
, int fd
,
236 int flags
EXT2FS_ATTR((unused
)))
239 ssize_t actual
, size
;
242 size
= fs
->blocksize
* (fs
->group_desc_count
+ 1);
250 actual
= read(fd
, buf
, size
);
255 if (actual
!= size
) {
256 retval
= EXT2_ET_SHORT_READ
;
261 * Now copy in the superblock and group descriptors
263 memcpy(fs
->super
, buf
, SUPERBLOCK_SIZE
);
265 memcpy(fs
->group_desc
, buf
+ fs
->blocksize
,
266 fs
->blocksize
* fs
->group_desc_count
);
276 * Write the block/inode bitmaps.
278 errcode_t
ext2fs_image_bitmap_write(ext2_filsys fs
, int fd
, int flags
)
280 ext2fs_generic_bitmap bmap
;
281 errcode_t err
, retval
;
283 __u32 itr
, cnt
, size
;
287 if (flags
& IMAGER_FLAG_INODEMAP
) {
288 if (!fs
->inode_map
) {
289 retval
= ext2fs_read_inode_bitmap(fs
);
293 bmap
= fs
->inode_map
;
294 err
= EXT2_ET_MAGIC_INODE_BITMAP
;
296 cnt
= EXT2_INODES_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
297 size
= (EXT2_INODES_PER_GROUP(fs
->super
) / 8);
299 if (!fs
->block_map
) {
300 retval
= ext2fs_read_block_bitmap(fs
);
304 bmap
= fs
->block_map
;
305 err
= EXT2_ET_MAGIC_BLOCK_BITMAP
;
306 itr
= fs
->super
->s_first_data_block
;
307 cnt
= EXT2_BLOCKS_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
308 size
= EXT2_BLOCKS_PER_GROUP(fs
->super
) / 8;
310 total_size
= size
* fs
->group_desc_count
;
314 if (size
> (cnt
>> 3))
317 retval
= ext2fs_get_generic_bmap_range(bmap
, itr
,
322 actual
= write(fd
, buf
, size
);
325 if (actual
!= (int) size
)
326 return EXT2_ET_SHORT_READ
;
332 size
= total_size
% fs
->blocksize
;
333 memset(buf
, 0, sizeof(buf
));
335 size
= fs
->blocksize
- size
;
338 if (c
> (int) sizeof(buf
))
340 actual
= write(fd
, buf
, c
);
344 return EXT2_ET_SHORT_WRITE
;
353 * Read the block/inode bitmaps.
355 errcode_t
ext2fs_image_bitmap_read(ext2_filsys fs
, int fd
, int flags
)
357 ext2fs_generic_bitmap bmap
;
358 errcode_t err
, retval
;
364 if (flags
& IMAGER_FLAG_INODEMAP
) {
365 if (!fs
->inode_map
) {
366 retval
= ext2fs_read_inode_bitmap(fs
);
370 bmap
= fs
->inode_map
;
371 err
= EXT2_ET_MAGIC_INODE_BITMAP
;
373 cnt
= EXT2_INODES_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
374 size
= (EXT2_INODES_PER_GROUP(fs
->super
) / 8);
376 if (!fs
->block_map
) {
377 retval
= ext2fs_read_block_bitmap(fs
);
381 bmap
= fs
->block_map
;
382 err
= EXT2_ET_MAGIC_BLOCK_BITMAP
;
383 itr
= fs
->super
->s_first_data_block
;
384 cnt
= EXT2_BLOCKS_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
385 size
= EXT2_BLOCKS_PER_GROUP(fs
->super
) / 8;
390 if (size
> (cnt
>> 3))
393 actual
= read(fd
, buf
, size
);
396 if (actual
!= (int) size
)
397 return EXT2_ET_SHORT_READ
;
399 retval
= ext2fs_set_generic_bmap_range(bmap
, itr
,