diff options
Diffstat (limited to 'fs/9p/acl.c')
-rw-r--r-- | fs/9p/acl.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 4293b4599ff6..cad38bc1710e 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c | |||
@@ -17,9 +17,11 @@ | |||
17 | #include <net/9p/9p.h> | 17 | #include <net/9p/9p.h> |
18 | #include <net/9p/client.h> | 18 | #include <net/9p/client.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/sched.h> | ||
20 | #include <linux/posix_acl_xattr.h> | 21 | #include <linux/posix_acl_xattr.h> |
21 | #include "xattr.h" | 22 | #include "xattr.h" |
22 | #include "acl.h" | 23 | #include "acl.h" |
24 | #include "v9fs_vfs.h" | ||
23 | 25 | ||
24 | static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) | 26 | static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) |
25 | { | 27 | { |
@@ -119,7 +121,77 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, | |||
119 | const void *value, size_t size, | 121 | const void *value, size_t size, |
120 | int flags, int type) | 122 | int flags, int type) |
121 | { | 123 | { |
122 | return 0; | 124 | int retval; |
125 | struct posix_acl *acl; | ||
126 | struct inode *inode = dentry->d_inode; | ||
127 | |||
128 | if (strcmp(name, "") != 0) | ||
129 | return -EINVAL; | ||
130 | if (S_ISLNK(inode->i_mode)) | ||
131 | return -EOPNOTSUPP; | ||
132 | if (!is_owner_or_cap(inode)) | ||
133 | return -EPERM; | ||
134 | if (value) { | ||
135 | /* update the cached acl value */ | ||
136 | acl = posix_acl_from_xattr(value, size); | ||
137 | if (IS_ERR(acl)) | ||
138 | return PTR_ERR(acl); | ||
139 | else if (acl) { | ||
140 | retval = posix_acl_valid(acl); | ||
141 | if (retval) | ||
142 | goto err_out; | ||
143 | } | ||
144 | } else | ||
145 | acl = NULL; | ||
146 | |||
147 | switch (type) { | ||
148 | case ACL_TYPE_ACCESS: | ||
149 | name = POSIX_ACL_XATTR_ACCESS; | ||
150 | if (acl) { | ||
151 | mode_t mode = inode->i_mode; | ||
152 | retval = posix_acl_equiv_mode(acl, &mode); | ||
153 | if (retval < 0) | ||
154 | goto err_out; | ||
155 | else { | ||
156 | struct iattr iattr; | ||
157 | if (retval == 0) { | ||
158 | /* | ||
159 | * ACL can be represented | ||
160 | * by the mode bits. So don't | ||
161 | * update ACL. | ||
162 | */ | ||
163 | acl = NULL; | ||
164 | value = NULL; | ||
165 | size = 0; | ||
166 | } | ||
167 | /* Updte the mode bits */ | ||
168 | iattr.ia_mode = ((mode & S_IALLUGO) | | ||
169 | (inode->i_mode & ~S_IALLUGO)); | ||
170 | iattr.ia_valid = ATTR_MODE; | ||
171 | /* FIXME should we update ctime ? | ||
172 | * What is the following setxattr update the | ||
173 | * mode ? | ||
174 | */ | ||
175 | v9fs_vfs_setattr_dotl(dentry, &iattr); | ||
176 | } | ||
177 | } | ||
178 | break; | ||
179 | case ACL_TYPE_DEFAULT: | ||
180 | name = POSIX_ACL_XATTR_DEFAULT; | ||
181 | if (!S_ISDIR(inode->i_mode)) { | ||
182 | retval = -EINVAL; | ||
183 | goto err_out; | ||
184 | } | ||
185 | break; | ||
186 | default: | ||
187 | BUG(); | ||
188 | } | ||
189 | retval = v9fs_xattr_set(dentry, name, value, size, flags); | ||
190 | if (!retval) | ||
191 | set_cached_acl(inode, type, acl); | ||
192 | err_out: | ||
193 | posix_acl_release(acl); | ||
194 | return retval; | ||
123 | } | 195 | } |
124 | 196 | ||
125 | const struct xattr_handler v9fs_xattr_acl_access_handler = { | 197 | const struct xattr_handler v9fs_xattr_acl_access_handler = { |