blob: 4293b4599ff645e8da821cc09bf68577eb65052b [file] [log] [blame]
Aneesh Kumar K.V85ff8722010-09-28 00:27:39 +05301/*
2 * Copyright IBM Corporation, 2010
3 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/fs.h>
17#include <net/9p/9p.h>
18#include <net/9p/client.h>
19#include <linux/slab.h>
20#include <linux/posix_acl_xattr.h>
21#include "xattr.h"
22#include "acl.h"
23
24static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
25{
26 ssize_t size;
27 void *value = NULL;
28 struct posix_acl *acl = NULL;;
29
30 size = v9fs_fid_xattr_get(fid, name, NULL, 0);
31 if (size > 0) {
32 value = kzalloc(size, GFP_NOFS);
33 if (!value)
34 return ERR_PTR(-ENOMEM);
35 size = v9fs_fid_xattr_get(fid, name, value, size);
36 if (size > 0) {
37 acl = posix_acl_from_xattr(value, size);
38 if (IS_ERR(acl))
39 goto err_out;
40 }
41 } else if (size == -ENODATA || size == 0 ||
42 size == -ENOSYS || size == -EOPNOTSUPP) {
43 acl = NULL;
44 } else
45 acl = ERR_PTR(-EIO);
46
47err_out:
48 kfree(value);
49 return acl;
50}
51
52int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
53{
54 int retval = 0;
55 struct posix_acl *pacl, *dacl;
56
57 /* get the default/access acl values and cache them */
58 dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
59 pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS);
60
61 if (!IS_ERR(dacl) && !IS_ERR(pacl)) {
62 set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl);
63 set_cached_acl(inode, ACL_TYPE_ACCESS, pacl);
64 posix_acl_release(dacl);
65 posix_acl_release(pacl);
66 } else
67 retval = -EIO;
68
69 return retval;
70}
71
72static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)
73{
74 struct posix_acl *acl;
75 /*
76 * 9p Always cache the acl value when
77 * instantiating the inode (v9fs_inode_from_fid)
78 */
79 acl = get_cached_acl(inode, type);
80 BUG_ON(acl == ACL_NOT_CACHED);
81 return acl;
82}
83
84int v9fs_check_acl(struct inode *inode, int mask)
85{
86 struct posix_acl *acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
87
88 if (IS_ERR(acl))
89 return PTR_ERR(acl);
90 if (acl) {
91 int error = posix_acl_permission(inode, acl, mask);
92 posix_acl_release(acl);
93 return error;
94 }
95 return -EAGAIN;
96}
Aneesh Kumar K.V7a4566b2010-09-28 00:27:39 +053097
98static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
99 void *buffer, size_t size, int type)
100{
101 struct posix_acl *acl;
102 int error;
103
104 if (strcmp(name, "") != 0)
105 return -EINVAL;
106
107 acl = v9fs_get_cached_acl(dentry->d_inode, type);
108 if (IS_ERR(acl))
109 return PTR_ERR(acl);
110 if (acl == NULL)
111 return -ENODATA;
112 error = posix_acl_to_xattr(acl, buffer, size);
113 posix_acl_release(acl);
114
115 return error;
116}
117
118static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
119 const void *value, size_t size,
120 int flags, int type)
121{
122 return 0;
123}
124
125const struct xattr_handler v9fs_xattr_acl_access_handler = {
126 .prefix = POSIX_ACL_XATTR_ACCESS,
127 .flags = ACL_TYPE_ACCESS,
128 .get = v9fs_xattr_get_acl,
129 .set = v9fs_xattr_set_acl,
130};
131
132const struct xattr_handler v9fs_xattr_acl_default_handler = {
133 .prefix = POSIX_ACL_XATTR_DEFAULT,
134 .flags = ACL_TYPE_DEFAULT,
135 .get = v9fs_xattr_get_acl,
136 .set = v9fs_xattr_set_acl,
137};