aboutsummaryrefslogtreecommitdiffstats
path: root/fs/generic_acl.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /fs/generic_acl.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/generic_acl.c')
-rw-r--r--fs/generic_acl.c159
1 files changed, 90 insertions, 69 deletions
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index e0b53aa7bbec..fe5df5457656 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -1,62 +1,59 @@
1/* 1/*
2 * fs/generic_acl.c
3 *
4 * (C) 2005 Andreas Gruenbacher <agruen@suse.de> 2 * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
5 * 3 *
6 * This file is released under the GPL. 4 * This file is released under the GPL.
5 *
6 * Generic ACL support for in-memory filesystems.
7 */ 7 */
8 8
9#include <linux/sched.h> 9#include <linux/sched.h>
10#include <linux/gfp.h>
10#include <linux/fs.h> 11#include <linux/fs.h>
11#include <linux/generic_acl.h> 12#include <linux/generic_acl.h>
13#include <linux/posix_acl.h>
14#include <linux/posix_acl_xattr.h>
12 15
13/** 16
14 * generic_acl_list - Generic xattr_handler->list() operation 17static size_t
15 * @ops: Filesystem specific getacl and setacl callbacks 18generic_acl_list(struct dentry *dentry, char *list, size_t list_size,
16 */ 19 const char *name, size_t name_len, int type)
17size_t
18generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
19 int type, char *list, size_t list_size)
20{ 20{
21 struct posix_acl *acl; 21 struct posix_acl *acl;
22 const char *name; 22 const char *xname;
23 size_t size; 23 size_t size;
24 24
25 acl = ops->getacl(inode, type); 25 acl = get_cached_acl(dentry->d_inode, type);
26 if (!acl) 26 if (!acl)
27 return 0; 27 return 0;
28 posix_acl_release(acl); 28 posix_acl_release(acl);
29 29
30 switch(type) { 30 switch (type) {
31 case ACL_TYPE_ACCESS: 31 case ACL_TYPE_ACCESS:
32 name = POSIX_ACL_XATTR_ACCESS; 32 xname = POSIX_ACL_XATTR_ACCESS;
33 break; 33 break;
34 34 case ACL_TYPE_DEFAULT:
35 case ACL_TYPE_DEFAULT: 35 xname = POSIX_ACL_XATTR_DEFAULT;
36 name = POSIX_ACL_XATTR_DEFAULT; 36 break;
37 break; 37 default:
38 38 return 0;
39 default:
40 return 0;
41 } 39 }
42 size = strlen(name) + 1; 40 size = strlen(xname) + 1;
43 if (list && size <= list_size) 41 if (list && size <= list_size)
44 memcpy(list, name, size); 42 memcpy(list, xname, size);
45 return size; 43 return size;
46} 44}
47 45
48/** 46static int
49 * generic_acl_get - Generic xattr_handler->get() operation 47generic_acl_get(struct dentry *dentry, const char *name, void *buffer,
50 * @ops: Filesystem specific getacl and setacl callbacks 48 size_t size, int type)
51 */
52int
53generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
54 int type, void *buffer, size_t size)
55{ 49{
56 struct posix_acl *acl; 50 struct posix_acl *acl;
57 int error; 51 int error;
58 52
59 acl = ops->getacl(inode, type); 53 if (strcmp(name, "") != 0)
54 return -EINVAL;
55
56 acl = get_cached_acl(dentry->d_inode, type);
60 if (!acl) 57 if (!acl)
61 return -ENODATA; 58 return -ENODATA;
62 error = posix_acl_to_xattr(acl, buffer, size); 59 error = posix_acl_to_xattr(acl, buffer, size);
@@ -65,17 +62,16 @@ generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
65 return error; 62 return error;
66} 63}
67 64
68/** 65static int
69 * generic_acl_set - Generic xattr_handler->set() operation 66generic_acl_set(struct dentry *dentry, const char *name, const void *value,
70 * @ops: Filesystem specific getacl and setacl callbacks 67 size_t size, int flags, int type)
71 */
72int
73generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
74 int type, const void *value, size_t size)
75{ 68{
69 struct inode *inode = dentry->d_inode;
76 struct posix_acl *acl = NULL; 70 struct posix_acl *acl = NULL;
77 int error; 71 int error;
78 72
73 if (strcmp(name, "") != 0)
74 return -EINVAL;
79 if (S_ISLNK(inode->i_mode)) 75 if (S_ISLNK(inode->i_mode))
80 return -EOPNOTSUPP; 76 return -EOPNOTSUPP;
81 if (!is_owner_or_cap(inode)) 77 if (!is_owner_or_cap(inode))
@@ -91,28 +87,27 @@ generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
91 error = posix_acl_valid(acl); 87 error = posix_acl_valid(acl);
92 if (error) 88 if (error)
93 goto failed; 89 goto failed;
94 switch(type) { 90 switch (type) {
95 case ACL_TYPE_ACCESS: 91 case ACL_TYPE_ACCESS:
96 mode = inode->i_mode; 92 mode = inode->i_mode;
97 error = posix_acl_equiv_mode(acl, &mode); 93 error = posix_acl_equiv_mode(acl, &mode);
98 if (error < 0) 94 if (error < 0)
99 goto failed; 95 goto failed;
100 inode->i_mode = mode; 96 inode->i_mode = mode;
101 if (error == 0) { 97 if (error == 0) {
102 posix_acl_release(acl); 98 posix_acl_release(acl);
103 acl = NULL; 99 acl = NULL;
104 } 100 }
105 break; 101 break;
106 102 case ACL_TYPE_DEFAULT:
107 case ACL_TYPE_DEFAULT: 103 if (!S_ISDIR(inode->i_mode)) {
108 if (!S_ISDIR(inode->i_mode)) { 104 error = -EINVAL;
109 error = -EINVAL; 105 goto failed;
110 goto failed; 106 }
111 } 107 break;
112 break;
113 } 108 }
114 } 109 }
115 ops->setacl(inode, type, acl); 110 set_cached_acl(inode, type, acl);
116 error = 0; 111 error = 0;
117failed: 112failed:
118 posix_acl_release(acl); 113 posix_acl_release(acl);
@@ -121,14 +116,12 @@ failed:
121 116
122/** 117/**
123 * generic_acl_init - Take care of acl inheritance at @inode create time 118 * generic_acl_init - Take care of acl inheritance at @inode create time
124 * @ops: Filesystem specific getacl and setacl callbacks
125 * 119 *
126 * Files created inside a directory with a default ACL inherit the 120 * Files created inside a directory with a default ACL inherit the
127 * directory's default ACL. 121 * directory's default ACL.
128 */ 122 */
129int 123int
130generic_acl_init(struct inode *inode, struct inode *dir, 124generic_acl_init(struct inode *inode, struct inode *dir)
131 struct generic_acl_operations *ops)
132{ 125{
133 struct posix_acl *acl = NULL; 126 struct posix_acl *acl = NULL;
134 mode_t mode = inode->i_mode; 127 mode_t mode = inode->i_mode;
@@ -136,7 +129,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
136 129
137 inode->i_mode = mode & ~current_umask(); 130 inode->i_mode = mode & ~current_umask();
138 if (!S_ISLNK(inode->i_mode)) 131 if (!S_ISLNK(inode->i_mode))
139 acl = ops->getacl(dir, ACL_TYPE_DEFAULT); 132 acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
140 if (acl) { 133 if (acl) {
141 struct posix_acl *clone; 134 struct posix_acl *clone;
142 135
@@ -145,7 +138,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
145 error = -ENOMEM; 138 error = -ENOMEM;
146 if (!clone) 139 if (!clone)
147 goto cleanup; 140 goto cleanup;
148 ops->setacl(inode, ACL_TYPE_DEFAULT, clone); 141 set_cached_acl(inode, ACL_TYPE_DEFAULT, clone);
149 posix_acl_release(clone); 142 posix_acl_release(clone);
150 } 143 }
151 clone = posix_acl_clone(acl, GFP_KERNEL); 144 clone = posix_acl_clone(acl, GFP_KERNEL);
@@ -156,7 +149,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
156 if (error >= 0) { 149 if (error >= 0) {
157 inode->i_mode = mode; 150 inode->i_mode = mode;
158 if (error > 0) 151 if (error > 0)
159 ops->setacl(inode, ACL_TYPE_ACCESS, clone); 152 set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
160 } 153 }
161 posix_acl_release(clone); 154 posix_acl_release(clone);
162 } 155 }
@@ -169,20 +162,19 @@ cleanup:
169 162
170/** 163/**
171 * generic_acl_chmod - change the access acl of @inode upon chmod() 164 * generic_acl_chmod - change the access acl of @inode upon chmod()
172 * @ops: FIlesystem specific getacl and setacl callbacks
173 * 165 *
174 * A chmod also changes the permissions of the owner, group/mask, and 166 * A chmod also changes the permissions of the owner, group/mask, and
175 * other ACL entries. 167 * other ACL entries.
176 */ 168 */
177int 169int
178generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops) 170generic_acl_chmod(struct inode *inode)
179{ 171{
180 struct posix_acl *acl, *clone; 172 struct posix_acl *acl, *clone;
181 int error = 0; 173 int error = 0;
182 174
183 if (S_ISLNK(inode->i_mode)) 175 if (S_ISLNK(inode->i_mode))
184 return -EOPNOTSUPP; 176 return -EOPNOTSUPP;
185 acl = ops->getacl(inode, ACL_TYPE_ACCESS); 177 acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
186 if (acl) { 178 if (acl) {
187 clone = posix_acl_clone(acl, GFP_KERNEL); 179 clone = posix_acl_clone(acl, GFP_KERNEL);
188 posix_acl_release(acl); 180 posix_acl_release(acl);
@@ -190,8 +182,37 @@ generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
190 return -ENOMEM; 182 return -ENOMEM;
191 error = posix_acl_chmod_masq(clone, inode->i_mode); 183 error = posix_acl_chmod_masq(clone, inode->i_mode);
192 if (!error) 184 if (!error)
193 ops->setacl(inode, ACL_TYPE_ACCESS, clone); 185 set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
194 posix_acl_release(clone); 186 posix_acl_release(clone);
195 } 187 }
196 return error; 188 return error;
197} 189}
190
191int
192generic_check_acl(struct inode *inode, int mask)
193{
194 struct posix_acl *acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
195
196 if (acl) {
197 int error = posix_acl_permission(inode, acl, mask);
198 posix_acl_release(acl);
199 return error;
200 }
201 return -EAGAIN;
202}
203
204struct xattr_handler generic_acl_access_handler = {
205 .prefix = POSIX_ACL_XATTR_ACCESS,
206 .flags = ACL_TYPE_ACCESS,
207 .list = generic_acl_list,
208 .get = generic_acl_get,
209 .set = generic_acl_set,
210};
211
212struct xattr_handler generic_acl_default_handler = {
213 .prefix = POSIX_ACL_XATTR_DEFAULT,
214 .flags = ACL_TYPE_DEFAULT,
215 .list = generic_acl_list,
216 .get = generic_acl_get,
217 .set = generic_acl_set,
218};