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, +};
signature.asc
Description: Digital signature
_______________________________________________ Bug-hurd mailing list Bug-hurd@gnu.org http://lists.gnu.org/mailman/listinfo/bug-hurd