linux/fs/hfsplus/posix_acl.c
<<
>>
Prefs
   1/*
   2 * linux/fs/hfsplus/posix_acl.c
   3 *
   4 * Vyacheslav Dubeyko <slava@dubeyko.com>
   5 *
   6 * Handler for Posix Access Control Lists (ACLs) support.
   7 */
   8
   9#include "hfsplus_fs.h"
  10#include "xattr.h"
  11#include "acl.h"
  12
  13struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
  14{
  15        struct posix_acl *acl;
  16        char *xattr_name;
  17        char *value = NULL;
  18        ssize_t size;
  19
  20        hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
  21
  22        switch (type) {
  23        case ACL_TYPE_ACCESS:
  24                xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
  25                break;
  26        case ACL_TYPE_DEFAULT:
  27                xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  28                break;
  29        default:
  30                return ERR_PTR(-EINVAL);
  31        }
  32
  33        size = __hfsplus_getxattr(inode, xattr_name, NULL, 0);
  34
  35        if (size > 0) {
  36                value = (char *)hfsplus_alloc_attr_entry();
  37                if (unlikely(!value))
  38                        return ERR_PTR(-ENOMEM);
  39                size = __hfsplus_getxattr(inode, xattr_name, value, size);
  40        }
  41
  42        if (size > 0)
  43                acl = posix_acl_from_xattr(&init_user_ns, value, size);
  44        else if (size == -ENODATA)
  45                acl = NULL;
  46        else
  47                acl = ERR_PTR(size);
  48
  49        hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
  50
  51        return acl;
  52}
  53
  54static int __hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
  55                                   int type)
  56{
  57        int err;
  58        char *xattr_name;
  59        size_t size = 0;
  60        char *value = NULL;
  61
  62        hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
  63
  64        switch (type) {
  65        case ACL_TYPE_ACCESS:
  66                xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
  67                break;
  68
  69        case ACL_TYPE_DEFAULT:
  70                xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  71                if (!S_ISDIR(inode->i_mode))
  72                        return acl ? -EACCES : 0;
  73                break;
  74
  75        default:
  76                return -EINVAL;
  77        }
  78
  79        if (acl) {
  80                size = posix_acl_xattr_size(acl->a_count);
  81                if (unlikely(size > HFSPLUS_MAX_INLINE_DATA_SIZE))
  82                        return -ENOMEM;
  83                value = (char *)hfsplus_alloc_attr_entry();
  84                if (unlikely(!value))
  85                        return -ENOMEM;
  86                err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
  87                if (unlikely(err < 0))
  88                        goto end_set_acl;
  89        }
  90
  91        err = __hfsplus_setxattr(inode, xattr_name, value, size, 0);
  92
  93end_set_acl:
  94        hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
  95
  96        if (!err)
  97                set_cached_acl(inode, type, acl);
  98
  99        return err;
 100}
 101
 102int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, int type)
 103{
 104        int err;
 105
 106        if (type == ACL_TYPE_ACCESS && acl) {
 107                err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 108                if (err)
 109                        return err;
 110        }
 111        return __hfsplus_set_posix_acl(inode, acl, type);
 112}
 113
 114int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
 115{
 116        int err = 0;
 117        struct posix_acl *default_acl, *acl;
 118
 119        hfs_dbg(ACL_MOD,
 120                "[%s]: ino %lu, dir->ino %lu\n",
 121                __func__, inode->i_ino, dir->i_ino);
 122
 123        if (S_ISLNK(inode->i_mode))
 124                return 0;
 125
 126        err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 127        if (err)
 128                return err;
 129
 130        if (default_acl) {
 131                err = __hfsplus_set_posix_acl(inode, default_acl,
 132                                              ACL_TYPE_DEFAULT);
 133                posix_acl_release(default_acl);
 134        }
 135
 136        if (acl) {
 137                if (!err)
 138                        err = __hfsplus_set_posix_acl(inode, acl,
 139                                                      ACL_TYPE_ACCESS);
 140                posix_acl_release(acl);
 141        }
 142        return err;
 143}
 144