diff options
Diffstat (limited to 'fs/hfsplus/xattr.c')
-rw-r--r-- | fs/hfsplus/xattr.c | 62 |
1 files changed, 56 insertions, 6 deletions
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index f66346155df5..bd8471fb9a6a 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -8,11 +8,16 @@ #include "hfsplus_fs.h" #include "xattr.h" +#include "acl.h" const struct xattr_handler *hfsplus_xattr_handlers[] = { &hfsplus_xattr_osx_handler, &hfsplus_xattr_user_handler, &hfsplus_xattr_trusted_handler, +#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL + &hfsplus_xattr_acl_access_handler, + &hfsplus_xattr_acl_default_handler, +#endif &hfsplus_xattr_security_handler, NULL }; @@ -46,11 +51,58 @@ static inline int is_known_namespace(const char *name) return true; } +static int can_set_system_xattr(struct inode *inode, const char *name, + const void *value, size_t size) +{ +#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL + struct posix_acl *acl; + int err; + + if (!inode_owner_or_capable(inode)) + return -EPERM; + + /* + * POSIX_ACL_XATTR_ACCESS is tied to i_mode + */ + if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) { + acl = posix_acl_from_xattr(&init_user_ns, value, size); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + err = posix_acl_equiv_mode(acl, &inode->i_mode); + posix_acl_release(acl); + if (err < 0) + return err; + mark_inode_dirty(inode); + } + /* + * We're changing the ACL. Get rid of the cached one + */ + forget_cached_acl(inode, ACL_TYPE_ACCESS); + + return 0; + } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) { + acl = posix_acl_from_xattr(&init_user_ns, value, size); + if (IS_ERR(acl)) + return PTR_ERR(acl); + posix_acl_release(acl); + + /* + * We're changing the default ACL. Get rid of the cached one + */ + forget_cached_acl(inode, ACL_TYPE_DEFAULT); + + return 0; + } +#endif /* CONFIG_HFSPLUS_FS_POSIX_ACL */ + return -EOPNOTSUPP; +} + static int can_set_xattr(struct inode *inode, const char *name, const void *value, size_t value_len) { if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return -EOPNOTSUPP; /* TODO: implement ACL support */ + return can_set_system_xattr(inode, name, value, value_len); if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) { /* @@ -253,11 +305,10 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len) return len; } -static ssize_t hfsplus_getxattr_finder_info(struct dentry *dentry, +static ssize_t hfsplus_getxattr_finder_info(struct inode *inode, void *value, size_t size) { ssize_t res = 0; - struct inode *inode = dentry->d_inode; struct hfs_find_data fd; u16 entry_type; u16 folder_rec_len = sizeof(struct DInfo) + sizeof(struct DXInfo); @@ -304,10 +355,9 @@ end_getxattr_finder_info: return res; } -ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, +ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, void *value, size_t size) { - struct inode *inode = dentry->d_inode; struct hfs_find_data fd; hfsplus_attr_entry *entry; __be32 xattr_record_type; @@ -333,7 +383,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, } if (!strcmp_xattr_finder_info(name)) - return hfsplus_getxattr_finder_info(dentry, value, size); + return hfsplus_getxattr_finder_info(inode, value, size); if (!HFSPLUS_SB(inode->i_sb)->attr_tree) return -EOPNOTSUPP; |