From a78926effb15bbabb1c0ed3e438b03be25c4d48c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 3 May 2001 04:02:29 +0000 Subject: [PATCH] Many files: ext2fs.h (EXT2_FLAG_IMAGE_FILE): Add new flag, and add image_header field in the ext2_filsys structure block.c (block_iterate_ind, block_iterate_dind, block_iterate_tind): inode.c (ext2fs_read_inode): rw_bitmaps.c (read_bitmaps): openfs.c (ext2fs_open): Add support for EXT2_FLAG_IMAGE_FILE imager.c (ext2fs_image_bitmap_read): Fix bug in imager to make sure the full bitmap is saved. --- lib/ext2fs/ChangeLog | 16 ++++++++++++++++ lib/ext2fs/block.c | 33 ++++++++++++++++++++++++--------- lib/ext2fs/e2image.h | 2 ++ lib/ext2fs/ext2fs.h | 4 +++- lib/ext2fs/imager.c | 6 ++++-- lib/ext2fs/inode.c | 26 ++++++++++++++++++-------- lib/ext2fs/openfs.c | 16 ++++++++++++++++ lib/ext2fs/rw_bitmaps.c | 23 +++++++++++++++++++++++ 8 files changed, 106 insertions(+), 20 deletions(-) diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index 26bde10..13d7299 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,5 +1,21 @@ +2001-05-02 Theodore Tso + + * ext2fs.h (EXT2_FLAG_IMAGE_FILE): Add new flag, and add + image_header field in the ext2_filsys structure + + * block.c (block_iterate_ind, block_iterate_dind, block_iterate_tind): + * inode.c (ext2fs_read_inode): + * rw_bitmaps.c (read_bitmaps): + * openfs.c (ext2fs_open): Add support for EXT2_FLAG_IMAGE_FILE + + * imager.c (ext2fs_image_bitmap_read): Fix bug in imager to make + sure the full bitmap is saved. + 2001-05-01 Theodore Tso + * e2image.h (struct ext2_image_hdr): Add space for the device name + in the image header. + * dir_iterate.c (ext2fs_process_dir_block): Add a double-check to make sure the rec_len is a multiple of 4, to prevent bus-errors on architectures which care about mis-aligned diff --git a/lib/ext2fs/block.c b/lib/ext2fs/block.c index 621e850..bd07023 100644 --- a/lib/ext2fs/block.c +++ b/lib/ext2fs/block.c @@ -64,8 +64,12 @@ static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, ret |= BLOCK_ERROR; return ret; } - ctx->errcode = io_channel_read_blk(ctx->fs->io, *ind_block, - 1, ctx->ind_buf); + if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) { + ctx->errcode = 0; + memset(ctx->ind_buf, 0, ctx->fs->blocksize); + } else + ctx->errcode = io_channel_read_blk(ctx->fs->io, *ind_block, + 1, ctx->ind_buf); if (ctx->errcode) { ret |= BLOCK_ERROR; return ret; @@ -105,7 +109,8 @@ static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, offset += sizeof(blk_t); } } - if (changed & BLOCK_CHANGED) { + if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && + (changed & BLOCK_CHANGED)) { if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) { block_nr = (blk_t *) ctx->ind_buf; @@ -149,8 +154,12 @@ static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, ret |= BLOCK_ERROR; return ret; } - ctx->errcode = io_channel_read_blk(ctx->fs->io, *dind_block, - 1, ctx->dind_buf); + if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) { + ctx->errcode = 0; + memset(ctx->dind_buf, 0, ctx->fs->blocksize); + } else + ctx->errcode = io_channel_read_blk(ctx->fs->io, *dind_block, + 1, ctx->dind_buf); if (ctx->errcode) { ret |= BLOCK_ERROR; return ret; @@ -192,7 +201,8 @@ static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, offset += sizeof(blk_t); } } - if (changed & BLOCK_CHANGED) { + if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && + (changed & BLOCK_CHANGED)) { if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) { block_nr = (blk_t *) ctx->dind_buf; @@ -236,8 +246,12 @@ static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, ret |= BLOCK_ERROR; return ret; } - ctx->errcode = io_channel_read_blk(ctx->fs->io, *tind_block, - 1, ctx->tind_buf); + if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) { + ctx->errcode = 0; + memset(ctx->tind_buf, 0, ctx->fs->blocksize); + } else + ctx->errcode = io_channel_read_blk(ctx->fs->io, *tind_block, + 1, ctx->tind_buf); if (ctx->errcode) { ret |= BLOCK_ERROR; return ret; @@ -279,7 +293,8 @@ static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, offset += sizeof(blk_t); } } - if (changed & BLOCK_CHANGED) { + if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && + (changed & BLOCK_CHANGED)) { if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) { block_nr = (blk_t *) ctx->tind_buf; diff --git a/lib/ext2fs/e2image.h b/lib/ext2fs/e2image.h index 75d7c04..e12b7d6 100644 --- a/lib/ext2fs/e2image.h +++ b/lib/ext2fs/e2image.h @@ -20,7 +20,9 @@ struct ext2_image_hdr { char fs_netaddr[32]; /* Network address */ __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */ __u32 fs_device; /* Device number of image */ + char fs_device_name[64]; /* Device name */ char fs_uuid[16]; /* UUID of filesystem */ + __u32 fs_blocksize; /* Block size of the filesystem */ __u32 fs_reserved[8]; __u32 image_device; /* Device number of image file */ diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 74bcb5d..f1a5e22 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -174,6 +174,7 @@ typedef struct ext2_file *ext2_file_t; #define EXT2_FLAG_FORCE 0x400 #define EXT2_FLAG_SUPER_ONLY 0x800 #define EXT2_FLAG_JOURNAL_DEV_OK 0x1000 +#define EXT2_FLAG_IMAGE_FILE 0x2000 /* * Special flag in the ext2 inode i_flag field that means that this is @@ -213,10 +214,11 @@ struct struct_ext2_filsys { ext2_dblist dblist; __u32 stride; /* for mke2fs */ struct ext2_super_block * orig_super; + struct ext2_image_hdr * image_header; /* * Reserved for future expansion */ - __u32 reserved[10]; + __u32 reserved[9]; /* * Reserved for the use of the calling application. diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c index 38dc7d8..f59541e 100644 --- a/lib/ext2fs/imager.c +++ b/lib/ext2fs/imager.c @@ -286,7 +286,7 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) return retval; } ptr = fs->inode_map->bitmap; - size = ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); } else { if (!fs->block_map) { retval = ext2fs_read_block_bitmap(fs); @@ -296,6 +296,7 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) ptr = fs->block_map->bitmap; size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; } + size = size * fs->group_desc_count; actual = write(fd, ptr, size); if (actual == -1) { @@ -349,7 +350,7 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) return retval; } ptr = fs->inode_map->bitmap; - size = ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); } else { if (!fs->block_map) { retval = ext2fs_read_block_bitmap(fs); @@ -359,6 +360,7 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) ptr = fs->block_map->bitmap; size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; } + size = size * fs->group_desc_count; buf = malloc(size); if (!buf) diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c index b09331c..9912a98 100644 --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -28,6 +28,7 @@ #endif #include "ext2fsP.h" +#include "e2image.h" struct ext2_struct_inode_scan { errcode_t magic; @@ -486,7 +487,7 @@ errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, unsigned long group, block, block_nr, offset; char *ptr; errcode_t retval; - int clen, length, i; + int clen, length, i, inodes_per_block; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -511,13 +512,22 @@ errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, } if ((ino == 0) || (ino > fs->super->s_inodes_count)) return EXT2_ET_BAD_INODE_NUM; - group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); - offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * - EXT2_INODE_SIZE(fs->super); - block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); - if (!fs->group_desc[(unsigned)group].bg_inode_table) - return EXT2_ET_MISSING_INODE_TABLE; - block_nr = fs->group_desc[(unsigned)group].bg_inode_table + block; + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { + inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); + block_nr = fs->image_header->offset_inode / fs->blocksize; + block_nr += (ino - 1) / inodes_per_block; + offset = ((ino - 1) % inodes_per_block) * + EXT2_INODE_SIZE(fs->super); + } else { + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * + EXT2_INODE_SIZE(fs->super); + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); + if (!fs->group_desc[(unsigned)group].bg_inode_table) + return EXT2_ET_MISSING_INODE_TABLE; + block_nr = fs->group_desc[(unsigned)group].bg_inode_table + + block; + } if (block_nr != fs->icache->buffer_blk) { retval = io_channel_read_blk(fs->io, block_nr, 1, fs->icache->buffer); diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index 3b9531a..f444524 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -30,6 +30,7 @@ #endif #include "ext2fs.h" +#include "e2image.h" /* * Note: if superblock is non-zero, block-size must also be non-zero. @@ -73,6 +74,21 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock, retval = ext2fs_get_mem(SUPERBLOCK_SIZE, (void **) &fs->super); if (retval) goto cleanup; + if (flags & EXT2_FLAG_IMAGE_FILE) { + retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr), + (void **) &fs->image_header); + if (retval) + goto cleanup; + retval = io_channel_read_blk(fs->io, 0, + -sizeof(struct ext2_image_hdr), + fs->image_header); + if (retval) + goto cleanup; + if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE) + return EXT2_ET_MAGIC_E2IMAGE; + superblock = 1; + block_size = fs->image_header->fs_blocksize; + } /* * If the user specifies a specific block # for the diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index 73979fd..093dddf 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -30,6 +30,7 @@ #endif #include "ext2fs.h" +#include "e2image.h" #ifdef __powerpc__ /* @@ -188,6 +189,28 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) } ext2fs_free_mem((void **) &buf); + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { + if (inode_bitmap) { + blk = (fs->image_header->offset_inodemap / + fs->blocksize); + retval = io_channel_read_blk(fs->io, blk, + -(inode_nbytes * fs->group_desc_count), + inode_bitmap); + if (retval) + goto cleanup; + } + if (block_bitmap) { + blk = (fs->image_header->offset_blockmap / + fs->blocksize); + retval = io_channel_read_blk(fs->io, blk, + -(block_nbytes * fs->group_desc_count), + block_bitmap); + if (retval) + goto cleanup; + } + return 0; + } + for (i = 0; i < fs->group_desc_count; i++) { if (block_bitmap) { blk = fs->group_desc[i].bg_block_bitmap; -- 1.8.3.1