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)
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);