acl.c (37bc15392a2363ca822b2c2828e0ccafbea32f75) acl.c (64e178a7118b1cf7648391755e44dcc209091003)
1/*
2 * linux/fs/ext2/acl.c
3 *
4 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
5 */
6
7#include <linux/capability.h>
8#include <linux/init.h>

--- 134 unchanged lines hidden (view full) ---

143struct posix_acl *
144ext2_get_acl(struct inode *inode, int type)
145{
146 int name_index;
147 char *value = NULL;
148 struct posix_acl *acl;
149 int retval;
150
1/*
2 * linux/fs/ext2/acl.c
3 *
4 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
5 */
6
7#include <linux/capability.h>
8#include <linux/init.h>

--- 134 unchanged lines hidden (view full) ---

143struct posix_acl *
144ext2_get_acl(struct inode *inode, int type)
145{
146 int name_index;
147 char *value = NULL;
148 struct posix_acl *acl;
149 int retval;
150
151 if (!test_opt(inode->i_sb, POSIX_ACL))
152 return NULL;
153
154 acl = get_cached_acl(inode, type);
155 if (acl != ACL_NOT_CACHED)
156 return acl;
157
158 switch (type) {
159 case ACL_TYPE_ACCESS:
160 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
161 break;
162 case ACL_TYPE_DEFAULT:
163 name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
164 break;
165 default:

--- 18 unchanged lines hidden (view full) ---

184 set_cached_acl(inode, type, acl);
185
186 return acl;
187}
188
189/*
190 * inode->i_mutex: down
191 */
151 switch (type) {
152 case ACL_TYPE_ACCESS:
153 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
154 break;
155 case ACL_TYPE_DEFAULT:
156 name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
157 break;
158 default:

--- 18 unchanged lines hidden (view full) ---

177 set_cached_acl(inode, type, acl);
178
179 return acl;
180}
181
182/*
183 * inode->i_mutex: down
184 */
192static int
193ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
185int
186ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
194{
195 int name_index;
196 void *value = NULL;
197 size_t size = 0;
198 int error;
199
187{
188 int name_index;
189 void *value = NULL;
190 size_t size = 0;
191 int error;
192
200 if (S_ISLNK(inode->i_mode))
201 return -EOPNOTSUPP;
202 if (!test_opt(inode->i_sb, POSIX_ACL))
203 return 0;
204
205 switch(type) {
206 case ACL_TYPE_ACCESS:
207 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
208 if (acl) {
209 error = posix_acl_equiv_mode(acl, &inode->i_mode);
210 if (error < 0)
211 return error;
212 else {

--- 32 unchanged lines hidden (view full) ---

245 * Initialize the ACLs of a new inode. Called from ext2_new_inode.
246 *
247 * dir->i_mutex: down
248 * inode->i_mutex: up (access to inode is still exclusive)
249 */
250int
251ext2_init_acl(struct inode *inode, struct inode *dir)
252{
193 switch(type) {
194 case ACL_TYPE_ACCESS:
195 name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
196 if (acl) {
197 error = posix_acl_equiv_mode(acl, &inode->i_mode);
198 if (error < 0)
199 return error;
200 else {

--- 32 unchanged lines hidden (view full) ---

233 * Initialize the ACLs of a new inode. Called from ext2_new_inode.
234 *
235 * dir->i_mutex: down
236 * inode->i_mutex: up (access to inode is still exclusive)
237 */
238int
239ext2_init_acl(struct inode *inode, struct inode *dir)
240{
253 struct posix_acl *acl = NULL;
254 int error = 0;
241 struct posix_acl *default_acl, *acl;
242 int error;
255
243
256 if (!S_ISLNK(inode->i_mode)) {
257 if (test_opt(dir->i_sb, POSIX_ACL)) {
258 acl = ext2_get_acl(dir, ACL_TYPE_DEFAULT);
259 if (IS_ERR(acl))
260 return PTR_ERR(acl);
261 }
262 if (!acl)
263 inode->i_mode &= ~current_umask();
264 }
265 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
266 if (S_ISDIR(inode->i_mode)) {
267 error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
268 if (error)
269 goto cleanup;
270 }
271 error = __posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
272 if (error < 0)
273 return error;
274 if (error > 0) {
275 /* This is an extended ACL */
276 error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
277 }
278 }
279cleanup:
280 posix_acl_release(acl);
281 return error;
282}
283
284/*
285 * Does chmod for an inode that may have an Access Control List. The
286 * inode->i_mode field must be updated to the desired value by the caller
287 * before calling this function.
288 * Returns 0 on success, or a negative error number.
289 *
290 * We change the ACL rather than storing some ACL entries in the file
291 * mode permission bits (which would be more efficient), because that
292 * would break once additional permissions (like ACL_APPEND, ACL_DELETE
293 * for directories) are added. There are no more bits available in the
294 * file mode.
295 *
296 * inode->i_mutex: down
297 */
298int
299ext2_acl_chmod(struct inode *inode)
300{
301 struct posix_acl *acl;
302 int error;
303
304 if (!test_opt(inode->i_sb, POSIX_ACL))
305 return 0;
306 if (S_ISLNK(inode->i_mode))
307 return -EOPNOTSUPP;
308 acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
309 if (IS_ERR(acl) || !acl)
310 return PTR_ERR(acl);
311 error = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
244 error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
312 if (error)
313 return error;
245 if (error)
246 return error;
314 error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
315 posix_acl_release(acl);
316 return error;
317}
318
247
319/*
320 * Extended attribut handlers
321 */
322static size_t
323ext2_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_size,
324 const char *name, size_t name_len, int type)
325{
326 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
327
328 if (!test_opt(dentry->d_sb, POSIX_ACL))
329 return 0;
330 if (list && size <= list_size)
331 memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
332 return size;
333}
334
335static size_t
336ext2_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_size,
337 const char *name, size_t name_len, int type)
338{
339 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
340
341 if (!test_opt(dentry->d_sb, POSIX_ACL))
342 return 0;
343 if (list && size <= list_size)
344 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
345 return size;
346}
347
348static int
349ext2_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
350 size_t size, int type)
351{
352 struct posix_acl *acl;
353 int error;
354
355 if (strcmp(name, "") != 0)
356 return -EINVAL;
357 if (!test_opt(dentry->d_sb, POSIX_ACL))
358 return -EOPNOTSUPP;
359
360 acl = ext2_get_acl(dentry->d_inode, type);
361 if (IS_ERR(acl))
362 return PTR_ERR(acl);
363 if (acl == NULL)
364 return -ENODATA;
365 error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
366 posix_acl_release(acl);
367
248 if (default_acl) {
249 error = ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
250 posix_acl_release(default_acl);
251 }
252 if (acl) {
253 if (!error)
254 error = ext2_set_acl(inode, acl, ACL_TYPE_ACCESS);
255 posix_acl_release(acl);
256 }
368 return error;
369}
257 return error;
258}
370
371static int
372ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
373 size_t size, int flags, int type)
374{
375 struct posix_acl *acl;
376 int error;
377
378 if (strcmp(name, "") != 0)
379 return -EINVAL;
380 if (!test_opt(dentry->d_sb, POSIX_ACL))
381 return -EOPNOTSUPP;
382 if (!inode_owner_or_capable(dentry->d_inode))
383 return -EPERM;
384
385 if (value) {
386 acl = posix_acl_from_xattr(&init_user_ns, value, size);
387 if (IS_ERR(acl))
388 return PTR_ERR(acl);
389 else if (acl) {
390 error = posix_acl_valid(acl);
391 if (error)
392 goto release_and_out;
393 }
394 } else
395 acl = NULL;
396
397 error = ext2_set_acl(dentry->d_inode, type, acl);
398
399release_and_out:
400 posix_acl_release(acl);
401 return error;
402}
403
404const struct xattr_handler ext2_xattr_acl_access_handler = {
405 .prefix = POSIX_ACL_XATTR_ACCESS,
406 .flags = ACL_TYPE_ACCESS,
407 .list = ext2_xattr_list_acl_access,
408 .get = ext2_xattr_get_acl,
409 .set = ext2_xattr_set_acl,
410};
411
412const struct xattr_handler ext2_xattr_acl_default_handler = {
413 .prefix = POSIX_ACL_XATTR_DEFAULT,
414 .flags = ACL_TYPE_DEFAULT,
415 .list = ext2_xattr_list_acl_default,
416 .get = ext2_xattr_get_acl,
417 .set = ext2_xattr_set_acl,
418};