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 Public
30 #include <sys/types.h>
33 #if EXT2_FLAT_INCLUDES
36 #include <linux/ext2_fs.h>
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 = fs->group_desc[(unsigned)group].bg_inode_table;
77 return EXT2_ET_MISSING_INODE_TABLE;
78 left = fs->inode_blocks_per_group;
83 retval = io_channel_read_blk(fs->io, blk, c, buf);
88 if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
92 /* Skip zero blocks */
93 if (check_zero_block(cp, fs->blocksize)) {
98 lseek(fd, fs->blocksize, SEEK_CUR);
101 /* Find non-zero blocks */
102 for (d=1; d < c; d++) {
103 if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
107 actual = write(fd, cp, fs->blocksize * d);
112 if (actual != fs->blocksize * d) {
113 retval = EXT2_ET_SHORT_WRITE;
118 cp += fs->blocksize * d;
131 * Read in the inode table and stuff it into place
133 errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags)
135 unsigned int group, c, left;
141 buf = malloc(fs->blocksize * BUF_BLOCKS);
145 for (group = 0; group < fs->group_desc_count; group++) {
146 blk = fs->group_desc[(unsigned)group].bg_inode_table;
148 retval = EXT2_ET_MISSING_INODE_TABLE;
151 left = fs->inode_blocks_per_group;
156 actual = read(fd, buf, fs->blocksize * c);
161 if (actual != fs->blocksize * c) {
162 retval = EXT2_ET_SHORT_READ;
165 retval = io_channel_write_blk(fs->io, blk, c, buf);
173 retval = ext2fs_flush_icache(fs);
181 * Write out superblock and group descriptors
183 errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags)
189 buf = malloc(fs->blocksize);
194 * Write out the superblock
196 memset(buf, 0, fs->blocksize);
197 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
198 actual = write(fd, buf, fs->blocksize);
203 if (actual != fs->blocksize) {
204 retval = EXT2_ET_SHORT_WRITE;
209 * Now write out the block group descriptors
211 cp = (char *) fs->group_desc;
212 actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
217 if (actual != fs->blocksize * fs->desc_blocks) {
218 retval = EXT2_ET_SHORT_WRITE;
230 * Read the superblock and group descriptors and overwrite them.
232 errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags)
235 ssize_t actual, size;
238 size = fs->blocksize * (fs->group_desc_count + 1);
246 actual = read(fd, buf, size);
251 if (actual != size) {
252 retval = EXT2_ET_SHORT_READ;
257 * Now copy in the superblock and group descriptors
259 memcpy(fs->super, buf, SUPERBLOCK_SIZE);
261 memcpy(fs->group_desc, buf + fs->blocksize,
262 fs->blocksize * fs->group_desc_count);
272 * Write the block/inode bitmaps.
274 errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
282 if (flags & IMAGER_FLAG_INODEMAP) {
283 if (!fs->inode_map) {
284 retval = ext2fs_read_inode_bitmap(fs);
288 ptr = fs->inode_map->bitmap;
289 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
291 if (!fs->block_map) {
292 retval = ext2fs_read_block_bitmap(fs);
296 ptr = fs->block_map->bitmap;
297 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
299 size = size * fs->group_desc_count;
301 actual = write(fd, ptr, size);
306 if (actual != size) {
307 retval = EXT2_ET_SHORT_WRITE;
310 size = size % fs->blocksize;
311 memset(zero_buf, 0, sizeof(zero_buf));
313 size = fs->blocksize - size;
316 if (c > sizeof(zero_buf))
317 c = sizeof(zero_buf);
318 actual = write(fd, zero_buf, c);
324 retval = EXT2_ET_SHORT_WRITE;
337 * Read the block/inode bitmaps.
339 errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
346 if (flags & IMAGER_FLAG_INODEMAP) {
347 if (!fs->inode_map) {
348 retval = ext2fs_read_inode_bitmap(fs);
352 ptr = fs->inode_map->bitmap;
353 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
355 if (!fs->block_map) {
356 retval = ext2fs_read_block_bitmap(fs);
360 ptr = fs->block_map->bitmap;
361 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
363 size = size * fs->group_desc_count;
369 actual = read(fd, buf, size);
374 if (actual != size) {
375 retval = EXT2_ET_SHORT_WRITE;
378 memcpy(ptr, buf, size);