> But then you just make sure that the little-endian bits are the same, and > now you're *done*. Yes, you're perfectly right. Sorry for not getting it. I hope the next time I will understand faster. > > For little endian machines, the data arranged in the following way: > > > > |o02.o01.n06.n05.n04.n03.n02.n01|o10.o09.o08.o07.o06.o05.o04.o03| > > |o18.o17.o16.o15.o14.o13.o12.o11|o26.o25.o24.o23.o22.o21.o20.o19| > > That's a singularly confused way or looking at it. Yep. I saw everything with big-endian eyes and confused myself. Shouldn't have happened. > Yes it does. Try it. I tried it. It does it. Here's the new patch (hopefully the last one for this issue)... Checked with sparse using C=2 and CF="-D__CHECK_ENDIAN__". Tested on an i386 box. Tested on an Ultrasparc IIi box. Signed-off-by: Andi Drebes <andi@xxxxxxxxxxxxxxxxxxx> --- fs/cramfs/inode.c | 119 ++++++++++++++++++++++++++++++--------------- include/linux/cramfs_fs.h | 22 ++++---- 2 files changed, 91 insertions(+), 50 deletions(-) diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 350680f..30dc640 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -4,6 +4,10 @@ * Copyright (C) 1999 Linus Torvalds. * * This file is released under the GPL. + * + * Changelog: + * 11/07 - Andi Drebes <andi@xxxxxxxxxxxxxxxxxxx> + * Made cramfs little endian only. */ /* @@ -34,13 +38,46 @@ static const struct address_space_operations cramfs_aops; static DEFINE_MUTEX(read_mutex); +#define CRAMFS_NAMELEN_MASK ((1ul << CRAMFS_NAMELEN_WIDTH)-1) +#define CRAMFS_MODE_MASK ((1ul << CRAMFS_MODE_WIDTH)-1) +#define CRAMFS_SIZE_MASK ((1ul << CRAMFS_SIZE_WIDTH)-1) + +static inline u32 cramfs_mode(struct cramfs_inode *inode) +{ + return le32_to_cpu(inode->mode_uid) & CRAMFS_MODE_MASK; +} + +static inline u32 cramfs_uid(struct cramfs_inode *inode) +{ + return le32_to_cpu(inode->mode_uid) >> CRAMFS_MODE_WIDTH; +} + +static inline u32 cramfs_size(struct cramfs_inode *inode) +{ + return le32_to_cpu(inode->size_gid) & CRAMFS_SIZE_MASK; +} + +static inline u32 cramfs_gid(struct cramfs_inode *inode) +{ + return le32_to_cpu(inode->size_gid) >> CRAMFS_SIZE_WIDTH; +} + +static inline u32 cramfs_offset(struct cramfs_inode *inode) +{ + return le32_to_cpu(inode->namelen_offset) >> CRAMFS_NAMELEN_WIDTH; +} + +static inline u32 cramfs_namelen(struct cramfs_inode *inode) +{ + return le32_to_cpu(inode->namelen_offset) & CRAMFS_NAMELEN_MASK; +} /* These two macros may change in future, to provide better st_ino semantics. */ -#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1) +#define CRAMINO(x) ((cramfs_offset(x) && cramfs_size(x)) ? \ + cramfs_offset(x) << 2 : 1) #define OFFSET(x) ((x)->i_ino) - static int cramfs_iget5_test(struct inode *inode, void *opaque) { struct cramfs_inode *cramfs_inode = opaque; @@ -53,13 +90,13 @@ static int cramfs_iget5_test(struct inode *inode, void *opaque) /* all empty directories, char, block, pipe, and sock, share inode #1 */ - if ((inode->i_mode != cramfs_inode->mode) || - (inode->i_gid != cramfs_inode->gid) || - (inode->i_uid != cramfs_inode->uid)) + if ((inode->i_mode != cramfs_mode(cramfs_inode)) || + (inode->i_gid != cramfs_gid(cramfs_inode)) || + (inode->i_uid != cramfs_uid(cramfs_inode))) return 0; /* does not match */ if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) && - (inode->i_rdev != old_decode_dev(cramfs_inode->size))) + (inode->i_rdev != old_decode_dev(cramfs_size(cramfs_inode)))) return 0; /* does not match */ return 1; /* matches */ @@ -69,11 +106,11 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque) { static struct timespec zerotime; struct cramfs_inode *cramfs_inode = opaque; - inode->i_mode = cramfs_inode->mode; - inode->i_uid = cramfs_inode->uid; - inode->i_size = cramfs_inode->size; - inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; - inode->i_gid = cramfs_inode->gid; + inode->i_mode = cramfs_mode(cramfs_inode); + inode->i_uid = cramfs_uid(cramfs_inode); + inode->i_size = cramfs_size(cramfs_inode); + inode->i_blocks = (cramfs_size(cramfs_inode) - 1) / 512 + 1; + inode->i_gid = cramfs_gid(cramfs_inode); /* Struct copy intentional */ inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; inode->i_ino = CRAMINO(cramfs_inode); @@ -94,7 +131,7 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque) inode->i_size = 0; inode->i_blocks = 0; init_special_inode(inode, inode->i_mode, - old_decode_dev(cramfs_inode->size)); + old_decode_dev(cramfs_size(cramfs_inode))); } return 0; } @@ -256,53 +293,57 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) mutex_unlock(&read_mutex); /* Do sanity checks on the superblock */ - if (super.magic != CRAMFS_MAGIC) { - /* check for wrong endianess */ - if (super.magic == CRAMFS_MAGIC_WEND) { - if (!silent) - printk(KERN_ERR "cramfs: wrong endianess\n"); - goto out; - } - + if (le32_to_cpu(super.magic) != CRAMFS_MAGIC && + le32_to_cpu(super.magic) != CRAMFS_MAGIC_WEND) { /* check at 512 byte offset */ mutex_lock(&read_mutex); memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super)); mutex_unlock(&read_mutex); - if (super.magic != CRAMFS_MAGIC) { - if (super.magic == CRAMFS_MAGIC_WEND && !silent) - printk(KERN_ERR "cramfs: wrong endianess\n"); - else if (!silent) + + if (le32_to_cpu(super.magic) == CRAMFS_MAGIC_WEND) + goto other_endian; + else if (le32_to_cpu(super.magic) != CRAMFS_MAGIC) { + if (!silent) printk(KERN_ERR "cramfs: wrong magic\n"); + goto out; } } + /* check for wrong endianess */ + else if (le32_to_cpu(super.magic) == CRAMFS_MAGIC_WEND) { +other_endian: + if (!silent) + printk(KERN_ERR "cramfs: filesystems in big endian format are not supported any longer.\n"); + + goto out; + } /* get feature flags first */ - if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { + if (le32_to_cpu(super.flags) & ~CRAMFS_SUPPORTED_FLAGS) { printk(KERN_ERR "cramfs: unsupported filesystem features\n"); goto out; } /* Check that the root inode is in a sane state */ - if (!S_ISDIR(super.root.mode)) { + if (!S_ISDIR(cramfs_mode(&super.root))) { printk(KERN_ERR "cramfs: root is not a directory\n"); goto out; } - root_offset = super.root.offset << 2; - if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { - sbi->size=super.size; - sbi->blocks=super.fsid.blocks; - sbi->files=super.fsid.files; + root_offset = cramfs_offset(&super.root) << 2; + if (__le32_to_cpu(super.flags) & CRAMFS_FLAG_FSID_VERSION_2) { + sbi->size = le32_to_cpu(super.size); + sbi->blocks = le32_to_cpu(super.fsid.blocks); + sbi->files = le32_to_cpu(super.fsid.files); } else { sbi->size=1<<28; sbi->blocks=0; sbi->files=0; } - sbi->magic=super.magic; - sbi->flags=super.flags; + sbi->magic = le32_to_cpu(super.magic); + sbi->flags = le32_to_cpu(super.flags); if (root_offset == 0) printk(KERN_INFO "cramfs: empty filesystem"); - else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && + else if (!(le32_to_cpu(super.flags) & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && ((root_offset != sizeof(struct cramfs_super)) && (root_offset != 512 + sizeof(struct cramfs_super)))) { @@ -383,10 +424,10 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) * and the name padded out to 4-byte boundaries * with zeroes. */ - namelen = de->namelen << 2; + namelen = cramfs_namelen(de) << 2; memcpy(buf, name, namelen); ino = CRAMINO(de); - mode = de->mode; + mode = cramfs_mode(de); mutex_unlock(&read_mutex); nextoffset = offset + sizeof(*de) + namelen; for (;;) { @@ -432,7 +473,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s if (sorted && (dentry->d_name.name[0] < name[0])) break; - namelen = de->namelen << 2; + namelen = cramfs_namelen(de) << 2; offset += sizeof(*de) + namelen; /* Quick check that the name is roughly the right length */ @@ -484,8 +525,8 @@ static int cramfs_readpage(struct file *file, struct page * page) start_offset = OFFSET(inode) + maxblock*4; mutex_lock(&read_mutex); if (page->index) - start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4); - compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); + start_offset = le32_to_cpu(*(__le32 *) cramfs_read(sb, blkptr_offset-4, 4)); + compr_len = le32_to_cpu(*(__le32 *) cramfs_read(sb, blkptr_offset, 4)) - start_offset; mutex_unlock(&read_mutex); pgdata = kmap(page); if (compr_len == 0) diff --git a/include/linux/cramfs_fs.h b/include/linux/cramfs_fs.h index 3be4e5a..66aba06 100644 --- a/include/linux/cramfs_fs.h +++ b/include/linux/cramfs_fs.h @@ -28,9 +28,9 @@ * Reasonably terse representation of the inode data. */ struct cramfs_inode { - __u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH; + __le32 mode_uid; /* SIZE for device files is i_rdev */ - __u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH; + __le32 size_gid; /* NAMELEN is the length of the file name, divided by 4 and rounded up. (cramfs doesn't support hard links.) */ /* OFFSET: For symlinks and non-empty regular files, this @@ -39,24 +39,24 @@ struct cramfs_inode { see README). For non-empty directories it is the offset (divided by 4) of the inode of the first file in that directory. For anything else, offset is zero. */ - __u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH; + __le32 namelen_offset; }; struct cramfs_info { - __u32 crc; - __u32 edition; - __u32 blocks; - __u32 files; + __le32 crc; + __le32 edition; + __le32 blocks; + __le32 files; }; /* * Superblock information at the beginning of the FS. */ struct cramfs_super { - __u32 magic; /* 0x28cd3d45 - random number */ - __u32 size; /* length in bytes */ - __u32 flags; /* feature flags */ - __u32 future; /* reserved for future use */ + __le32 magic; /* 0x28cd3d45 - random number */ + __le32 size; /* length in bytes */ + __le32 flags; /* feature flags */ + __le32 future; /* reserved for future use */ __u8 signature[16]; /* "Compressed ROMFS" */ struct cramfs_info fsid; /* unique filesystem info */ __u8 name[16]; /* user-defined name */ - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html