Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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