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 = malloc(fs->blocksize * BUF_BLOCKS);
73 for (group = 0; group < fs->group_desc_count; group++) {
74 blk = fs->group_desc[(unsigned)group].bg_inode_table;
76 retval = EXT2_ET_MISSING_INODE_TABLE;
79 left = fs->inode_blocks_per_group;
84 retval = io_channel_read_blk(fs->io, blk, c, buf);
89 if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
93 /* Skip zero blocks */
94 if (check_zero_block(cp, fs->blocksize)) {
99 lseek(fd, fs->blocksize, SEEK_CUR);
102 /* Find non-zero blocks */
103 for (d=1; d < c; d++) {
104 if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
108 actual = write(fd, cp, fs->blocksize * d);
113 if (actual != (ssize_t) (fs->blocksize * d)) {
114 retval = EXT2_ET_SHORT_WRITE;
119 cp += fs->blocksize * d;
132 * Read in the inode table and stuff it into place
134 errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
135 int flags EXT2FS_ATTR((unused)))
137 unsigned int group, c, left;
143 buf = malloc(fs->blocksize * BUF_BLOCKS);
147 for (group = 0; group < fs->group_desc_count; group++) {
148 blk = fs->group_desc[(unsigned)group].bg_inode_table;
150 retval = EXT2_ET_MISSING_INODE_TABLE;
153 left = fs->inode_blocks_per_group;
158 actual = read(fd, buf, fs->blocksize * c);
163 if (actual != (ssize_t) (fs->blocksize * c)) {
164 retval = EXT2_ET_SHORT_READ;
167 retval = io_channel_write_blk(fs->io, blk, c, buf);
175 retval = ext2fs_flush_icache(fs);
183 * Write out superblock and group descriptors
185 errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
186 int flags EXT2FS_ATTR((unused)))
192 buf = malloc(fs->blocksize);
197 * Write out the superblock
199 memset(buf, 0, fs->blocksize);
200 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
201 actual = write(fd, buf, fs->blocksize);
206 if (actual != (ssize_t) fs->blocksize) {
207 retval = EXT2_ET_SHORT_WRITE;
212 * Now write out the block group descriptors
214 cp = (char *) fs->group_desc;
215 actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
220 if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
221 retval = EXT2_ET_SHORT_WRITE;
233 * Read the superblock and group descriptors and overwrite them.
235 errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
236 int flags EXT2FS_ATTR((unused)))
239 ssize_t actual, size;
242 size = fs->blocksize * (fs->group_desc_count + 1);
250 actual = read(fd, buf, size);
255 if (actual != size) {
256 retval = EXT2_ET_SHORT_READ;
261 * Now copy in the superblock and group descriptors
263 memcpy(fs->super, buf, SUPERBLOCK_SIZE);
265 memcpy(fs->group_desc, buf + fs->blocksize,
266 fs->blocksize * fs->group_desc_count);
276 * Write the block/inode bitmaps.
278 errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
280 ext2fs_generic_bitmap bmap;
281 errcode_t err, retval;
283 __u32 itr, cnt, size;
287 if (flags & IMAGER_FLAG_INODEMAP) {
288 if (!fs->inode_map) {
289 retval = ext2fs_read_inode_bitmap(fs);
293 bmap = fs->inode_map;
294 err = EXT2_ET_MAGIC_INODE_BITMAP;
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 err = EXT2_ET_MAGIC_BLOCK_BITMAP;
306 itr = fs->super->s_first_data_block;
307 cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
308 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
310 total_size = size * fs->group_desc_count;
314 if (size > (cnt >> 3))
317 retval = ext2fs_get_generic_bitmap_range(bmap,
318 err, itr, size << 3, buf);
322 actual = write(fd, buf, size);
325 if (actual != (int) size)
326 return EXT2_ET_SHORT_READ;
332 size = total_size % fs->blocksize;
333 memset(buf, 0, sizeof(buf));
335 size = fs->blocksize - size;
338 if (c > (int) sizeof(buf))
340 actual = write(fd, buf, c);
344 return EXT2_ET_SHORT_WRITE;
353 * Read the block/inode bitmaps.
355 errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
357 ext2fs_generic_bitmap bmap;
358 errcode_t err, retval;
364 if (flags & IMAGER_FLAG_INODEMAP) {
365 if (!fs->inode_map) {
366 retval = ext2fs_read_inode_bitmap(fs);
370 bmap = fs->inode_map;
371 err = EXT2_ET_MAGIC_INODE_BITMAP;
373 cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
374 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
376 if (!fs->block_map) {
377 retval = ext2fs_read_block_bitmap(fs);
381 bmap = fs->block_map;
382 err = EXT2_ET_MAGIC_BLOCK_BITMAP;
383 itr = fs->super->s_first_data_block;
384 cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
385 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
390 if (size > (cnt >> 3))
393 actual = read(fd, buf, size);
396 if (actual != (int) size)
397 return EXT2_ET_SHORT_READ;
399 retval = ext2fs_set_generic_bitmap_range(bmap,
400 err, itr, size << 3, buf);