The following patch makes cramfs little endian only.
When trying to mount a big endian image, an error message is produced.

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 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 <[EMAIL PROTECTED]>
+ *     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 */
-- 
1.5.1.53.g77e6f

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to