posix_acl.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. #include "hfsplus_fs.h"
  9. #include "xattr.h"
  10. #include "acl.h"
  11. struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
  12. {
  13. struct posix_acl *acl;
  14. char *xattr_name;
  15. char *value = NULL;
  16. ssize_t size;
  17. hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
  18. switch (type) {
  19. case ACL_TYPE_ACCESS:
  20. xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
  21. break;
  22. case ACL_TYPE_DEFAULT:
  23. xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  24. break;
  25. default:
  26. return ERR_PTR(-EINVAL);
  27. }
  28. size = __hfsplus_getxattr(inode, xattr_name, NULL, 0);
  29. if (size > 0) {
  30. value = (char *)hfsplus_alloc_attr_entry();
  31. if (unlikely(!value))
  32. return ERR_PTR(-ENOMEM);
  33. size = __hfsplus_getxattr(inode, xattr_name, value, size);
  34. }
  35. if (size > 0)
  36. acl = posix_acl_from_xattr(&init_user_ns, value, size);
  37. else if (size == -ENODATA)
  38. acl = NULL;
  39. else
  40. acl = ERR_PTR(size);
  41. hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
  42. return acl;
  43. }
  44. int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
  45. int type)
  46. {
  47. int err;
  48. char *xattr_name;
  49. size_t size = 0;
  50. char *value = NULL;
  51. hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
  52. switch (type) {
  53. case ACL_TYPE_ACCESS:
  54. xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
  55. if (acl) {
  56. err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
  57. if (err)
  58. return err;
  59. }
  60. err = 0;
  61. break;
  62. case ACL_TYPE_DEFAULT:
  63. xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  64. if (!S_ISDIR(inode->i_mode))
  65. return acl ? -EACCES : 0;
  66. break;
  67. default:
  68. return -EINVAL;
  69. }
  70. if (acl) {
  71. size = posix_acl_xattr_size(acl->a_count);
  72. if (unlikely(size > HFSPLUS_MAX_INLINE_DATA_SIZE))
  73. return -ENOMEM;
  74. value = (char *)hfsplus_alloc_attr_entry();
  75. if (unlikely(!value))
  76. return -ENOMEM;
  77. err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
  78. if (unlikely(err < 0))
  79. goto end_set_acl;
  80. }
  81. err = __hfsplus_setxattr(inode, xattr_name, value, size, 0);
  82. end_set_acl:
  83. hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
  84. if (!err)
  85. set_cached_acl(inode, type, acl);
  86. return err;
  87. }
  88. int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
  89. {
  90. int err = 0;
  91. struct posix_acl *default_acl, *acl;
  92. hfs_dbg(ACL_MOD,
  93. "[%s]: ino %lu, dir->ino %lu\n",
  94. __func__, inode->i_ino, dir->i_ino);
  95. if (S_ISLNK(inode->i_mode))
  96. return 0;
  97. err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
  98. if (err)
  99. return err;
  100. if (default_acl) {
  101. err = hfsplus_set_posix_acl(inode, default_acl,
  102. ACL_TYPE_DEFAULT);
  103. posix_acl_release(default_acl);
  104. }
  105. if (acl) {
  106. if (!err)
  107. err = hfsplus_set_posix_acl(inode, acl,
  108. ACL_TYPE_ACCESS);
  109. posix_acl_release(acl);
  110. }
  111. return err;
  112. }