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)
72 buf = malloc(fs->blocksize * BUF_BLOCKS);
76 for (group = 0; group < fs->group_desc_count; group++) {
77 blk = ext2fs_inode_table_loc(fs, group);
79 retval = EXT2_ET_MISSING_INODE_TABLE;
82 left = fs->inode_blocks_per_group;
87 retval = io_channel_read_blk64(fs->io, blk, c, buf);
92 if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
96 /* Skip zero blocks */
97 if (check_zero_block(cp, fs->blocksize)) {
102 r = ext2fs_llseek(fd, fs->blocksize,
110 /* Find non-zero blocks */
111 for (d = 1; d < c; d++) {
112 if (check_zero_block(cp +
118 actual = write(fd, cp, d * fs->blocksize);
123 if (actual != d * fs->blocksize) {
124 retval = EXT2_ET_SHORT_WRITE;
129 cp += d * fs->blocksize;
142 * Read in the inode table and stuff it into place
144 errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
145 int flags EXT2FS_ATTR((unused)))
154 buf = malloc(fs->blocksize * BUF_BLOCKS);
158 for (group = 0; group < fs->group_desc_count; group++) {
159 blk = ext2fs_inode_table_loc(fs, group);
161 retval = EXT2_ET_MISSING_INODE_TABLE;
164 left = fs->inode_blocks_per_group;
169 actual = read(fd, buf, fs->blocksize * c);
174 if (actual != fs->blocksize * c) {
175 retval = EXT2_ET_SHORT_READ;
178 retval = io_channel_write_blk64(fs->io, blk, c, buf);
186 retval = ext2fs_flush_icache(fs);
194 * Write out superblock and group descriptors
196 errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
197 int flags EXT2FS_ATTR((unused)))
202 #ifdef WORDS_BIGENDIAN
203 unsigned int groups_per_block;
204 struct ext2_group_desc *gdp;
208 if (fs->group_desc == NULL)
209 return EXT2_ET_NO_GDESC;
211 buf = malloc(fs->blocksize);
216 * Write out the superblock
218 memset(buf, 0, fs->blocksize);
219 #ifdef WORDS_BIGENDIAN
221 * We're writing out superblock so let's convert
222 * it to little endian and then back if needed
224 ext2fs_swap_super(fs->super);
225 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
226 ext2fs_swap_super(fs->super);
228 memcpy(buf, fs->super, SUPERBLOCK_SIZE);
230 actual = write(fd, buf, fs->blocksize);
235 if (actual != (ssize_t) fs->blocksize) {
236 retval = EXT2_ET_SHORT_WRITE;
241 * Now write out the block group descriptors
244 cp = (char *) fs->group_desc;
246 #ifdef WORDS_BIGENDIAN
248 * Convert group descriptors to little endian and back
251 groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
252 for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
253 gdp = ext2fs_group_desc(fs, fs->group_desc, j);
255 ext2fs_swap_group_desc2(fs, gdp);
259 actual = write(fd, cp, (ssize_t)fs->blocksize * fs->desc_blocks);
262 #ifdef WORDS_BIGENDIAN
263 groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
264 for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
265 gdp = ext2fs_group_desc(fs, fs->group_desc, j);
267 ext2fs_swap_group_desc2(fs, gdp);
275 if (actual != (ssize_t)fs->blocksize * fs->desc_blocks) {
276 retval = EXT2_ET_SHORT_WRITE;
288 * Read the superblock and group descriptors and overwrite them.
290 errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
291 int flags EXT2FS_ATTR((unused)))
294 ssize_t actual, size;
297 size = (ssize_t)fs->blocksize * (fs->group_desc_count + 1);
305 actual = read(fd, buf, size);
310 if (actual != size) {
311 retval = EXT2_ET_SHORT_READ;
316 * Now copy in the superblock and group descriptors
318 memcpy(fs->super, buf, SUPERBLOCK_SIZE);
320 memcpy(fs->group_desc, buf + fs->blocksize,
321 (ssize_t)fs->blocksize * fs->group_desc_count);
331 * Write the block/inode bitmaps.
333 errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
335 ext2fs_generic_bitmap bmap;
339 __u64 itr, cnt, size, total_size;
342 if (flags & IMAGER_FLAG_INODEMAP) {
343 if (!fs->inode_map) {
344 retval = ext2fs_read_inode_bitmap(fs);
348 bmap = fs->inode_map;
350 cnt = (__u64)EXT2_INODES_PER_GROUP(fs->super) *
351 fs->group_desc_count;
352 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
354 if (!fs->block_map) {
355 retval = ext2fs_read_block_bitmap(fs);
359 bmap = fs->block_map;
360 itr = fs->super->s_first_data_block;
361 cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count);
362 size = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
364 total_size = size * fs->group_desc_count;
368 if (size > (cnt >> 3))
371 retval = ext2fs_get_generic_bmap_range(bmap, itr,
376 actual = write(fd, buf, size);
379 if (actual != (int) size)
380 return EXT2_ET_SHORT_READ;
386 size = total_size % fs->blocksize;
387 memset(buf, 0, sizeof(buf));
389 size = fs->blocksize - size;
392 if (c > (int) sizeof(buf))
394 actual = write(fd, buf, c);
397 if ((size_t) actual != c)
398 return EXT2_ET_SHORT_WRITE;
407 * Read the block/inode bitmaps.
409 errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
411 ext2fs_generic_bitmap bmap;
418 if (flags & IMAGER_FLAG_INODEMAP) {
419 if (!fs->inode_map) {
420 retval = ext2fs_read_inode_bitmap(fs);
424 bmap = fs->inode_map;
426 cnt = (__u64)EXT2_INODES_PER_GROUP(fs->super) *
427 fs->group_desc_count;
428 size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
430 if (!fs->block_map) {
431 retval = ext2fs_read_block_bitmap(fs);
435 bmap = fs->block_map;
436 itr = fs->super->s_first_data_block;
437 cnt = EXT2_GROUPS_TO_BLOCKS(fs->super, fs->group_desc_count);
438 size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
443 if (size > (cnt >> 3))
446 actual = read(fd, buf, size);
449 if (actual != (int) size)
450 return EXT2_ET_SHORT_READ;
452 retval = ext2fs_set_generic_bmap_range(bmap, itr,