From 7331196a16e57ef80dd6ae40eeeab14747ce2f5d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 25 Jan 2005 23:42:56 -0500 Subject: [PATCH] Add library support for large (EA in inode) inodes. Make sure that garbage doesn't get written into the reserved portion when writing into filesystems that have large inodes defined. --- lib/ext2fs/ChangeLog | 22 ++++++ lib/ext2fs/ext2_fs.h | 59 ++++++++++++++ lib/ext2fs/ext2fs.h | 16 +++- lib/ext2fs/ext_attr.c | 40 +--------- lib/ext2fs/inode.c | 215 +++++++++++++++++++++++++++++--------------------- lib/ext2fs/swapfs.c | 90 ++++++++++++++++++++- 6 files changed, 310 insertions(+), 132 deletions(-) diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index c0dc827..451491e 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,25 @@ +2005-01-25 Theodore Ts'o + + * ext2fs.h: Add definition of struct ext2_inode_large + + * ext2_fs.h: Add new function prototypes + + * ext_attr.c (ext2fs_read_ext_attr, ext2fs_write_ext_attr): The + ext2fs_swap_ext_attr() has been moved to swapfs.c, and + given a new argument, has_header. + + * swapfs.c (ext2fs_swap_ext_attr): Moved from ext_attr.c, and + takes an argument which controls whether or not there is + an EA header which needs to be byteswaped. + (ext2fs_swap_inode_full): New function which byte-swaps + the EA in inode. + + * inode.c (ext2fs_get_next_inode_full, ext2fs_read_inode_full, + ext2fs_write_inode_full): New functions, originally from + Alex Tomas, but which needed to be substantially fixed so + that the tests wouldn't cause major stack overwrite bugs + in byte-swapping is enabled. + 2005-01-18 Theodore Ts'o * Makefile.in: Fix the kernel compile-time echo commands to be diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index b182ef2..ff615c4 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -304,6 +304,65 @@ struct ext2_inode { } osd2; /* OS dependent 2 */ }; +/* + * Permanent part of an large inode on the disk + */ +struct ext2_inode_large { + __u16 i_mode; /* File mode */ + __u16 i_uid; /* Low 16 bits of Owner Uid */ + __u32 i_size; /* Size in bytes */ + __u32 i_atime; /* Access time */ + __u32 i_ctime; /* Creation time */ + __u32 i_mtime; /* Modification time */ + __u32 i_dtime; /* Deletion Time */ + __u16 i_gid; /* Low 16 bits of Group Id */ + __u16 i_links_count; /* Links count */ + __u32 i_blocks; /* Blocks count */ + __u32 i_flags; /* File flags */ + union { + struct { + __u32 l_i_reserved1; + } linux1; + struct { + __u32 h_i_translator; + } hurd1; + struct { + __u32 m_i_reserved1; + } masix1; + } osd1; /* OS dependent 1 */ + __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ + __u32 i_generation; /* File version (for NFS) */ + __u32 i_file_acl; /* File ACL */ + __u32 i_dir_acl; /* Directory ACL */ + __u32 i_faddr; /* Fragment address */ + union { + struct { + __u8 l_i_frag; /* Fragment number */ + __u8 l_i_fsize; /* Fragment size */ + __u16 i_pad1; + __u16 l_i_uid_high; /* these 2 fields */ + __u16 l_i_gid_high; /* were reserved2[0] */ + __u32 l_i_reserved2; + } linux2; + struct { + __u8 h_i_frag; /* Fragment number */ + __u8 h_i_fsize; /* Fragment size */ + __u16 h_i_mode_high; + __u16 h_i_uid_high; + __u16 h_i_gid_high; + __u32 h_i_author; + } hurd2; + struct { + __u8 m_i_frag; /* Fragment number */ + __u8 m_i_fsize; /* Fragment size */ + __u16 m_pad1; + __u32 m_i_reserved2[2]; + } masix2; + } osd2; /* OS dependent 2 */ + __u16 i_extra_isize; + __u16 i_pad1; +}; + #define i_size_high i_dir_acl #if defined(__KERNEL__) || defined(__linux__) diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 1b7e1b0..a25c728 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -698,7 +698,6 @@ extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest); extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); /* ext_attr.c */ -void ext2fs_swap_ext_attr(ext2_filsys fs, char *to, char *from); extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf); extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *buf); @@ -787,6 +786,10 @@ errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); /* inode.c */ extern errcode_t ext2fs_flush_icache(ext2_filsys fs); +extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, + ext2_ino_t *ino, + struct ext2_inode *inode, + int bufsize); extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, ext2_inode_scan *ret_scan); extern void ext2fs_close_inode_scan(ext2_inode_scan scan); @@ -803,8 +806,14 @@ extern void ext2fs_set_inode_callback void *done_group_data); extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, int clear_flags); +extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize); extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, struct ext2_inode * inode); +extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize); extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode * inode); extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); @@ -909,8 +918,13 @@ extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, ext2fs_generic_bitmap *dest); /* swapfs.c */ +extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, + int has_header); extern void ext2fs_swap_super(struct ext2_super_block * super); extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp); +extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, + struct ext2_inode_large *f, int hostorder, + int bufsize); extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t, struct ext2_inode *f, int hostorder); diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c index 9aa092f..08211c3 100644 --- a/lib/ext2fs/ext_attr.c +++ b/lib/ext2fs/ext_attr.c @@ -23,42 +23,6 @@ #include "ext2fs.h" -#ifdef EXT2FS_ENABLE_SWAPFS -void ext2fs_swap_ext_attr(ext2_filsys fs, char *to, char *from) -{ - struct ext2_ext_attr_header *from_header = - (struct ext2_ext_attr_header *)from; - struct ext2_ext_attr_header *to_header = - (struct ext2_ext_attr_header *)to; - struct ext2_ext_attr_entry *from_entry, *to_entry; - char *from_end = (char *)from_header + fs->blocksize; - int n; - - if (to_header != from_header) - memcpy(to_header, from_header, fs->blocksize); - - to_header->h_magic = ext2fs_swab32(from_header->h_magic); - to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); - to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); - for (n=0; n<4; n++) - to_header->h_reserved[n] = - ext2fs_swab32(from_header->h_reserved[n]); - - from_entry = (struct ext2_ext_attr_entry *)(from_header+1); - to_entry = (struct ext2_ext_attr_entry *)(to_header+1); - while ((char *)from_entry < from_end && *(__u32 *)from_entry) { - to_entry->e_value_offs = - ext2fs_swab16(from_entry->e_value_offs); - to_entry->e_value_block = - ext2fs_swab32(from_entry->e_value_block); - to_entry->e_value_size = - ext2fs_swab32(from_entry->e_value_size); - from_entry = EXT2_EXT_ATTR_NEXT(from_entry); - to_entry = EXT2_EXT_ATTR_NEXT(to_entry); - } -} -#endif - errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf) { errcode_t retval; @@ -69,7 +33,7 @@ errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf) #ifdef EXT2FS_ENABLE_SWAPFS if ((fs->flags & (EXT2_FLAG_SWAP_BYTES| EXT2_FLAG_SWAP_BYTES_READ)) != 0) - ext2fs_swap_ext_attr(fs, buf, buf); + ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1); #endif return 0; } @@ -87,7 +51,7 @@ errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf) if (retval) return retval; write_buf = buf; - ext2fs_swap_ext_attr(fs, buf, inbuf); + ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1); } else #endif write_buf = (char *) inbuf; diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c index d0de254..2517d67 100644 --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -14,6 +14,9 @@ #if HAVE_UNISTD_H #include #endif +#if HAVE_ERRNO_H +#include +#endif #if HAVE_SYS_STAT_H #include #endif @@ -375,8 +378,8 @@ static inline int is_empty_scan(ext2_inode_scan scan) } #endif -errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, - struct ext2_inode *inode) +errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode, int bufsize) { errcode_t retval; int extra_bytes = 0; @@ -446,8 +449,10 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, #ifdef EXT2FS_ENABLE_SWAPFS if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - ext2fs_swap_inode(scan->fs, inode, - (struct ext2_inode *) scan->temp_buffer, 0); + ext2fs_swap_inode_full(scan->fs, + (struct ext2_inode_large *) inode, + (struct ext2_inode_large *) scan->temp_buffer, + 0, bufsize); else #endif *inode = *((struct ext2_inode *) scan->temp_buffer); @@ -458,11 +463,13 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, #ifdef EXT2FS_ENABLE_SWAPFS if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - ext2fs_swap_inode(scan->fs, inode, - (struct ext2_inode *) scan->ptr, 0); + ext2fs_swap_inode_full(scan->fs, + (struct ext2_inode_large *) inode, + (struct ext2_inode_large *) scan->ptr, + 0, bufsize); else #endif - *inode = *((struct ext2_inode *) scan->ptr); + memcpy(inode, scan->ptr, bufsize); scan->ptr += scan->inode_size; scan->bytes_left -= scan->inode_size; if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) @@ -475,17 +482,23 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, return retval; } +errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode) +{ + return ext2fs_get_next_inode_full(scan, ino, inode, + sizeof(struct ext2_inode)); +} + /* * Functions to read and write a single inode. */ -errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode) +errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize) { unsigned long group, block, block_nr, offset; char *ptr; errcode_t retval; - int clen, i, inodes_per_block; - unsigned int length; + int clen, i, inodes_per_block, length; io_channel io; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -503,10 +516,13 @@ errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, return retval; } /* Check to see if it's in the inode cache */ - for (i=0; i < fs->icache->cache_size; i++) { - if (fs->icache->cache[i].ino == ino) { - *inode = fs->icache->cache[i].inode; - return 0; + if (bufsize == sizeof(struct ext2_inode)) { + /* only old good inode can be retrieve from the cache */ + for (i=0; i < fs->icache->cache_size; i++) { + if (fs->icache->cache[i].ino == ino) { + *inode = fs->icache->cache[i].inode; + return 0; + } } } if ((ino == 0) || (ino > fs->super->s_inodes_count)) @@ -529,43 +545,41 @@ errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, block; io = fs->io; } - if (block_nr != fs->icache->buffer_blk) { - retval = io_channel_read_blk(io, block_nr, 1, - fs->icache->buffer); - if (retval) - return retval; - fs->icache->buffer_blk = block_nr; - } offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); - ptr = ((char *) fs->icache->buffer) + (unsigned) offset; - memset(inode, 0, sizeof(struct ext2_inode)); length = EXT2_INODE_SIZE(fs->super); - if (length > sizeof(struct ext2_inode)) - length = sizeof(struct ext2_inode); - - if ((offset + length) > (unsigned) EXT2_BLOCK_SIZE(fs->super)) { - clen = (int) (EXT2_BLOCK_SIZE(fs->super) - offset); - memcpy((char *) inode, ptr, clen); - length -= clen; - - retval = io_channel_read_blk(io, block_nr+1, 1, - fs->icache->buffer); - if (retval) { - fs->icache->buffer_blk = 0; - return retval; + if (bufsize < length) + length = bufsize; + + ptr = (char *) inode; + while (length) { + clen = length; + if ((offset + length) > fs->blocksize) + clen = fs->blocksize - offset; + + if (block_nr != fs->icache->buffer_blk) { + retval = io_channel_read_blk(io, block_nr, 1, + fs->icache->buffer); + if (retval) + return retval; + fs->icache->buffer_blk = block_nr; } - fs->icache->buffer_blk = block_nr+1; - - memcpy(((char *) inode) + clen, - fs->icache->buffer, length); - } else - memcpy((char *) inode, ptr, length); - + + memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, + clen); + + offset = 0; + length -= clen; + ptr += clen; + block_nr++; + } + #ifdef EXT2FS_ENABLE_SWAPFS if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - ext2fs_swap_inode(fs, inode, inode, 0); + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode, + (struct ext2_inode_large *) inode, + 0, length); #endif /* Update the inode cache */ @@ -577,15 +591,21 @@ errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, return 0; } -errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode) +errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode) +{ + return ext2fs_read_inode_full(fs, ino, inode, + sizeof(struct ext2_inode)); +} + +errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize) { unsigned long group, block, block_nr, offset; - errcode_t retval; - struct ext2_inode temp_inode; + errcode_t retval = 0; + struct ext2_inode_large temp_inode, *w_inode; char *ptr; - int clen, i; - unsigned int length; + int clen, i, length; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -616,13 +636,27 @@ errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, if ((ino == 0) || (ino > fs->super->s_inodes_count)) return EXT2_ET_BAD_INODE_NUM; + length = bufsize; + if (length < EXT2_INODE_SIZE(fs->super)) + length = EXT2_INODE_SIZE(fs->super); + + if (length > (int) sizeof(struct ext2_inode_large)) { + w_inode = malloc(length); + if (!w_inode) + return ENOMEM; + } else + w_inode = &temp_inode; + memset(w_inode, 0, length); + #ifdef EXT2FS_ENABLE_SWAPFS if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) - ext2fs_swap_inode(fs, &temp_inode, inode, 1); + ext2fs_swap_inode_full(fs, w_inode, + (struct ext2_inode_large *) inode, + 1, bufsize); else #endif - memcpy(&temp_inode, inode, sizeof(struct ext2_inode)); + memcpy(w_inode, inode, bufsize); group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * @@ -631,54 +665,57 @@ errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, 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; + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); - ptr = (char *) fs->icache->buffer + (unsigned) offset; length = EXT2_INODE_SIZE(fs->super); - clen = length; - if (length > sizeof(struct ext2_inode)) - length = sizeof(struct ext2_inode); - - if (fs->icache->buffer_blk != block_nr) { - retval = io_channel_read_blk(fs->io, block_nr, 1, - fs->icache->buffer); - if (retval) - return retval; - fs->icache->buffer_blk = block_nr; - } - - if ((offset + length) > (unsigned) EXT2_BLOCK_SIZE(fs->super)) { - clen = (int) (EXT2_BLOCK_SIZE(fs->super) - offset); - length -= clen; - } else { - length = 0; - } - memcpy(ptr, &temp_inode, clen); - retval = io_channel_write_blk(fs->io, block_nr, 1, fs->icache->buffer); - if (retval) - return retval; + if (length > bufsize) + length = bufsize; - if (length) { - retval = io_channel_read_blk(fs->io, ++block_nr, 1, - fs->icache->buffer); - if (retval) { - fs->icache->buffer_blk = 0; - return retval; + ptr = (char *) w_inode; + + while (length) { + clen = length; + if ((offset + length) > fs->blocksize) + clen = fs->blocksize - offset; + + if (fs->icache->buffer_blk != block_nr) { + retval = io_channel_read_blk(fs->io, block_nr, 1, + fs->icache->buffer); + if (retval) + goto errout; + fs->icache->buffer_blk = block_nr; } - fs->icache->buffer_blk = block_nr; - memcpy(fs->icache->buffer, ((char *) &temp_inode) + clen, - length); - retval = io_channel_write_blk(fs->io, block_nr, 1, + + memcpy((char *) fs->icache->buffer + (unsigned) offset, + ptr, clen); + + retval = io_channel_write_blk(fs->io, block_nr, 1, fs->icache->buffer); if (retval) - return retval; + goto errout; + + offset = 0; + ptr += clen; + length -= clen; + block_nr++; } - + fs->flags |= EXT2_FLAG_CHANGED; - return 0; +errout: + if (w_inode && w_inode != &temp_inode) + free(w_inode); + return retval; } +errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + return ext2fs_write_inode_full(fs, ino, inode, + sizeof(struct ext2_inode)); +} + errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks) { struct ext2_inode inode; diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index f3c07e4..9081701 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -13,10 +13,12 @@ #if HAVE_UNISTD_H #include #endif +#include #include #include "ext2_fs.h" #include "ext2fs.h" +#include #ifdef EXT2FS_ENABLE_SWAPFS void ext2fs_swap_super(struct ext2_super_block * sb) @@ -78,12 +80,53 @@ void ext2fs_swap_group_desc(struct ext2_group_desc *gdp) gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count); } -void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, - struct ext2_inode *f, int hostorder) +void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header) +{ + struct ext2_ext_attr_header *from_header = + (struct ext2_ext_attr_header *)from; + struct ext2_ext_attr_header *to_header = + (struct ext2_ext_attr_header *)to; + struct ext2_ext_attr_entry *from_entry, *to_entry; + char *from_end = (char *)from_header + bufsize; + int n; + + if (to_header != from_header) + memcpy(to_header, from_header, bufsize); + + from_entry = (struct ext2_ext_attr_entry *)from_header; + to_entry = (struct ext2_ext_attr_entry *)to_header; + + if (has_header) { + to_header->h_magic = ext2fs_swab32(from_header->h_magic); + to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); + to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); + for (n=0; n<4; n++) + to_header->h_reserved[n] = + ext2fs_swab32(from_header->h_reserved[n]); + from_entry = (struct ext2_ext_attr_entry *)(from_header+1); + to_entry = (struct ext2_ext_attr_entry *)(to_header+1); + } + + while ((char *)from_entry < from_end && *(__u32 *)from_entry) { + to_entry->e_value_offs = + ext2fs_swab16(from_entry->e_value_offs); + to_entry->e_value_block = + ext2fs_swab32(from_entry->e_value_block); + to_entry->e_value_size = + ext2fs_swab32(from_entry->e_value_size); + from_entry = EXT2_EXT_ATTR_NEXT(from_entry); + to_entry = EXT2_EXT_ATTR_NEXT(to_entry); + } +} + +void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, + struct ext2_inode_large *f, int hostorder, + int bufsize) { unsigned i; int islnk = 0; - + __u32 *eaf, *eat; + if (hostorder && LINUX_S_ISLNK(f->i_mode)) islnk = 1; t->i_mode = ext2fs_swab16(f->i_mode); @@ -101,7 +144,7 @@ void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, t->i_flags = ext2fs_swab32(f->i_flags); t->i_file_acl = ext2fs_swab32(f->i_file_acl); t->i_dir_acl = ext2fs_swab32(f->i_dir_acl); - if (!islnk || ext2fs_inode_data_blocks(fs, t)) { + if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) { for (i = 0; i < EXT2_N_BLOCKS; i++) t->i_block[i] = ext2fs_swab32(f->i_block[i]); } else if (t != f) { @@ -151,5 +194,44 @@ void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]); break; } + + if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) + return; /* no i_extra_isize field */ + + t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); + if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) - + sizeof(struct ext2_inode)) { + /* this is error case: i_extra_size is too large */ + return; + } + + i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32); + if (bufsize < (int) i) + return; /* no space for EA magic */ + + eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + + f->i_extra_isize); + + if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC) + return; /* it seems no magic here */ + + eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + + f->i_extra_isize); + *eat = ext2fs_swab32(*eaf); + + /* convert EA(s) */ + ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), + bufsize - sizeof(struct ext2_inode) - + t->i_extra_isize - sizeof(__u32), 0); + } + +void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, + struct ext2_inode *f, int hostorder) +{ + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t, + (struct ext2_inode_large *) f, hostorder, + sizeof(struct ext2_inode)); +} + #endif -- 1.8.3.1