|
@@ -17,9 +17,11 @@
|
|
|
#include <net/9p/9p.h>
|
|
|
#include <net/9p/client.h>
|
|
|
#include <linux/slab.h>
|
|
|
+#include <linux/sched.h>
|
|
|
#include <linux/posix_acl_xattr.h>
|
|
|
#include "xattr.h"
|
|
|
#include "acl.h"
|
|
|
+#include "v9fs_vfs.h"
|
|
|
|
|
|
static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
|
|
|
{
|
|
@@ -119,7 +121,77 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
|
|
|
const void *value, size_t size,
|
|
|
int flags, int type)
|
|
|
{
|
|
|
- return 0;
|
|
|
+ int retval;
|
|
|
+ struct posix_acl *acl;
|
|
|
+ struct inode *inode = dentry->d_inode;
|
|
|
+
|
|
|
+ if (strcmp(name, "") != 0)
|
|
|
+ return -EINVAL;
|
|
|
+ if (S_ISLNK(inode->i_mode))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ if (!is_owner_or_cap(inode))
|
|
|
+ return -EPERM;
|
|
|
+ if (value) {
|
|
|
+ /* update the cached acl value */
|
|
|
+ acl = posix_acl_from_xattr(value, size);
|
|
|
+ if (IS_ERR(acl))
|
|
|
+ return PTR_ERR(acl);
|
|
|
+ else if (acl) {
|
|
|
+ retval = posix_acl_valid(acl);
|
|
|
+ if (retval)
|
|
|
+ goto err_out;
|
|
|
+ }
|
|
|
+ } else
|
|
|
+ acl = NULL;
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case ACL_TYPE_ACCESS:
|
|
|
+ name = POSIX_ACL_XATTR_ACCESS;
|
|
|
+ if (acl) {
|
|
|
+ mode_t mode = inode->i_mode;
|
|
|
+ retval = posix_acl_equiv_mode(acl, &mode);
|
|
|
+ if (retval < 0)
|
|
|
+ goto err_out;
|
|
|
+ else {
|
|
|
+ struct iattr iattr;
|
|
|
+ if (retval == 0) {
|
|
|
+ /*
|
|
|
+ * ACL can be represented
|
|
|
+ * by the mode bits. So don't
|
|
|
+ * update ACL.
|
|
|
+ */
|
|
|
+ acl = NULL;
|
|
|
+ value = NULL;
|
|
|
+ size = 0;
|
|
|
+ }
|
|
|
+ /* Updte the mode bits */
|
|
|
+ iattr.ia_mode = ((mode & S_IALLUGO) |
|
|
|
+ (inode->i_mode & ~S_IALLUGO));
|
|
|
+ iattr.ia_valid = ATTR_MODE;
|
|
|
+ /* FIXME should we update ctime ?
|
|
|
+ * What is the following setxattr update the
|
|
|
+ * mode ?
|
|
|
+ */
|
|
|
+ v9fs_vfs_setattr_dotl(dentry, &iattr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACL_TYPE_DEFAULT:
|
|
|
+ name = POSIX_ACL_XATTR_DEFAULT;
|
|
|
+ if (!S_ISDIR(inode->i_mode)) {
|
|
|
+ retval = -EINVAL;
|
|
|
+ goto err_out;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ BUG();
|
|
|
+ }
|
|
|
+ retval = v9fs_xattr_set(dentry, name, value, size, flags);
|
|
|
+ if (!retval)
|
|
|
+ set_cached_acl(inode, type, acl);
|
|
|
+err_out:
|
|
|
+ posix_acl_release(acl);
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
const struct xattr_handler v9fs_xattr_acl_access_handler = {
|