bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

OT: Fixed Roland'd Hurd EA ext2 patch for Linux


From: cascardo
Subject: OT: Fixed Roland'd Hurd EA ext2 patch for Linux
Date: Sun, 29 Jan 2006 00:29:02 -0200
User-agent: Mutt/1.5.6+20040907i

A fixed patch for supporting passive translators in Linux follows.

This is a simple fix of the latest Roland's patch. Since I fixed the
patch by hand, don't expect it to apply cleanly (it wouldn't anyway in
linux 2.6.14) and tell me if there is any problem with it.

Besides including a comment in the header with my name and the date of
change (as required by GPL) in the section of the patch the refers to
the only file that was needed to change, the fix was too much simple.

Since many applications (as I am usually lucky, my test one did it
too) get the size of the list of attributes before really retrieving
them, passing a NULL buffer to the syscall, they all got a 0 length
list, since the code only would substract the size (actually add) of
the attribute name if the buffer was not a NULL pointer. I have only
moved this substraction outside an if block. (Two of them, in
fact. One for the author and one for the translator attribute.)

So, here it is. The description above should enable anyone to fix it
perself.


--- linux-2.6/fs/Kconfig
+++ linux-2.6/fs/Kconfig
@@ -26,6 +26,14 @@ config EXT2_FS_XATTR
 
          If unsure, say N.
 
+config EXT2_FS_XATTR_HURD
+       bool "Ext2 GNU/Hurd special attribute support"
+       depends on EXT2_FS_XATTR
+       default y
+       help
+         Enable access to gnu.* extended attribute names on ext2 filesystems
+         created for use with the GNU/Hurd operating system.
+
 config EXT2_FS_POSIX_ACL
        bool "Ext2 POSIX Access Control Lists"
        depends on EXT2_FS_XATTR
--- linux-2.6/fs/ext2/Makefile
+++ linux-2.6/fs/ext2/Makefile
@@ -11,3 +11,4 @@ ext2-$(CONFIG_EXT2_FS_XATTR)   += xattr.o
 ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o
 ext2-$(CONFIG_EXT2_FS_SECURITY)         += xattr_security.o
 ext2-$(CONFIG_EXT2_FS_XIP)      += xip.o
+ext2-$(CONFIG_EXT2_FS_XATTR_HURD)+= xattr_hurd.o
--- linux-2.6/fs/ext2/ext2.h
+++ linux-2.6/fs/ext2/ext2.h
@@ -64,6 +64,10 @@ struct ext2_inode_info {
        struct posix_acl        *i_acl;
        struct posix_acl        *i_default_acl;
 #endif
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       __u32   i_hurd_translator;
+       __u32   i_hurd_author;
+#endif
        rwlock_t i_meta_lock;
        struct inode    vfs_inode;
 };
--- linux-2.6/fs/ext2/ialloc.c
+++ linux-2.6/fs/ext2/ialloc.c
@@ -590,6 +590,10 @@ got:
        ei->i_frag_size = 0;
        ei->i_file_acl = 0;
        ei->i_dir_acl = 0;
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       ei->i_hurd_translator = 0;
+       ei->i_hurd_author = inode->i_uid;
+#endif
        ei->i_dtime = 0;
        ei->i_block_group = group;
        ei->i_next_alloc_block = 0;
--- linux-2.6/fs/ext2/inode.c
+++ linux-2.6/fs/ext2/inode.c
@@ -1118,6 +1118,16 @@ void ext2_read_inode (struct inode * ino
        ei->i_prealloc_count = 0;
        ei->i_block_group = (ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
        ei->i_dir_start_lookup = 0;
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (EXT2_SB(inode->i_sb)->s_es->s_creator_os == 
cpu_to_le32(EXT2_OS_HURD)) {
+               ei->i_hurd_translator = 
le32_to_cpu(raw_inode->osd1.hurd1.h_i_translator);
+               ei->i_hurd_author = 
le32_to_cpu(raw_inode->osd2.hurd2.h_i_author);
+       }
+       else {
+               ei->i_hurd_translator = 0;
+               ei->i_hurd_author = inode->i_uid;
+       }
+#endif
 
        /*
         * NOTE! The in-memory inode i_data array is in little-endian order
@@ -1248,7 +1258,14 @@ static int ext2_update_inode(struct inod
                        }
                }
        }
-       
+
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (EXT2_SB(inode->i_sb)->s_es->s_creator_os == 
cpu_to_le32(EXT2_OS_HURD)) {
+               raw_inode->osd1.hurd1.h_i_translator = 
cpu_to_le32(ei->i_hurd_translator);
+               raw_inode->osd2.hurd2.h_i_author = 
cpu_to_le32(ei->i_hurd_author);
+       }
+#endif
+
        raw_inode->i_generation = cpu_to_le32(inode->i_generation);
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
                if (old_valid_dev(inode->i_rdev)) {
--- linux-2.6/fs/ext2/xattr.c
+++ linux-2.6/fs/ext2/xattr.c
@@ -10,3 +10,6 @@
 *  Red Hat Inc.
 *
 * Copyright 2006 Thadeu Lima de Souza Cascardo
 * 2006/01/29: fixed Hurd compatible attribute listin
 *
 */
@@ -110,6 +110,9 @@ static struct xattr_handler *ext2_xattr_
 #ifdef CONFIG_EXT2_FS_SECURITY
        [EXT2_XATTR_INDEX_SECURITY]          = &ext2_xattr_security_handler,
 #endif
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       [EXT2_XATTR_INDEX_HURD]              = &ext2_xattr_hurd_handler,
+#endif
 };
 
 struct xattr_handler *ext2_xattr_handlers[] = {
@@ -122,6 +125,9 @@ struct xattr_handler *ext2_xattr_handler
 #ifdef CONFIG_EXT2_FS_SECURITY
        &ext2_xattr_security_handler,
 #endif
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       &ext2_xattr_hurd_handler,
+#endif
        NULL
 };
 
@@ -316,6 +322,42 @@ bad_block: ext2_error(inode->i_sb, "ext2
        error = buffer_size - rest;  /* total size */
 
 cleanup:
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (error >= 0 && (EXT2_SB(inode->i_sb)->s_es->s_creator_os
+                          == cpu_to_le32(EXT2_OS_HURD))) {
+               struct ext2_inode_info *ei = EXT2_I(inode);
+               size_t size;
+               const char *name;
+               if (ei->i_hurd_author != inode->i_uid) {
+                       name = "gnu.author";
+                       size = sizeof "gnu.author";
+                       if (buffer) {
+                               if (size > rest) {
+                                       error = -ERANGE;
+                               } else {
+                                       memcpy(buffer, name, size);
+                                       buffer += size;
+                               }
+                       }
+                       rest -= size;
+               }
+               if (ei->i_hurd_translator != 0) {
+                       name = "gnu.translator";
+                       size = sizeof "gnu.translator";
+                       if (buffer) {
+                               if (size > rest) {
+                                       error = -ERANGE;
+                               } else {
+                                       memcpy(buffer, name, size);
+                                       buffer += size;
+                               }
+                       }
+                       rest -= size;
+               }
+               if (error >= 0)
+                       error = buffer_size - rest;  /* total size */
+       }
+#endif
        brelse(bh);
        up_read(&EXT2_I(inode)->xattr_sem);
 
@@ -812,6 +854,12 @@ ext2_xattr_delete_inode(struct inode *in
 
 cleanup:
        brelse(bh);
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (EXT2_I(inode)->i_hurd_translator != 0) {
+               ext2_free_blocks(inode, EXT2_I(inode)->i_hurd_translator, 1);
+               EXT2_I(inode)->i_hurd_translator = 0;
+       }
+#endif
        up_write(&EXT2_I(inode)->xattr_sem);
 }
 
--- linux-2.6/fs/ext2/xattr.h
+++ linux-2.6/fs/ext2/xattr.h
@@ -23,6 +23,7 @@
 #define EXT2_XATTR_INDEX_TRUSTED               4
 #define        EXT2_XATTR_INDEX_LUSTRE                 5
 #define EXT2_XATTR_INDEX_SECURITY              6
+#define EXT2_XATTR_INDEX_HURD                  7
 
 struct ext2_xattr_header {
        __le32  h_magic;        /* magic number for identification */
@@ -61,6 +62,7 @@ extern struct xattr_handler ext2_xattr_t
 extern struct xattr_handler ext2_xattr_acl_access_handler;
 extern struct xattr_handler ext2_xattr_acl_default_handler;
 extern struct xattr_handler ext2_xattr_security_handler;
+extern struct xattr_handler ext2_xattr_hurd_handler;
 
 extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
 
--- linux-2.6//dev/null
+++ linux-2.6/fs/ext2/xattr_hurd.c
@@ -0,0 +1,273 @@
+/*
+ * linux/fs/ext2/xattr_hurd.c
+ * Handler for Hurd-specific attributes.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/buffer_head.h>
+#include "ext2.h"
+#include "xattr.h"
+
+#define XATTR_HURD_PREFIX "gnu."
+
+/*
+ * This gets called only when EXT2_XATTR_INDEX_HURD appears in xattr data
+ * on disk.  The compatibility pseudo-attributes for EXT2_OS_HURD format
+ * filesystems is handled in ext2_xattr_list specially.
+ */
+static size_t
+ext2_xattr_hurd_list(struct inode *inode, char *list, size_t list_size,
+                    const char *name, size_t name_len)
+{
+       const size_t prefix_len = sizeof(XATTR_HURD_PREFIX)-1;
+       const size_t total_len = prefix_len + name_len + 1;
+
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return 0;
+
+       if (list && total_len <= list_size) {
+               memcpy(list, XATTR_HURD_PREFIX, prefix_len);
+               memcpy(list+prefix_len, name, name_len);
+               list[prefix_len + name_len] = '\0';
+       }
+       return total_len;
+}
+
+/*
+ * A filesystem in EXT2_OS_HURD does not usually have normal xattr blocks.
+ * However, its inodes do have Hurd-specific information that we present
+ * as pseudo-attributes.
+ */
+static inline int
+IS_HURD_COMPAT(struct super_block *sb)
+{
+       return (EXT2_SB(sb)->s_es->s_creator_os == cpu_to_le32(EXT2_OS_HURD));
+}
+
+/*
+ * Report the "gnu.translator" and "gnu.author" attribute values
+ * from an inode in EXT2_OS_HURD format.
+ */
+static int
+hurd_compat_get(struct inode *inode, const char *name,
+               void *buffer, size_t size)
+{
+       int error = -EOPNOTSUPP;
+       struct ext2_inode_info *ei = EXT2_I(inode);
+
+       /*
+        * Compatibility mode.
+        */
+       if (!strcmp(name, "translator")) {
+               struct buffer_head *bh;
+               u16 len;
+               if (ei->i_hurd_translator == 0)
+                       /* No translator set, empty.  */
+                       return 0;
+               error = -EIO;
+               bh = sb_bread(inode->i_sb, ei->i_hurd_translator);
+               if (bh) {
+                       len = le16_to_cpup((const u16 *) bh->b_data);
+                       if (len > bh->b_size - 2)
+                               error = -EFBIG; /* ? */
+                       else if (buffer == NULL)
+                               /* Just return the total.  */
+                               error = len;
+                       else if (len > size)
+                               error = -ERANGE;
+                       else {
+                               memcpy(buffer, bh->b_data + 2, len);
+                               error = len;
+                       }
+                       brelse(bh);
+               }
+       }
+       else if (!strcmp(name, "author")) {
+               if (ei->i_hurd_author == inode->i_uid)
+                       error = 0;
+               else {
+                       if (buffer && size < sizeof ei->i_hurd_author)
+                               error = -ERANGE;
+                       else if (buffer)
+                               memcpy(buffer, &ei->i_hurd_author,
+                                      sizeof ei->i_hurd_author);
+                       error = sizeof ei->i_hurd_author;
+               }
+       }
+
+       return error;
+}
+
+/*
+ * Store the "gnu.translator" and "gnu.author" attribute values
+ * in an inode in EXT2_OS_HURD format.
+ */
+static int
+compat_hurd_set(struct inode *inode, const char *name,
+               const void *value, size_t size, int flags)
+{
+       int error;
+       struct ext2_inode_info *ei = EXT2_I(inode);
+
+       /*
+        * Compatibility mode.  We actually have to re-read the
+        * raw inode because ext2_read_inode does not cache this field.
+        */
+       if (!strcmp(name, "translator")) {
+               u32 bno;
+               u16 len;
+               struct buffer_head *bh;
+
+               error = permission(inode, MAY_WRITE, NULL);
+               if (error)
+                       return error;
+               if (ei->i_hurd_translator == 0) {
+                       /* No existing translator.  */
+                       if (flags & XATTR_REPLACE)
+                               return -ENODATA;
+                       if (size == 0) { /* Nothing really to do.  */
+                               inode->i_ctime = CURRENT_TIME;
+                               mark_inode_dirty(inode);
+                               return 0;
+                       }
+               }
+               else if (flags & XATTR_CREATE)
+                       return -EEXIST;
+
+               if (size == 0) { /* Removing translator.  */
+                       bno = ei->i_hurd_translator;
+                       ei->i_hurd_translator = 0;
+                       ext2_free_blocks(inode, bno, 1);
+                       unmap_underlying_metadata(inode->i_sb->s_bdev, bno);
+                       inode->i_ctime = CURRENT_TIME;
+                       mark_inode_dirty(inode);
+                       return 0;
+               }
+
+               if (size > inode->i_sb->s_blocksize - 2)
+                       return -ERANGE;
+
+               bno = ei->i_hurd_translator;
+               if (bno == 0) {
+                       /*
+                        * Need to allocate a new block.
+                        */
+                       struct super_block *sb = inode->i_sb;
+                       u32 goal = le32_to_cpu(EXT2_SB(sb)->s_es->
+                                              s_first_data_block) +
+                               EXT2_I(inode)->i_block_group *
+                               EXT2_BLOCKS_PER_GROUP(sb);
+                       bno = ext2_new_block(inode, goal, 0, 0, &error);
+                       if (error)
+                               return error;
+               }
+
+               bh = sb_getblk(inode->i_sb, bno);
+               lock_buffer(bh);
+               len = cpu_to_le16(size);
+               memcpy(bh->b_data, &len, sizeof len);
+               memcpy(bh->b_data + 2, value, size);
+               set_buffer_uptodate(bh);
+               unlock_buffer(bh);
+               mark_buffer_dirty(bh);
+               brelse(bh);
+
+               ei->i_hurd_translator = bno;
+               inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+               return 0;
+       }
+
+       if (!strcmp(name, "author")) {
+               error = permission(inode, MAY_WRITE, NULL);
+               if (error)
+                       return error;
+               switch (size) {
+               default:
+                       return -EINVAL;
+               case 0:
+                       ei->i_hurd_author = inode->i_uid;
+                       break;
+               case sizeof ei->i_hurd_author:
+                       memcpy(&ei->i_hurd_author,
+                              value, sizeof ei->i_hurd_author);
+                       break;
+               }
+               inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+               return 0;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+/*
+ * Access either pseudo-attributes from an EXT2_OS_HURD format filesystem,
+ * or normal xattrs stored on disk with the "gnu." prefix.  For the latter,
+ * we only let Linux users do it when they could do arbitrary user attributes.
+ */
+static int
+ext2_xattr_hurd_get(struct inode *inode, const char *name,
+                   void *buffer, size_t size)
+{
+       int error;
+
+       if (IS_HURD_COMPAT(inode->i_sb)) {
+               down_read(&EXT2_I(inode)->xattr_sem);
+               error = hurd_compat_get(inode, name, buffer, size);
+               up_read(&EXT2_I(inode)->xattr_sem);
+               if (error != -EOPNOTSUPP)
+                       return error;
+       }
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return -EOPNOTSUPP;
+       error = permission(inode, MAY_READ, NULL);
+       if (error)
+               return error;
+
+       return ext2_xattr_get(inode, EXT2_XATTR_INDEX_HURD, name,
+                             buffer, size);
+}
+
+static int
+ext2_xattr_hurd_set(struct inode *inode, const char *name,
+                   const void *value, size_t size, int flags)
+{
+       int error;
+
+       if (value == NULL)
+               size = 0;
+
+       if (IS_HURD_COMPAT(inode->i_sb)) {
+               down_write(&EXT2_I(inode)->xattr_sem);
+               error = compat_hurd_set(inode, name, value, size, flags);
+               up_write(&EXT2_I(inode)->xattr_sem);
+               if (error != -EOPNOTSUPP)
+                       return error;
+       }
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return -EOPNOTSUPP;
+       error = permission(inode, MAY_WRITE, NULL);
+       if (error)
+               return error;
+
+       return ext2_xattr_set(inode, EXT2_XATTR_INDEX_HURD, name,
+                             value, size, flags);
+}
+
+struct xattr_handler ext2_xattr_hurd_handler = {
+       .prefix = XATTR_HURD_PREFIX,
+       .list   = ext2_xattr_hurd_list,
+       .get    = ext2_xattr_hurd_get,
+       .set    = ext2_xattr_hurd_set,
+};

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]