Currently e2image metadata image handling and creating is completely broken on big endian systems. It just does not care about endianness at all. This was uncovered With addition of i_bitmaps test, which is the first test that actually tests e2image metadata image. Fix it by making sure that all on-disk metadata that we write and read to/from the metadata image is properly converted. Signed-off-by: Lukas Czerner <lczerner@xxxxxxxxxx> --- lib/ext2fs/imager.c | 41 +++++++++++++++++++++++++++++++++++++++++ lib/ext2fs/inode.c | 2 +- lib/ext2fs/openfs.c | 4 ++-- lib/ext2fs/rw_bitmaps.c | 4 ++-- misc/e2image.c | 22 +++++++++++----------- 5 files changed, 57 insertions(+), 16 deletions(-) diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c index efb85b9..7fd06f7 100644 --- a/lib/ext2fs/imager.c +++ b/lib/ext2fs/imager.c @@ -195,6 +195,11 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, char *buf, *cp; ssize_t actual; errcode_t retval; +#ifdef WORDS_BIGENDIAN + unsigned int groups_per_block; + struct ext2_group_desc *gdp; + int j; +#endif buf = malloc(fs->blocksize); if (!buf) @@ -204,7 +209,17 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, * Write out the superblock */ memset(buf, 0, fs->blocksize); +#ifdef WORDS_BIGENDIAN + /* + * We're writing out superblock so let's convert + * it to little endian and then back if needed + */ + ext2fs_swap_super(fs->super); memcpy(buf, fs->super, SUPERBLOCK_SIZE); + ext2fs_swap_super(fs->super); +#else + memcpy(buf, fs->super, SUPERBLOCK_SIZE); +#endif actual = write(fd, buf, fs->blocksize); if (actual == -1) { retval = errno; @@ -218,8 +233,34 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, /* * Now write out the block group descriptors */ + cp = (char *) fs->group_desc; + +#ifdef WORDS_BIGENDIAN + /* + * Convert group descriptors to little endian and back + * if needed + */ + groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); + gdp = (struct ext2_group_desc *) cp; + for (j=0; j < groups_per_block*fs->desc_blocks; j++) { + gdp = ext2fs_group_desc(fs, fs->group_desc, j); + ext2fs_swap_group_desc2(fs, gdp); + } +#endif + actual = write(fd, cp, fs->blocksize * fs->desc_blocks); + + +#ifdef WORDS_BIGENDIAN + groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); + gdp = (struct ext2_group_desc *) cp; + for (j=0; j < groups_per_block*fs->desc_blocks; j++) { + gdp = ext2fs_group_desc(fs, fs->group_desc, j); + ext2fs_swap_group_desc2(fs, gdp); + } +#endif + if (actual == -1) { retval = errno; goto errout; diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c index ad01a9f..015cfe4 100644 --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -770,7 +770,7 @@ errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, } 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 = ext2fs_le32_to_cpu(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); diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index 385d6e8..532e70f 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -185,10 +185,10 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, fs->image_header); if (retval) goto cleanup; - if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE) + if (ext2fs_le32_to_cpu(fs->image_header->magic_number) != EXT2_ET_MAGIC_E2IMAGE) return EXT2_ET_MAGIC_E2IMAGE; superblock = 1; - block_size = fs->image_header->fs_blocksize; + block_size = ext2fs_le32_to_cpu(fs->image_header->fs_blocksize); } /* diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index 0b532db..e86bacd 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -253,7 +253,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) ext2fs_free_mem(&buf); if (fs->flags & EXT2_FLAG_IMAGE_FILE) { - blk = (fs->image_header->offset_inodemap / fs->blocksize); + blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize); ino_cnt = fs->super->s_inodes_count; while (inode_bitmap && ino_cnt > 0) { retval = io_channel_read_blk64(fs->image_io, blk++, @@ -270,7 +270,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) ino_itr += cnt; ino_cnt -= cnt; } - blk = (fs->image_header->offset_blockmap / + blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) / fs->blocksize); blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count); diff --git a/misc/e2image.c b/misc/e2image.c index 5a18bb4..83ae633 100644 --- a/misc/e2image.c +++ b/misc/e2image.c @@ -240,7 +240,7 @@ static void write_image_file(ext2_filsys fs, int fd) write_header(fd, NULL, sizeof(struct ext2_image_hdr), fs->blocksize); memset(&hdr, 0, sizeof(struct ext2_image_hdr)); - hdr.offset_super = seek_relative(fd, 0); + hdr.offset_super = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_super_write(fs, fd, 0); if (retval) { com_err(program_name, retval, "%s", @@ -248,7 +248,7 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.offset_inode = seek_relative(fd, 0); + hdr.offset_inode = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_inode_write(fs, fd, (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0); if (retval) { @@ -257,7 +257,7 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.offset_blockmap = seek_relative(fd, 0); + hdr.offset_blockmap = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_bitmap_write(fs, fd, 0); if (retval) { com_err(program_name, retval, "%s", @@ -265,7 +265,7 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.offset_inodemap = seek_relative(fd, 0); + hdr.offset_inodemap = ext2fs_cpu_to_le32(seek_relative(fd, 0)); retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP); if (retval) { com_err(program_name, retval, "%s", @@ -273,23 +273,23 @@ static void write_image_file(ext2_filsys fs, int fd) exit(1); } - hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE; + hdr.magic_number = ext2fs_cpu_to_le32(EXT2_ET_MAGIC_E2IMAGE); strcpy(hdr.magic_descriptor, "Ext2 Image 1.0"); gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname)); strncpy(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name)-1); hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0; - hdr.fs_blocksize = fs->blocksize; + hdr.fs_blocksize = ext2fs_cpu_to_le32(fs->blocksize); if (stat(device_name, &st) == 0) - hdr.fs_device = st.st_rdev; + hdr.fs_device = ext2fs_cpu_to_le32(st.st_rdev); if (fstat(fd, &st) == 0) { - hdr.image_device = st.st_dev; - hdr.image_inode = st.st_ino; + hdr.image_device = ext2fs_cpu_to_le32(st.st_dev); + hdr.image_inode = ext2fs_cpu_to_le32(st.st_ino); } memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid)); - hdr.image_time = time(0); + hdr.image_time = ext2fs_cpu_to_le32(time(0)); write_header(fd, &hdr, sizeof(struct ext2_image_hdr), fs->blocksize); } @@ -1423,7 +1423,7 @@ static void install_image(char *device, char *image_fn, int type) ext2fs_rewrite_to_io(fs, io); - seek_set(fd, fs->image_header->offset_inode); + seek_set(fd, ext2fs_le32_to_cpu(fs->image_header->offset_inode)); retval = ext2fs_image_inode_read(fs, fd, 0); if (retval) { -- 2.7.5