1 /* vi: set sw=4 ts=4: */
3 * image.c --- writes out the critical parts of the filesystem as a
6 * Copyright (C) 2000 Theodore Ts'o.
8 * Note: this uses the POSIX IO interfaces, unlike most of the other
9 * functions in this library. So sue me.
12 * This file may be redistributed under the terms of the GNU Public
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
;
70 buf
= xmalloc(fs
->blocksize
* BUF_BLOCKS
);
72 for (group
= 0; group
< fs
->group_desc_count
; group
++) {
73 blk
= fs
->group_desc
[(unsigned)group
].bg_inode_table
;
75 return EXT2_ET_MISSING_INODE_TABLE
;
76 left
= fs
->inode_blocks_per_group
;
81 retval
= io_channel_read_blk(fs
->io
, blk
, c
, buf
);
86 if (!(flags
& IMAGER_FLAG_SPARSEWRITE
)) {
90 /* Skip zero blocks */
91 if (check_zero_block(cp
, fs
->blocksize
)) {
96 lseek(fd
, fs
->blocksize
, SEEK_CUR
);
99 /* Find non-zero blocks */
100 for (d
=1; d
< c
; d
++) {
101 if (check_zero_block(cp
+ d
*fs
->blocksize
, fs
->blocksize
))
105 actual
= write(fd
, cp
, fs
->blocksize
* d
);
110 if (actual
!= (ssize_t
) (fs
->blocksize
* d
)) {
111 retval
= EXT2_ET_SHORT_WRITE
;
116 cp
+= fs
->blocksize
* d
;
129 * Read in the inode table and stuff it into place
131 errcode_t
ext2fs_image_inode_read(ext2_filsys fs
, int fd
,
132 int flags
EXT2FS_ATTR((unused
)))
134 unsigned int group
, c
, left
;
140 buf
= xmalloc(fs
->blocksize
* BUF_BLOCKS
);
142 for (group
= 0; group
< fs
->group_desc_count
; group
++) {
143 blk
= fs
->group_desc
[(unsigned)group
].bg_inode_table
;
145 retval
= EXT2_ET_MISSING_INODE_TABLE
;
148 left
= fs
->inode_blocks_per_group
;
153 actual
= read(fd
, buf
, fs
->blocksize
* c
);
158 if (actual
!= (ssize_t
) (fs
->blocksize
* c
)) {
159 retval
= EXT2_ET_SHORT_READ
;
162 retval
= io_channel_write_blk(fs
->io
, blk
, c
, buf
);
170 retval
= ext2fs_flush_icache(fs
);
178 * Write out superblock and group descriptors
180 errcode_t
ext2fs_image_super_write(ext2_filsys fs
, int fd
,
181 int flags
EXT2FS_ATTR((unused
)))
187 buf
= xmalloc(fs
->blocksize
);
190 * Write out the superblock
192 memset(buf
, 0, fs
->blocksize
);
193 memcpy(buf
, fs
->super
, SUPERBLOCK_SIZE
);
194 actual
= write(fd
, buf
, fs
->blocksize
);
199 if (actual
!= (ssize_t
) fs
->blocksize
) {
200 retval
= EXT2_ET_SHORT_WRITE
;
205 * Now write out the block group descriptors
207 cp
= (char *) fs
->group_desc
;
208 actual
= write(fd
, cp
, fs
->blocksize
* fs
->desc_blocks
);
213 if (actual
!= (ssize_t
) (fs
->blocksize
* fs
->desc_blocks
)) {
214 retval
= EXT2_ET_SHORT_WRITE
;
226 * Read the superblock and group descriptors and overwrite them.
228 errcode_t
ext2fs_image_super_read(ext2_filsys fs
, int fd
,
229 int flags
EXT2FS_ATTR((unused
)))
232 ssize_t actual
, size
;
235 size
= fs
->blocksize
* (fs
->group_desc_count
+ 1);
241 actual
= read(fd
, buf
, size
);
246 if (actual
!= size
) {
247 retval
= EXT2_ET_SHORT_READ
;
252 * Now copy in the superblock and group descriptors
254 memcpy(fs
->super
, buf
, SUPERBLOCK_SIZE
);
256 memcpy(fs
->group_desc
, buf
+ fs
->blocksize
,
257 fs
->blocksize
* fs
->group_desc_count
);
267 * Write the block/inode bitmaps.
269 errcode_t
ext2fs_image_bitmap_write(ext2_filsys fs
, int fd
, int flags
)
277 if (flags
& IMAGER_FLAG_INODEMAP
) {
278 if (!fs
->inode_map
) {
279 retval
= ext2fs_read_inode_bitmap(fs
);
283 ptr
= fs
->inode_map
->bitmap
;
284 size
= (EXT2_INODES_PER_GROUP(fs
->super
) / 8);
286 if (!fs
->block_map
) {
287 retval
= ext2fs_read_block_bitmap(fs
);
291 ptr
= fs
->block_map
->bitmap
;
292 size
= EXT2_BLOCKS_PER_GROUP(fs
->super
) / 8;
294 size
= size
* fs
->group_desc_count
;
296 actual
= write(fd
, ptr
, size
);
301 if (actual
!= size
) {
302 retval
= EXT2_ET_SHORT_WRITE
;
305 size
= size
% fs
->blocksize
;
306 memset(zero_buf
, 0, sizeof(zero_buf
));
308 size
= fs
->blocksize
- size
;
311 if (c
> (int) sizeof(zero_buf
))
312 c
= sizeof(zero_buf
);
313 actual
= write(fd
, zero_buf
, c
);
319 retval
= EXT2_ET_SHORT_WRITE
;
332 * Read the block/inode bitmaps.
334 errcode_t
ext2fs_image_bitmap_read(ext2_filsys fs
, int fd
, int flags
)
336 char *ptr
, *buf
= NULL
;
341 if (flags
& IMAGER_FLAG_INODEMAP
) {
342 if (!fs
->inode_map
) {
343 retval
= ext2fs_read_inode_bitmap(fs
);
347 ptr
= fs
->inode_map
->bitmap
;
348 size
= (EXT2_INODES_PER_GROUP(fs
->super
) / 8);
350 if (!fs
->block_map
) {
351 retval
= ext2fs_read_block_bitmap(fs
);
355 ptr
= fs
->block_map
->bitmap
;
356 size
= EXT2_BLOCKS_PER_GROUP(fs
->super
) / 8;
358 size
= size
* fs
->group_desc_count
;
362 actual
= read(fd
, buf
, size
);
367 if (actual
!= size
) {
368 retval
= EXT2_ET_SHORT_WRITE
;
371 memcpy(ptr
, buf
, size
);