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]>
---
 inode.c |  163 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 136 insertions(+), 27 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 350680f..3fbf567 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.
  */
 
 /*
@@ -40,6 +44,95 @@ static DEFINE_MUTEX(read_mutex);
 #define CRAMINO(x)     (((x)->offset && (x)->size)?(x)->offset<<2:1)
 #define OFFSET(x)      ((x)->i_ino)
 
+#ifdef __BIG_ENDIAN
+/* Converts a cramfs_info from little endian to big endian. */
+static inline void cramfs_convert_info_letobe(struct cramfs_info* info)
+{
+        info->crc = swab32(info->crc);
+        info->edition = swab32(info->edition);
+        info->blocks = swab32(info->blocks);
+        info->files = swab32(info->files);
+}
+
+/* Converts a cramfs_info from little endian to big endian. */
+static inline void cramfs_convert_inode_letobe(struct cramfs_inode* inode)
+{
+       u8* inode_bytes = (u8*)inode;
+       u8 old_nloffs[4];
+
+       inode->mode = swab16(inode->mode);
+       inode->uid = swab16(inode->uid);
+       inode->size = (inode_bytes[6] << 16) | (inode_bytes[5] << 8) | 
(inode_bytes[4]);
+
+       /* Save the old values of the namelength and the offset */
+       memcpy(old_nloffs, inode_bytes+8, 4);
+
+       /* Convert the namelength and the offset */
+       inode_bytes[8] = ((old_nloffs[0] & 0x3f) << 2) | ((old_nloffs[3] & 
0xc0) >> 6);
+       inode_bytes[9] = ((old_nloffs[3] & 0x3f) << 2) | ((old_nloffs[2] & 
0xc0) >> 6);
+       inode_bytes[10] = ((old_nloffs[2] & 0x3f) << 2) | ((old_nloffs[1] & 
0xc0) >> 6);
+       inode_bytes[11] = ((old_nloffs[1] & 0x3f) << 2) | ((old_nloffs[0] & 
0xc0) >> 6);
+}
+
+/* Converts a cramfs superblock from little endian to big endian. */
+static inline void cramfs_convert_super_letobe(struct cramfs_super* super)
+{
+       super->magic = swab32(super->magic);
+       super->size = swab32(super->size);
+       super->flags = swab32(super->flags);
+       super->future = swab32(super->future);
+       cramfs_convert_info_letobe(&super->fsid);
+       cramfs_convert_inode_letobe(&super->root);
+}
+
+/* Converts a 32 bit integer from little endian to big endian */
+static inline u32 cramfs_convert_u32_letobe(u32 val)
+{
+       return swab32(val);
+}
+
+static inline void cramfs_info_to_host(struct cramfs_info *info)
+{
+       cramfs_convert_info_letobe(info);
+}
+
+static inline void cramfs_inode_to_host(struct cramfs_inode *inode)
+{
+       cramfs_convert_inode_letobe(inode);
+}
+
+static inline void cramfs_super_to_host(struct cramfs_super *super)
+{
+       cramfs_convert_super_letobe(super);
+}
+
+static inline u32 cramfs_u32_to_host(u32 val)
+{
+       return cramfs_convert_u32_letobe(val);
+}
+
+#elif defined(__LITTLE_ENDIAN)
+
+static inline void cramfs_info_to_host(struct cramfs_info *info)
+{
+}
+
+static inline void cramfs_inode_to_host(struct cramfs_inode *inode)
+{
+}
+
+static inline void cramfs_super_to_host(struct cramfs_super *super)
+{
+}
+
+static inline u32 cramfs_u32_to_host(u32 val)
+{
+       return val;
+}
+
+#else
+#error "Neither __BIG_ENDIAN nor __LITTLE_ENDIAN defined."
+#endif
 
 static int cramfs_iget5_test(struct inode *inode, void *opaque)
 {
@@ -253,29 +346,35 @@ static int cramfs_fill_super(struct super_block *sb, void 
*data, int silent)
 
        /* Read the first block and get the superblock from it */
        memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
+       cramfs_super_to_host(&super);
        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 (super.magic != CRAMFS_MAGIC && super.magic != CRAMFS_MAGIC_WEND) {
                /* check at 512 byte offset */
                mutex_lock(&read_mutex);
                memcpy(&super, cramfs_read(sb, 512, sizeof(super)), 
sizeof(super));
+               cramfs_super_to_host(&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 (super.magic == CRAMFS_MAGIC_WEND) {
+                       goto other_endian;
+               }
+               else if (super.magic != CRAMFS_MAGIC) {
+                       if (!silent)
                                printk(KERN_ERR "cramfs: wrong magic\n");
+
                        goto out;
                }
        }
+       /* check for wrong endianess */
+       else if (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) {
@@ -367,7 +466,8 @@ static int cramfs_readdir(struct file *filp, void *dirent, 
filldir_t filldir)
 
        copied = 0;
        while (offset < inode->i_size) {
-               struct cramfs_inode *de;
+               void *inode_data;
+               struct cramfs_inode de;
                unsigned long nextoffset;
                char *name;
                ino_t ino;
@@ -375,20 +475,22 @@ static int cramfs_readdir(struct file *filp, void 
*dirent, filldir_t filldir)
                int namelen, error;
 
                mutex_lock(&read_mutex);
-               de = cramfs_read(sb, OFFSET(inode) + offset, 
sizeof(*de)+CRAMFS_MAXPATHLEN);
-               name = (char *)(de+1);
+               inode_data = cramfs_read(sb, OFFSET(inode) + offset, 
sizeof(de)+CRAMFS_MAXPATHLEN);
+               memcpy(&de, inode_data, sizeof(de));
+               name = inode_data+sizeof(de);
+               cramfs_inode_to_host(&de);
 
                /*
                 * Namelengths on disk are shifted by two
                 * and the name padded out to 4-byte boundaries
                 * with zeroes.
                 */
-               namelen = de->namelen << 2;
+               namelen = de.namelen << 2;
                memcpy(buf, name, namelen);
-               ino = CRAMINO(de);
-               mode = de->mode;
+               ino = CRAMINO(&de);
+               mode = de.mode;
                mutex_unlock(&read_mutex);
-               nextoffset = offset + sizeof(*de) + namelen;
+               nextoffset = offset + sizeof(de) + namelen;
                for (;;) {
                        if (!namelen) {
                                kfree(buf);
@@ -421,19 +523,22 @@ static struct dentry * cramfs_lookup(struct inode *dir, 
struct dentry *dentry, s
        mutex_lock(&read_mutex);
        sorted = CRAMFS_SB(dir->i_sb)->flags & CRAMFS_FLAG_SORTED_DIRS;
        while (offset < dir->i_size) {
-               struct cramfs_inode *de;
+               void* inode_data;
+               struct cramfs_inode de;
                char *name;
                int namelen, retval;
 
-               de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, 
sizeof(*de)+CRAMFS_MAXPATHLEN);
-               name = (char *)(de+1);
+               inode_data = cramfs_read(dir->i_sb, OFFSET(dir) + offset, 
sizeof(de)+CRAMFS_MAXPATHLEN);
+               memcpy(&de, inode_data, sizeof(de));
+               name = (char *)(inode_data+sizeof(de));
+               cramfs_inode_to_host(&de);
 
                /* Try to take advantage of sorted directories */
                if (sorted && (dentry->d_name.name[0] < name[0]))
                        break;
 
-               namelen = de->namelen << 2;
-               offset += sizeof(*de) + namelen;
+               namelen = de.namelen << 2;
+               offset += sizeof(de) + namelen;
 
                /* Quick check that the name is roughly the right length */
                if (((dentry->d_name.len + 3) & ~3) != namelen)
@@ -454,7 +559,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, 
struct dentry *dentry, s
                if (retval > 0)
                        continue;
                if (!retval) {
-                       struct cramfs_inode entry = *de;
+                       struct cramfs_inode entry = de;
                        mutex_unlock(&read_mutex);
                        d_add(dentry, get_cramfs_inode(dir->i_sb, &entry));
                        return NULL;
@@ -483,9 +588,13 @@ static int cramfs_readpage(struct file *file, struct page 
* page)
 
                start_offset = OFFSET(inode) + maxblock*4;
                mutex_lock(&read_mutex);
-               if (page->index)
+               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 = cramfs_u32_to_host(start_offset);
+               }
+
+               compr_len = cramfs_u32_to_host(*(u32 *) cramfs_read(sb, 
blkptr_offset, 4)) - start_offset;
+
                mutex_unlock(&read_mutex);
                pgdata = kmap(page);
                if (compr_len == 0)
-
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