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>
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 = xmalloc(fs->blocksize * BUF_BLOCKS);
71 for (group = 0; group < fs->group_desc_count; group++) {
72 blk = fs->group_desc[(unsigned)group].bg_inode_table;
74 return EXT2_ET_MISSING_INODE_TABLE;
75 left = fs->inode_blocks_per_group;
80 retval = io_channel_read_blk(fs->io, blk, c, buf);
85 if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
89 /* Skip zero blocks */
90 if (check_zero_block(cp, fs->blocksize)) {
95 lseek(fd, fs->blocksize, SEEK_CUR);
98 /* Find non-zero blocks */
99 for (d=1; d < c; d++) {
100 if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
104 actual = write(fd, cp, fs->blocksize * d);
109 if (actual != (ssize_t) (fs->blocksize * d)) {
110 retval = EXT2_ET_SHORT_WRITE;
115 cp += fs->blocksize * d;
128 * Read in the inode table and stuff it into place
130 errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
131 int flags EXT2FS_ATTR((unused)))
133 unsigned int group, c, left;
139 buf = xmalloc(fs->blocksize * BUF_BLOCKS);
141 for (group = 0; group < fs->group_desc_count; group++) {
142 blk = fs->group_desc[(unsigned)group].bg_inode_table;
144 retval = EXT2_ET_MISSING_INODE_TABLE;
147 left = fs->inode_blocks_per_group;
152 actual = read(fd, buf, fs->blocksize * c);
157 if (actual != (ssize_t) (fs->blocksize * c)) {
158 retval = EXT2_ET_SHORT_READ;
161 retval = io_channel_write_blk(fs->io, blk, c, buf);
169 retval = ext2fs_flush_icache(fs);
177 * Write out superblock and group descriptors
179 errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
180 int flags EXT2FS_ATTR((unused)))
186 buf = xmalloc(fs->blocksize);
189 * Write out the superblock
191 memset(buf, 0, fs->blocksize);
192 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
193 actual = write(fd, buf, fs->blocksize);
198 if (actual != (ssize_t) fs->blocksize) {
199 retval = EXT2_ET_SHORT_WRITE;
204 * Now write out the block group descriptors
206 cp = (char *) fs->group_desc;
207 actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
212 if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
213 retval = EXT2_ET_SHORT_WRITE;
225 * Read the superblock and group descriptors and overwrite them.
227 errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
228 int flags EXT2FS_ATTR((unused)))
231 ssize_t actual, size;
234 size = fs->blocksize * (fs->group_desc_count + 1);
240 actual = read(fd, buf, size);
245 if (actual != size) {
246 retval = EXT2_ET_SHORT_READ;
251 * Now copy in the superblock and group descriptors
253 memcpy(fs->super, buf, SUPERBLOCK_SIZE);
255 memcpy(fs->group_desc, buf + fs->blocksize,
256 fs->blocksize * fs->group_desc_count);
266 * Write the block/inode bitmaps.
268 errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
276 if (flags & IMAGER_FLAG_INODEMAP) {
277 if (!fs->inode_map) {
278 retval = ext2fs_read_inode_bitmap(fs);
282 ptr = fs->inode_map->bitmap;
283 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
285 if (!fs->block_map) {
286 retval = ext2fs_read_block_bitmap(fs);
290 ptr = fs->block_map->bitmap;
291 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
293 size = size * fs->group_desc_count;
295 actual = write(fd, ptr, size);
300 if (actual != size) {
301 retval = EXT2_ET_SHORT_WRITE;
304 size = size % fs->blocksize;
305 memset(zero_buf, 0, sizeof(zero_buf));
307 size = fs->blocksize - size;
310 if (c > (int) sizeof(zero_buf))
311 c = sizeof(zero_buf);
312 actual = write(fd, zero_buf, c);
318 retval = EXT2_ET_SHORT_WRITE;
331 * Read the block/inode bitmaps.
333 errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
340 if (flags & IMAGER_FLAG_INODEMAP) {
341 if (!fs->inode_map) {
342 retval = ext2fs_read_inode_bitmap(fs);
346 ptr = fs->inode_map->bitmap;
347 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
349 if (!fs->block_map) {
350 retval = ext2fs_read_block_bitmap(fs);
354 ptr = fs->block_map->bitmap;
355 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
357 size = size * fs->group_desc_count;
361 actual = read(fd, buf, size);
366 if (actual != size) {
367 retval = EXT2_ET_SHORT_WRITE;
370 memcpy(ptr, buf, size);