xattr_acl.c revision 1b1dcc1b57a49136f118a0f16367256ff9994a69
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/posix_acl.h> 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/reiserfs_fs.h> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/xattr.h> 79a59f452abe11f569e13ec16c51e6d61c54b9838Christoph Hellwig#include <linux/posix_acl_xattr.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/reiserfs_xattr.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/reiserfs_acl.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsstatic int reiserfs_set_acl(struct inode *inode, int type, 13bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl *acl); 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsxattr_set_acl(struct inode *inode, int type, const void *value, size_t size) 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct posix_acl *acl; 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!reiserfs_posixacl(inode->i_sb)) 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (value) { 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = posix_acl_from_xattr(value, size); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(acl)) { 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(acl); 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (acl) { 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = posix_acl_valid(acl); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto release_and_out; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = NULL; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds error = reiserfs_set_acl(inode, type, acl); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds release_and_out: 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds posix_acl_release(acl); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsxattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct posix_acl *acl; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!reiserfs_posixacl(inode->i_sb)) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 54bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl = reiserfs_get_acl(inode, type); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(acl)) 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(acl); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acl == NULL) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODATA; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = posix_acl_to_xattr(acl, buffer, size); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds posix_acl_release(acl); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert from filesystem to in-memory representation. 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 68bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsstatic struct posix_acl *posix_acl_from_disk(const void *value, size_t size) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *end = (char *)value + size; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n, count; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct posix_acl *acl; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!value) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (size < sizeof(reiserfs_acl_header)) 77bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ERR_PTR(-EINVAL); 78bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (((reiserfs_acl_header *) value)->a_version != 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_to_le32(REISERFS_ACL_VERSION)) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = (char *)value + sizeof(reiserfs_acl_header); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = reiserfs_acl_count(size); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count < 0) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = posix_acl_alloc(count, GFP_NOFS); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acl) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 90bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds for (n = 0; n < count; n++) { 91bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((char *)value + sizeof(reiserfs_acl_entry_short) > end) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 94bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 96bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (acl->a_entries[n].e_tag) { 97bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER_OBJ: 98bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP_OBJ: 99bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_MASK: 100bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_OTHER: 101bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds value = (char *)value + 102bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds sizeof(reiserfs_acl_entry_short); 103bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl->a_entries[n].e_id = ACL_UNDEFINED_ID; 104bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 105bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 106bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER: 107bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP: 108bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds value = (char *)value + sizeof(reiserfs_acl_entry); 109bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if ((char *)value > end) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 111bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl->a_entries[n].e_id = le32_to_cpu(entry->e_id); 112bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 113bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 114bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 115bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto fail; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (value != end) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return acl; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 122bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds fail: 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds posix_acl_release(acl); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert from in-memory to filesystem representation. 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 130bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsstatic void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size) 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reiserfs_acl_header *ext_acl; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *e; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *size = reiserfs_acl_size(acl->a_count); 137bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds ext_acl = (reiserfs_acl_header *) kmalloc(sizeof(reiserfs_acl_header) + 138bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl->a_count * 139bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds sizeof(reiserfs_acl_entry), 140bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds GFP_NOFS); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ext_acl) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e = (char *)ext_acl + sizeof(reiserfs_acl_header); 145bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds for (n = 0; n < acl->a_count; n++) { 146bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e; 147bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 149bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (acl->a_entries[n].e_tag) { 150bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER: 151bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP: 152bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds entry->e_id = cpu_to_le32(acl->a_entries[n].e_id); 153bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds e += sizeof(reiserfs_acl_entry); 154bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 155bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 156bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER_OBJ: 157bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP_OBJ: 158bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_MASK: 159bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_OTHER: 160bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds e += sizeof(reiserfs_acl_entry_short); 161bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 162bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 163bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 164bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto fail; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (char *)ext_acl; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 169bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds fail: 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ext_acl); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inode operation get_posix_acl(). 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1771b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * inode->i_mutex: down 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BKL held [before 2.5.x] 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 180bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsstruct posix_acl *reiserfs_get_acl(struct inode *inode, int type) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *name, *value; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct posix_acl *acl, **p_acl; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t size; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 186bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 187bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 188bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (type) { 189bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_ACCESS: 190bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_ACCESS; 191bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds p_acl = &reiserfs_i->i_acl_access; 192bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 193bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_DEFAULT: 194bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_DEFAULT; 195bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds p_acl = &reiserfs_i->i_acl_default; 196bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 197bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 198bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ERR_PTR(-EINVAL); 199bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 200bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 201bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (IS_ERR(*p_acl)) { 202bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (PTR_ERR(*p_acl) == -ENODATA) 203bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return NULL; 204bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } else if (*p_acl != NULL) 205bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return posix_acl_dup(*p_acl); 206bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 207bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds size = reiserfs_xattr_get(inode, name, NULL, 0); 208bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if ((int)size < 0) { 209bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (size == -ENODATA || size == -ENOSYS) { 210bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds *p_acl = ERR_PTR(-ENODATA); 211bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return NULL; 212bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 213bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ERR_PTR(size); 214bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 216bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds value = kmalloc(size, GFP_NOFS); 217bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!value) 218bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ERR_PTR(-ENOMEM); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = reiserfs_xattr_get(inode, name, value, size); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval == -ENODATA || retval == -ENOSYS) { 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This shouldn't actually happen as it should have 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds been caught above.. but just in case */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = NULL; 225bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds *p_acl = ERR_PTR(-ENODATA); 226bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } else if (retval < 0) { 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = ERR_PTR(retval); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = posix_acl_from_disk(value, retval); 230bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds *p_acl = posix_acl_dup(acl); 231bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(value); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return acl; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inode operation set_posix_acl(). 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2401b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * inode->i_mutex: down 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BKL held [before 2.5.x] 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 246bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds char *name; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *value = NULL; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct posix_acl **p_acl; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t size; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 251bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (S_ISLNK(inode->i_mode)) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 256bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (type) { 257bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_ACCESS: 258bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_ACCESS; 259bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds p_acl = &reiserfs_i->i_acl_access; 260bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (acl) { 261bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds mode_t mode = inode->i_mode; 262bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds error = posix_acl_equiv_mode(acl, &mode); 263bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (error < 0) 264bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return error; 265bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds else { 266bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds inode->i_mode = mode; 267bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (error == 0) 268bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl = NULL; 269bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 270bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 271bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 272bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_DEFAULT: 273bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_DEFAULT; 274bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds p_acl = &reiserfs_i->i_acl_default; 275bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!S_ISDIR(inode->i_mode)) 276bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return acl ? -EACCES : 0; 277bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 278bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 279bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return -EINVAL; 280bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 281bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 282bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (acl) { 283bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds value = posix_acl_to_disk(acl, &size); 284bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (IS_ERR(value)) 285bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return (int)PTR_ERR(value); 286bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds error = reiserfs_xattr_set(inode, name, value, size, 0); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 288bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds error = reiserfs_xattr_del(inode, name); 289bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (error == -ENODATA) { 290bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* This may seem odd here, but it means that the ACL was set 291bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds * with a value representable with mode bits. If there was 292bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds * an ACL before, reiserfs_xattr_del already dirtied the inode. 293bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds */ 294bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds mark_inode_dirty(inode); 295bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds error = 0; 296bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 297bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 299833d304b22edff5cc687ab7e5549c2f0dcdd951aJames Lamanna kfree(value); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!error) { 302bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* Release the old one */ 303bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!IS_ERR(*p_acl) && *p_acl) 304bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(*p_acl); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 306bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (acl == NULL) 307bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds *p_acl = ERR_PTR(-ENODATA); 308bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds else 309bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds *p_acl = posix_acl_dup(acl); 310bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen/* dir->i_mutex: locked, 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inode is new and not released into the wild yet */ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 318bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsreiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry, 319bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct inode *inode) 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 321bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl *acl; 322bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int err = 0; 323bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 324bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* ACLs only get applied to files and directories */ 325bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (S_ISLNK(inode->i_mode)) 326bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 327bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 328bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* ACLs can only be used on "new" objects, so if it's an old object 329bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds * there is nothing to inherit from */ 330bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (get_inode_sd_version(dir) == STAT_DATA_V1) 331bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto apply_umask; 332bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 333bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This 334bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds * would be useless since permissions are ignored, and a pain because 335bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds * it introduces locking cycles */ 336bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (is_reiserfs_priv_object(dir)) { 337bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_mark_inode_private(inode); 338bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto apply_umask; 339bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 340bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 341bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl = reiserfs_get_acl(dir, ACL_TYPE_DEFAULT); 342bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (IS_ERR(acl)) { 343bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (PTR_ERR(acl) == -ENODATA) 344bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto apply_umask; 345bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return PTR_ERR(acl); 346bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 347bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 348bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (acl) { 349bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl *acl_copy; 350bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds mode_t mode = inode->i_mode; 351bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int need_acl; 352bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 353bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* Copy the default ACL to the default ACL of a new directory */ 354bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (S_ISDIR(inode->i_mode)) { 355bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds err = reiserfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); 356bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (err) 357bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto cleanup; 358bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 359bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 360bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* Now we reconcile the new ACL and the mode, 361bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds potentially modifying both */ 362bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl_copy = posix_acl_clone(acl, GFP_NOFS); 363bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!acl_copy) { 364bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds err = -ENOMEM; 365bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto cleanup; 366bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 367bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 368bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds need_acl = posix_acl_create_masq(acl_copy, &mode); 369bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (need_acl >= 0) { 370bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (mode != inode->i_mode) { 371bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds inode->i_mode = mode; 372bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 373bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 374bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* If we need an ACL.. */ 375bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (need_acl > 0) { 376bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds err = 377bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_set_acl(inode, ACL_TYPE_ACCESS, 378bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl_copy); 379bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (err) 380bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto cleanup_copy; 381bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 382bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 383bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds cleanup_copy: 384bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(acl_copy); 385bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds cleanup: 386bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(acl); 387bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } else { 388bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds apply_umask: 389bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* no ACL, apply umask */ 390bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds inode->i_mode &= ~current->fs->umask; 391bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 392bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 393bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return err; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Looks up and caches the result of the default ACL. 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We do this so that we don't need to carry the xattr_sem into 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reiserfs_new_inode if we don't need to */ 399bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsint reiserfs_cache_default_acl(struct inode *inode) 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 401bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int ret = 0; 402bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (reiserfs_posixacl(inode->i_sb) && !is_reiserfs_priv_object(inode)) { 403bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl *acl; 404bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_lock_xattr_i(inode); 405bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_lock_xattrs(inode->i_sb); 406bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); 407bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_unlock_xattrs(inode->i_sb); 408bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_unlock_xattr_i(inode); 409bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds ret = acl ? 1 : 0; 410bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(acl); 411bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 412bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 413bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ret; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 416bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsint reiserfs_acl_chmod(struct inode *inode) 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 418bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl *acl, *clone; 419bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int error; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (S_ISLNK(inode->i_mode)) 422bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return -EOPNOTSUPP; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 424bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (get_inode_sd_version(inode) == STAT_DATA_V1 || 425bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds !reiserfs_posixacl(inode->i_sb)) { 426bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 429bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_lock_xattrs(inode->i_sb); 430bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); 431bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_unlock_xattrs(inode->i_sb); 432bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!acl) 433bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 434bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (IS_ERR(acl)) 435bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return PTR_ERR(acl); 436bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds clone = posix_acl_clone(acl, GFP_NOFS); 437bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(acl); 438bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!clone) 439bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return -ENOMEM; 440bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds error = posix_acl_chmod_masq(clone, inode->i_mode); 441bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!error) { 442bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int lock = !has_xattr_dir(inode); 443bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_write_lock_xattr_i(inode); 444bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (lock) 445bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_write_lock_xattrs(inode->i_sb); 446bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds else 447bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_lock_xattrs(inode->i_sb); 448bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 449bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (lock) 450bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_write_unlock_xattrs(inode->i_sb); 451bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds else 452bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_read_unlock_xattrs(inode->i_sb); 453bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_write_unlock_xattr_i(inode); 454bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 455bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(clone); 456bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return error; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsposix_acl_access_get(struct inode *inode, const char *name, 461bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds void *buffer, size_t size) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 463bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1) 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsposix_acl_access_set(struct inode *inode, const char *name, 470bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds const void *value, size_t size, int flags) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 472bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1) 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 477bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsstatic int posix_acl_access_del(struct inode *inode, const char *name) 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 479bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 480bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl **acl = &reiserfs_i->i_acl_access; 481bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1) 482bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return -EINVAL; 483bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!IS_ERR(*acl) && *acl) { 484bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(*acl); 485bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds *acl = ERR_PTR(-ENODATA); 486bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 487bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 488bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 492bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsposix_acl_access_list(struct inode *inode, const char *name, int namelen, 493bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds char *out) 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 495bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int len = namelen; 496bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!reiserfs_posixacl(inode->i_sb)) 497bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 498bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (out) 499bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds memcpy(out, name, len); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return len; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct reiserfs_xattr_handler posix_acl_access_handler = { 5059a59f452abe11f569e13ec16c51e6d61c54b9838Christoph Hellwig .prefix = POSIX_ACL_XATTR_ACCESS, 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get = posix_acl_access_get, 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set = posix_acl_access_set, 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .del = posix_acl_access_del, 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .list = posix_acl_access_list, 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 513bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsposix_acl_default_get(struct inode *inode, const char *name, 514bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds void *buffer, size_t size) 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 516bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1) 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsposix_acl_default_set(struct inode *inode, const char *name, 523bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds const void *value, size_t size, int flags) 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 525bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1) 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 530bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsstatic int posix_acl_default_del(struct inode *inode, const char *name) 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 532bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 533bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl **acl = &reiserfs_i->i_acl_default; 534bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1) 535bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return -EINVAL; 536bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!IS_ERR(*acl) && *acl) { 537bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(*acl); 538bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds *acl = ERR_PTR(-ENODATA); 539bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 540bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 541bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 545bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsposix_acl_default_list(struct inode *inode, const char *name, int namelen, 546bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds char *out) 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 548bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int len = namelen; 549bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!reiserfs_posixacl(inode->i_sb)) 550bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 551bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (out) 552bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds memcpy(out, name, len); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 554bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return len; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct reiserfs_xattr_handler posix_acl_default_handler = { 5589a59f452abe11f569e13ec16c51e6d61c54b9838Christoph Hellwig .prefix = POSIX_ACL_XATTR_DEFAULT, 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get = posix_acl_default_get, 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set = posix_acl_default_set, 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .del = posix_acl_default_del, 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .list = posix_acl_default_list, 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 564