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;
70 buf = malloc(fs->blocksize * BUF_BLOCKS);
74 for (group = 0; group < fs->group_desc_count; group++) {
75 blk = ext2fs_inode_table_loc(fs, (unsigned)group);
77 retval = EXT2_ET_MISSING_INODE_TABLE;
80 left = fs->inode_blocks_per_group;
85 retval = io_channel_read_blk64(fs->io, blk, c, buf);
90 if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
94 /* Skip zero blocks */
95 if (check_zero_block(cp, fs->blocksize)) {
100 lseek(fd, fs->blocksize, SEEK_CUR);
103 /* Find non-zero blocks */
104 for (d=1; d < c; d++) {
105 if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
109 actual = write(fd, cp, fs->blocksize * d);
114 if (actual != (ssize_t) (fs->blocksize * d)) {
115 retval = EXT2_ET_SHORT_WRITE;
120 cp += fs->blocksize * d;
133 * Read in the inode table and stuff it into place
135 errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
136 int flags EXT2FS_ATTR((unused)))
138 unsigned int group, c, left;
144 buf = malloc(fs->blocksize * BUF_BLOCKS);
148 for (group = 0; group < fs->group_desc_count; group++) {
149 blk = ext2fs_inode_table_loc(fs, (unsigned)group);
151 retval = EXT2_ET_MISSING_INODE_TABLE;
154 left = fs->inode_blocks_per_group;
159 actual = read(fd, buf, fs->blocksize * c);
164 if (actual != (ssize_t) (fs->blocksize * c)) {
165 retval = EXT2_ET_SHORT_READ;
168 retval = io_channel_write_blk64(fs->io, blk, c, buf);
176 retval = ext2fs_flush_icache(fs);
184 * Write out superblock and group descriptors
186 errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
187 int flags EXT2FS_ATTR((unused)))
193 buf = malloc(fs->blocksize);
198 * Write out the superblock
200 memset(buf, 0, fs->blocksize);
201 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
202 actual = write(fd, buf, fs->blocksize);
207 if (actual != (ssize_t) fs->blocksize) {
208 retval = EXT2_ET_SHORT_WRITE;
213 * Now write out the block group descriptors
215 cp = (char *) fs->group_desc;
216 actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
221 if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
222 retval = EXT2_ET_SHORT_WRITE;
234 * Read the superblock and group descriptors and overwrite them.
236 errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
237 int flags EXT2FS_ATTR((unused)))
240 ssize_t actual, size;
243 size = fs->blocksize * (fs->group_desc_count + 1);
251 actual = read(fd, buf, size);
256 if (actual != size) {
257 retval = EXT2_ET_SHORT_READ;
262 * Now copy in the superblock and group descriptors
264 memcpy(fs->super, buf, SUPERBLOCK_SIZE);
266 memcpy(fs->group_desc, buf + fs->blocksize,
267 fs->blocksize * fs->group_desc_count);
277 * Write the block/inode bitmaps.
279 errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
281 ext2fs_generic_bitmap bmap;
284 __u32 itr, cnt, size;
288 if (flags & IMAGER_FLAG_INODEMAP) {
289 if (!fs->inode_map) {
290 retval = ext2fs_read_inode_bitmap(fs);
294 bmap = fs->inode_map;
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 itr = fs->super->s_first_data_block;
306 cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
307 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
309 total_size = size * fs->group_desc_count;
313 if (size > (cnt >> 3))
316 retval = ext2fs_get_generic_bmap_range(bmap, itr,
321 actual = write(fd, buf, size);
324 if (actual != (int) size)
325 return EXT2_ET_SHORT_READ;
331 size = total_size % fs->blocksize;
332 memset(buf, 0, sizeof(buf));
334 size = fs->blocksize - size;
337 if (c > (int) sizeof(buf))
339 actual = write(fd, buf, c);
343 return EXT2_ET_SHORT_WRITE;
352 * Read the block/inode bitmaps.
354 errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
356 ext2fs_generic_bitmap bmap;
363 if (flags & IMAGER_FLAG_INODEMAP) {
364 if (!fs->inode_map) {
365 retval = ext2fs_read_inode_bitmap(fs);
369 bmap = fs->inode_map;
371 cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
372 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
374 if (!fs->block_map) {
375 retval = ext2fs_read_block_bitmap(fs);
379 bmap = fs->block_map;
380 itr = fs->super->s_first_data_block;
381 cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
382 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
387 if (size > (cnt >> 3))
390 actual = read(fd, buf, size);
393 if (actual != (int) size)
394 return EXT2_ET_SHORT_READ;
396 retval = ext2fs_set_generic_bmap_range(bmap, itr,