diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/reiserfs/xattr_acl.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'fs/reiserfs/xattr_acl.c')
-rw-r--r-- | fs/reiserfs/xattr_acl.c | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c new file mode 100644 index 000000000000..e302071903a1 --- /dev/null +++ b/fs/reiserfs/xattr_acl.c | |||
@@ -0,0 +1,571 @@ | |||
1 | #include <linux/fs.h> | ||
2 | #include <linux/posix_acl.h> | ||
3 | #include <linux/reiserfs_fs.h> | ||
4 | #include <linux/errno.h> | ||
5 | #include <linux/pagemap.h> | ||
6 | #include <linux/xattr.h> | ||
7 | #include <linux/xattr_acl.h> | ||
8 | #include <linux/reiserfs_xattr.h> | ||
9 | #include <linux/reiserfs_acl.h> | ||
10 | #include <asm/uaccess.h> | ||
11 | |||
12 | static int reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl); | ||
13 | |||
14 | static int | ||
15 | xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) | ||
16 | { | ||
17 | struct posix_acl *acl; | ||
18 | int error; | ||
19 | |||
20 | if (!reiserfs_posixacl(inode->i_sb)) | ||
21 | return -EOPNOTSUPP; | ||
22 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
23 | return -EPERM; | ||
24 | |||
25 | if (value) { | ||
26 | acl = posix_acl_from_xattr(value, size); | ||
27 | if (IS_ERR(acl)) { | ||
28 | return PTR_ERR(acl); | ||
29 | } else if (acl) { | ||
30 | error = posix_acl_valid(acl); | ||
31 | if (error) | ||
32 | goto release_and_out; | ||
33 | } | ||
34 | } else | ||
35 | acl = NULL; | ||
36 | |||
37 | error = reiserfs_set_acl (inode, type, acl); | ||
38 | |||
39 | release_and_out: | ||
40 | posix_acl_release(acl); | ||
41 | return error; | ||
42 | } | ||
43 | |||
44 | |||
45 | static int | ||
46 | xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) | ||
47 | { | ||
48 | struct posix_acl *acl; | ||
49 | int error; | ||
50 | |||
51 | if (!reiserfs_posixacl(inode->i_sb)) | ||
52 | return -EOPNOTSUPP; | ||
53 | |||
54 | acl = reiserfs_get_acl (inode, type); | ||
55 | if (IS_ERR(acl)) | ||
56 | return PTR_ERR(acl); | ||
57 | if (acl == NULL) | ||
58 | return -ENODATA; | ||
59 | error = posix_acl_to_xattr(acl, buffer, size); | ||
60 | posix_acl_release(acl); | ||
61 | |||
62 | return error; | ||
63 | } | ||
64 | |||
65 | |||
66 | /* | ||
67 | * Convert from filesystem to in-memory representation. | ||
68 | */ | ||
69 | static struct posix_acl * | ||
70 | posix_acl_from_disk(const void *value, size_t size) | ||
71 | { | ||
72 | const char *end = (char *)value + size; | ||
73 | int n, count; | ||
74 | struct posix_acl *acl; | ||
75 | |||
76 | if (!value) | ||
77 | return NULL; | ||
78 | if (size < sizeof(reiserfs_acl_header)) | ||
79 | return ERR_PTR(-EINVAL); | ||
80 | if (((reiserfs_acl_header *)value)->a_version != | ||
81 | cpu_to_le32(REISERFS_ACL_VERSION)) | ||
82 | return ERR_PTR(-EINVAL); | ||
83 | value = (char *)value + sizeof(reiserfs_acl_header); | ||
84 | count = reiserfs_acl_count(size); | ||
85 | if (count < 0) | ||
86 | return ERR_PTR(-EINVAL); | ||
87 | if (count == 0) | ||
88 | return NULL; | ||
89 | acl = posix_acl_alloc(count, GFP_NOFS); | ||
90 | if (!acl) | ||
91 | return ERR_PTR(-ENOMEM); | ||
92 | for (n=0; n < count; n++) { | ||
93 | reiserfs_acl_entry *entry = | ||
94 | (reiserfs_acl_entry *)value; | ||
95 | if ((char *)value + sizeof(reiserfs_acl_entry_short) > end) | ||
96 | goto fail; | ||
97 | acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); | ||
98 | acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); | ||
99 | switch(acl->a_entries[n].e_tag) { | ||
100 | case ACL_USER_OBJ: | ||
101 | case ACL_GROUP_OBJ: | ||
102 | case ACL_MASK: | ||
103 | case ACL_OTHER: | ||
104 | value = (char *)value + | ||
105 | sizeof(reiserfs_acl_entry_short); | ||
106 | acl->a_entries[n].e_id = ACL_UNDEFINED_ID; | ||
107 | break; | ||
108 | |||
109 | case ACL_USER: | ||
110 | case ACL_GROUP: | ||
111 | value = (char *)value + sizeof(reiserfs_acl_entry); | ||
112 | if ((char *)value > end) | ||
113 | goto fail; | ||
114 | acl->a_entries[n].e_id = | ||
115 | le32_to_cpu(entry->e_id); | ||
116 | break; | ||
117 | |||
118 | default: | ||
119 | goto fail; | ||
120 | } | ||
121 | } | ||
122 | if (value != end) | ||
123 | goto fail; | ||
124 | return acl; | ||
125 | |||
126 | fail: | ||
127 | posix_acl_release(acl); | ||
128 | return ERR_PTR(-EINVAL); | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * Convert from in-memory to filesystem representation. | ||
133 | */ | ||
134 | static void * | ||
135 | posix_acl_to_disk(const struct posix_acl *acl, size_t *size) | ||
136 | { | ||
137 | reiserfs_acl_header *ext_acl; | ||
138 | char *e; | ||
139 | int n; | ||
140 | |||
141 | *size = reiserfs_acl_size(acl->a_count); | ||
142 | ext_acl = (reiserfs_acl_header *)kmalloc(sizeof(reiserfs_acl_header) + | ||
143 | acl->a_count * sizeof(reiserfs_acl_entry), GFP_NOFS); | ||
144 | if (!ext_acl) | ||
145 | return ERR_PTR(-ENOMEM); | ||
146 | ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION); | ||
147 | e = (char *)ext_acl + sizeof(reiserfs_acl_header); | ||
148 | for (n=0; n < acl->a_count; n++) { | ||
149 | reiserfs_acl_entry *entry = (reiserfs_acl_entry *)e; | ||
150 | entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); | ||
151 | entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); | ||
152 | switch(acl->a_entries[n].e_tag) { | ||
153 | case ACL_USER: | ||
154 | case ACL_GROUP: | ||
155 | entry->e_id = | ||
156 | cpu_to_le32(acl->a_entries[n].e_id); | ||
157 | e += sizeof(reiserfs_acl_entry); | ||
158 | break; | ||
159 | |||
160 | case ACL_USER_OBJ: | ||
161 | case ACL_GROUP_OBJ: | ||
162 | case ACL_MASK: | ||
163 | case ACL_OTHER: | ||
164 | e += sizeof(reiserfs_acl_entry_short); | ||
165 | break; | ||
166 | |||
167 | default: | ||
168 | goto fail; | ||
169 | } | ||
170 | } | ||
171 | return (char *)ext_acl; | ||
172 | |||
173 | fail: | ||
174 | kfree(ext_acl); | ||
175 | return ERR_PTR(-EINVAL); | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Inode operation get_posix_acl(). | ||
180 | * | ||
181 | * inode->i_sem: down | ||
182 | * BKL held [before 2.5.x] | ||
183 | */ | ||
184 | struct posix_acl * | ||
185 | reiserfs_get_acl(struct inode *inode, int type) | ||
186 | { | ||
187 | char *name, *value; | ||
188 | struct posix_acl *acl, **p_acl; | ||
189 | size_t size; | ||
190 | int retval; | ||
191 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); | ||
192 | |||
193 | switch (type) { | ||
194 | case ACL_TYPE_ACCESS: | ||
195 | name = XATTR_NAME_ACL_ACCESS; | ||
196 | p_acl = &reiserfs_i->i_acl_access; | ||
197 | break; | ||
198 | case ACL_TYPE_DEFAULT: | ||
199 | name = XATTR_NAME_ACL_DEFAULT; | ||
200 | p_acl = &reiserfs_i->i_acl_default; | ||
201 | break; | ||
202 | default: | ||
203 | return ERR_PTR (-EINVAL); | ||
204 | } | ||
205 | |||
206 | if (IS_ERR (*p_acl)) { | ||
207 | if (PTR_ERR (*p_acl) == -ENODATA) | ||
208 | return NULL; | ||
209 | } else if (*p_acl != NULL) | ||
210 | return posix_acl_dup (*p_acl); | ||
211 | |||
212 | size = reiserfs_xattr_get (inode, name, NULL, 0); | ||
213 | if ((int)size < 0) { | ||
214 | if (size == -ENODATA || size == -ENOSYS) { | ||
215 | *p_acl = ERR_PTR (-ENODATA); | ||
216 | return NULL; | ||
217 | } | ||
218 | return ERR_PTR (size); | ||
219 | } | ||
220 | |||
221 | value = kmalloc (size, GFP_NOFS); | ||
222 | if (!value) | ||
223 | return ERR_PTR (-ENOMEM); | ||
224 | |||
225 | retval = reiserfs_xattr_get(inode, name, value, size); | ||
226 | if (retval == -ENODATA || retval == -ENOSYS) { | ||
227 | /* This shouldn't actually happen as it should have | ||
228 | been caught above.. but just in case */ | ||
229 | acl = NULL; | ||
230 | *p_acl = ERR_PTR (-ENODATA); | ||
231 | } else if (retval < 0) { | ||
232 | acl = ERR_PTR(retval); | ||
233 | } else { | ||
234 | acl = posix_acl_from_disk(value, retval); | ||
235 | *p_acl = posix_acl_dup (acl); | ||
236 | } | ||
237 | |||
238 | kfree(value); | ||
239 | return acl; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * Inode operation set_posix_acl(). | ||
244 | * | ||
245 | * inode->i_sem: down | ||
246 | * BKL held [before 2.5.x] | ||
247 | */ | ||
248 | static int | ||
249 | reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | ||
250 | { | ||
251 | char *name; | ||
252 | void *value = NULL; | ||
253 | struct posix_acl **p_acl; | ||
254 | size_t size; | ||
255 | int error; | ||
256 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); | ||
257 | |||
258 | if (S_ISLNK(inode->i_mode)) | ||
259 | return -EOPNOTSUPP; | ||
260 | |||
261 | switch (type) { | ||
262 | case ACL_TYPE_ACCESS: | ||
263 | name = XATTR_NAME_ACL_ACCESS; | ||
264 | p_acl = &reiserfs_i->i_acl_access; | ||
265 | if (acl) { | ||
266 | mode_t mode = inode->i_mode; | ||
267 | error = posix_acl_equiv_mode (acl, &mode); | ||
268 | if (error < 0) | ||
269 | return error; | ||
270 | else { | ||
271 | inode->i_mode = mode; | ||
272 | if (error == 0) | ||
273 | acl = NULL; | ||
274 | } | ||
275 | } | ||
276 | break; | ||
277 | case ACL_TYPE_DEFAULT: | ||
278 | name = XATTR_NAME_ACL_DEFAULT; | ||
279 | p_acl = &reiserfs_i->i_acl_default; | ||
280 | if (!S_ISDIR (inode->i_mode)) | ||
281 | return acl ? -EACCES : 0; | ||
282 | break; | ||
283 | default: | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | |||
287 | if (acl) { | ||
288 | value = posix_acl_to_disk(acl, &size); | ||
289 | if (IS_ERR(value)) | ||
290 | return (int)PTR_ERR(value); | ||
291 | error = reiserfs_xattr_set(inode, name, value, size, 0); | ||
292 | } else { | ||
293 | error = reiserfs_xattr_del (inode, name); | ||
294 | if (error == -ENODATA) { | ||
295 | /* This may seem odd here, but it means that the ACL was set | ||
296 | * with a value representable with mode bits. If there was | ||
297 | * an ACL before, reiserfs_xattr_del already dirtied the inode. | ||
298 | */ | ||
299 | mark_inode_dirty (inode); | ||
300 | error = 0; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | if (value) | ||
305 | kfree(value); | ||
306 | |||
307 | if (!error) { | ||
308 | /* Release the old one */ | ||
309 | if (!IS_ERR (*p_acl) && *p_acl) | ||
310 | posix_acl_release (*p_acl); | ||
311 | |||
312 | if (acl == NULL) | ||
313 | *p_acl = ERR_PTR (-ENODATA); | ||
314 | else | ||
315 | *p_acl = posix_acl_dup (acl); | ||
316 | } | ||
317 | |||
318 | return error; | ||
319 | } | ||
320 | |||
321 | /* dir->i_sem: down, | ||
322 | * inode is new and not released into the wild yet */ | ||
323 | int | ||
324 | reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode) | ||
325 | { | ||
326 | struct posix_acl *acl; | ||
327 | int err = 0; | ||
328 | |||
329 | /* ACLs only get applied to files and directories */ | ||
330 | if (S_ISLNK (inode->i_mode)) | ||
331 | return 0; | ||
332 | |||
333 | /* ACLs can only be used on "new" objects, so if it's an old object | ||
334 | * there is nothing to inherit from */ | ||
335 | if (get_inode_sd_version (dir) == STAT_DATA_V1) | ||
336 | goto apply_umask; | ||
337 | |||
338 | /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This | ||
339 | * would be useless since permissions are ignored, and a pain because | ||
340 | * it introduces locking cycles */ | ||
341 | if (is_reiserfs_priv_object (dir)) { | ||
342 | reiserfs_mark_inode_private (inode); | ||
343 | goto apply_umask; | ||
344 | } | ||
345 | |||
346 | acl = reiserfs_get_acl (dir, ACL_TYPE_DEFAULT); | ||
347 | if (IS_ERR (acl)) { | ||
348 | if (PTR_ERR (acl) == -ENODATA) | ||
349 | goto apply_umask; | ||
350 | return PTR_ERR (acl); | ||
351 | } | ||
352 | |||
353 | if (acl) { | ||
354 | struct posix_acl *acl_copy; | ||
355 | mode_t mode = inode->i_mode; | ||
356 | int need_acl; | ||
357 | |||
358 | /* Copy the default ACL to the default ACL of a new directory */ | ||
359 | if (S_ISDIR (inode->i_mode)) { | ||
360 | err = reiserfs_set_acl (inode, ACL_TYPE_DEFAULT, acl); | ||
361 | if (err) | ||
362 | goto cleanup; | ||
363 | } | ||
364 | |||
365 | /* Now we reconcile the new ACL and the mode, | ||
366 | potentially modifying both */ | ||
367 | acl_copy = posix_acl_clone (acl, GFP_NOFS); | ||
368 | if (!acl_copy) { | ||
369 | err = -ENOMEM; | ||
370 | goto cleanup; | ||
371 | } | ||
372 | |||
373 | |||
374 | need_acl = posix_acl_create_masq (acl_copy, &mode); | ||
375 | if (need_acl >= 0) { | ||
376 | if (mode != inode->i_mode) { | ||
377 | inode->i_mode = mode; | ||
378 | } | ||
379 | |||
380 | /* If we need an ACL.. */ | ||
381 | if (need_acl > 0) { | ||
382 | err = reiserfs_set_acl (inode, ACL_TYPE_ACCESS, acl_copy); | ||
383 | if (err) | ||
384 | goto cleanup_copy; | ||
385 | } | ||
386 | } | ||
387 | cleanup_copy: | ||
388 | posix_acl_release (acl_copy); | ||
389 | cleanup: | ||
390 | posix_acl_release (acl); | ||
391 | } else { | ||
392 | apply_umask: | ||
393 | /* no ACL, apply umask */ | ||
394 | inode->i_mode &= ~current->fs->umask; | ||
395 | } | ||
396 | |||
397 | return err; | ||
398 | } | ||
399 | |||
400 | /* Looks up and caches the result of the default ACL. | ||
401 | * We do this so that we don't need to carry the xattr_sem into | ||
402 | * reiserfs_new_inode if we don't need to */ | ||
403 | int | ||
404 | reiserfs_cache_default_acl (struct inode *inode) | ||
405 | { | ||
406 | int ret = 0; | ||
407 | if (reiserfs_posixacl (inode->i_sb) && | ||
408 | !is_reiserfs_priv_object (inode)) { | ||
409 | struct posix_acl *acl; | ||
410 | reiserfs_read_lock_xattr_i (inode); | ||
411 | reiserfs_read_lock_xattrs (inode->i_sb); | ||
412 | acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT); | ||
413 | reiserfs_read_unlock_xattrs (inode->i_sb); | ||
414 | reiserfs_read_unlock_xattr_i (inode); | ||
415 | ret = acl ? 1 : 0; | ||
416 | posix_acl_release (acl); | ||
417 | } | ||
418 | |||
419 | return ret; | ||
420 | } | ||
421 | |||
422 | int | ||
423 | reiserfs_acl_chmod (struct inode *inode) | ||
424 | { | ||
425 | struct posix_acl *acl, *clone; | ||
426 | int error; | ||
427 | |||
428 | if (S_ISLNK(inode->i_mode)) | ||
429 | return -EOPNOTSUPP; | ||
430 | |||
431 | if (get_inode_sd_version (inode) == STAT_DATA_V1 || | ||
432 | !reiserfs_posixacl(inode->i_sb)) | ||
433 | { | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | reiserfs_read_lock_xattrs (inode->i_sb); | ||
438 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
439 | reiserfs_read_unlock_xattrs (inode->i_sb); | ||
440 | if (!acl) | ||
441 | return 0; | ||
442 | if (IS_ERR(acl)) | ||
443 | return PTR_ERR(acl); | ||
444 | clone = posix_acl_clone(acl, GFP_NOFS); | ||
445 | posix_acl_release(acl); | ||
446 | if (!clone) | ||
447 | return -ENOMEM; | ||
448 | error = posix_acl_chmod_masq(clone, inode->i_mode); | ||
449 | if (!error) { | ||
450 | int lock = !has_xattr_dir (inode); | ||
451 | reiserfs_write_lock_xattr_i (inode); | ||
452 | if (lock) | ||
453 | reiserfs_write_lock_xattrs (inode->i_sb); | ||
454 | else | ||
455 | reiserfs_read_lock_xattrs (inode->i_sb); | ||
456 | error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); | ||
457 | if (lock) | ||
458 | reiserfs_write_unlock_xattrs (inode->i_sb); | ||
459 | else | ||
460 | reiserfs_read_unlock_xattrs (inode->i_sb); | ||
461 | reiserfs_write_unlock_xattr_i (inode); | ||
462 | } | ||
463 | posix_acl_release(clone); | ||
464 | return error; | ||
465 | } | ||
466 | |||
467 | static int | ||
468 | posix_acl_access_get(struct inode *inode, const char *name, | ||
469 | void *buffer, size_t size) | ||
470 | { | ||
471 | if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | ||
472 | return -EINVAL; | ||
473 | return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); | ||
474 | } | ||
475 | |||
476 | static int | ||
477 | posix_acl_access_set(struct inode *inode, const char *name, | ||
478 | const void *value, size_t size, int flags) | ||
479 | { | ||
480 | if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | ||
481 | return -EINVAL; | ||
482 | return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); | ||
483 | } | ||
484 | |||
485 | static int | ||
486 | posix_acl_access_del (struct inode *inode, const char *name) | ||
487 | { | ||
488 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); | ||
489 | struct posix_acl **acl = &reiserfs_i->i_acl_access; | ||
490 | if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | ||
491 | return -EINVAL; | ||
492 | if (!IS_ERR (*acl) && *acl) { | ||
493 | posix_acl_release (*acl); | ||
494 | *acl = ERR_PTR (-ENODATA); | ||
495 | } | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static int | ||
501 | posix_acl_access_list (struct inode *inode, const char *name, int namelen, char *out) | ||
502 | { | ||
503 | int len = namelen; | ||
504 | if (!reiserfs_posixacl (inode->i_sb)) | ||
505 | return 0; | ||
506 | if (out) | ||
507 | memcpy (out, name, len); | ||
508 | |||
509 | return len; | ||
510 | } | ||
511 | |||
512 | struct reiserfs_xattr_handler posix_acl_access_handler = { | ||
513 | .prefix = XATTR_NAME_ACL_ACCESS, | ||
514 | .get = posix_acl_access_get, | ||
515 | .set = posix_acl_access_set, | ||
516 | .del = posix_acl_access_del, | ||
517 | .list = posix_acl_access_list, | ||
518 | }; | ||
519 | |||
520 | static int | ||
521 | posix_acl_default_get (struct inode *inode, const char *name, | ||
522 | void *buffer, size_t size) | ||
523 | { | ||
524 | if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | ||
525 | return -EINVAL; | ||
526 | return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); | ||
527 | } | ||
528 | |||
529 | static int | ||
530 | posix_acl_default_set(struct inode *inode, const char *name, | ||
531 | const void *value, size_t size, int flags) | ||
532 | { | ||
533 | if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | ||
534 | return -EINVAL; | ||
535 | return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); | ||
536 | } | ||
537 | |||
538 | static int | ||
539 | posix_acl_default_del (struct inode *inode, const char *name) | ||
540 | { | ||
541 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); | ||
542 | struct posix_acl **acl = &reiserfs_i->i_acl_default; | ||
543 | if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | ||
544 | return -EINVAL; | ||
545 | if (!IS_ERR (*acl) && *acl) { | ||
546 | posix_acl_release (*acl); | ||
547 | *acl = ERR_PTR (-ENODATA); | ||
548 | } | ||
549 | |||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | static int | ||
554 | posix_acl_default_list (struct inode *inode, const char *name, int namelen, char *out) | ||
555 | { | ||
556 | int len = namelen; | ||
557 | if (!reiserfs_posixacl (inode->i_sb)) | ||
558 | return 0; | ||
559 | if (out) | ||
560 | memcpy (out, name, len); | ||
561 | |||
562 | return len; | ||
563 | } | ||
564 | |||
565 | struct reiserfs_xattr_handler posix_acl_default_handler = { | ||
566 | .prefix = XATTR_NAME_ACL_DEFAULT, | ||
567 | .get = posix_acl_default_get, | ||
568 | .set = posix_acl_default_set, | ||
569 | .del = posix_acl_default_del, | ||
570 | .list = posix_acl_default_list, | ||
571 | }; | ||