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;
71 buf = malloc(fs->blocksize * BUF_BLOCKS);
75 for (group = 0; group < fs->group_desc_count; group++) {
76 blk = ext2fs_inode_table_loc(fs, (unsigned)group);
78 retval = EXT2_ET_MISSING_INODE_TABLE;
81 left = fs->inode_blocks_per_group;
86 retval = io_channel_read_blk64(fs->io, blk, c, buf);
91 if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
95 /* Skip zero blocks */
96 if (check_zero_block(cp, fs->blocksize)) {
101 r = lseek(fd, fs->blocksize, SEEK_CUR);
108 /* Find non-zero blocks */
109 for (d=1; d < c; d++) {
110 if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
114 actual = write(fd, cp, fs->blocksize * d);
119 if (actual != (ssize_t) (fs->blocksize * d)) {
120 retval = EXT2_ET_SHORT_WRITE;
125 cp += fs->blocksize * d;
138 * Read in the inode table and stuff it into place
140 errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
141 int flags EXT2FS_ATTR((unused)))
143 unsigned int group, c, left;
149 buf = malloc(fs->blocksize * BUF_BLOCKS);
153 for (group = 0; group < fs->group_desc_count; group++) {
154 blk = ext2fs_inode_table_loc(fs, (unsigned)group);
156 retval = EXT2_ET_MISSING_INODE_TABLE;
159 left = fs->inode_blocks_per_group;
164 actual = read(fd, buf, fs->blocksize * c);
169 if (actual != (ssize_t) (fs->blocksize * c)) {
170 retval = EXT2_ET_SHORT_READ;
173 retval = io_channel_write_blk64(fs->io, blk, c, buf);
181 retval = ext2fs_flush_icache(fs);
189 * Write out superblock and group descriptors
191 errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
192 int flags EXT2FS_ATTR((unused)))
198 buf = malloc(fs->blocksize);
203 * Write out the superblock
205 memset(buf, 0, fs->blocksize);
206 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
207 actual = write(fd, buf, fs->blocksize);
212 if (actual != (ssize_t) fs->blocksize) {
213 retval = EXT2_ET_SHORT_WRITE;
218 * Now write out the block group descriptors
220 cp = (char *) fs->group_desc;
221 actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
226 if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
227 retval = EXT2_ET_SHORT_WRITE;
239 * Read the superblock and group descriptors and overwrite them.
241 errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
242 int flags EXT2FS_ATTR((unused)))
245 ssize_t actual, size;
248 size = fs->blocksize * (fs->group_desc_count + 1);
256 actual = read(fd, buf, size);
261 if (actual != size) {
262 retval = EXT2_ET_SHORT_READ;
267 * Now copy in the superblock and group descriptors
269 memcpy(fs->super, buf, SUPERBLOCK_SIZE);
271 memcpy(fs->group_desc, buf + fs->blocksize,
272 fs->blocksize * fs->group_desc_count);
282 * Write the block/inode bitmaps.
284 errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
286 ext2fs_generic_bitmap bmap;
290 __u64 itr, cnt, size, total_size;
293 if (flags & IMAGER_FLAG_INODEMAP) {
294 if (!fs->inode_map) {
295 retval = ext2fs_read_inode_bitmap(fs);
299 bmap = fs->inode_map;
301 cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
302 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
304 if (!fs->block_map) {
305 retval = ext2fs_read_block_bitmap(fs);
309 bmap = fs->block_map;
310 itr = fs->super->s_first_data_block;
311 cnt = EXT2_GROUPS_TO_BLOCKS(fs->super, fs->group_desc_count);
312 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
314 total_size = size * fs->group_desc_count;
318 if (size > (cnt >> 3))
321 retval = ext2fs_get_generic_bmap_range(bmap, itr,
326 actual = write(fd, buf, size);
329 if (actual != (int) size)
330 return EXT2_ET_SHORT_READ;
336 size = total_size % fs->blocksize;
337 memset(buf, 0, sizeof(buf));
339 size = fs->blocksize - size;
342 if (c > (int) sizeof(buf))
344 actual = write(fd, buf, c);
347 if ((size_t) actual != c)
348 return EXT2_ET_SHORT_WRITE;
357 * Read the block/inode bitmaps.
359 errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
361 ext2fs_generic_bitmap bmap;
368 if (flags & IMAGER_FLAG_INODEMAP) {
369 if (!fs->inode_map) {
370 retval = ext2fs_read_inode_bitmap(fs);
374 bmap = fs->inode_map;
376 cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
377 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
379 if (!fs->block_map) {
380 retval = ext2fs_read_block_bitmap(fs);
384 bmap = fs->block_map;
385 itr = fs->super->s_first_data_block;
386 cnt = EXT2_GROUPS_TO_BLOCKS(fs->super, fs->group_desc_count);
387 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
392 if (size > (cnt >> 3))
395 actual = read(fd, buf, size);
398 if (actual != (int) size)
399 return EXT2_ET_SHORT_READ;
401 retval = ext2fs_set_generic_bmap_range(bmap, itr,