]>
Commit | Line | Data |
---|---|---|
f701fa52 AM |
1 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/Makefile linux-2.4.23.xattr/Makefile |
2 | --- linux-2.4.23.datalogging+quota/Makefile 2003-12-11 12:53:17.834531104 -0500 | |
3 | +++ linux-2.4.23.xattr/Makefile 2003-12-11 13:03:06.815992312 -0500 | |
4 | @@ -92,7 +92,7 @@ export MODLIB | |
5 | CPPFLAGS := -D__KERNEL__ -I$(HPATH) | |
6 | ||
7 | CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ | |
8 | - -fno-strict-aliasing -fno-common | |
9 | + -fno-strict-aliasing -fno-common -Wno-sign-compare | |
10 | ifndef CONFIG_FRAME_POINTER | |
11 | CFLAGS += -fomit-frame-pointer | |
12 | endif | |
13 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/Config.in linux-2.4.23.xattr/fs/Config.in | |
14 | --- linux-2.4.23.datalogging+quota/fs/Config.in 2003-12-11 13:00:09.957878832 -0500 | |
15 | +++ linux-2.4.23.xattr/fs/Config.in 2003-12-11 13:00:17.428743088 -0500 | |
16 | @@ -15,6 +15,7 @@ dep_mbool ' Enable reiserfs debug mode' | |
17 | dep_mbool ' Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS | |
18 | dep_mbool ' ReiserFS extended attributes' CONFIG_REISERFS_FS_XATTR $CONFIG_REISERFS_FS | |
19 | dep_mbool ' ReiserFS extended user attributes' CONFIG_REISERFS_FS_XATTR_USER $CONFIG_REISERFS_FS_XATTR | |
20 | +dep_mbool ' ReiserFS POSIX Access Control Lists' CONFIG_REISERFS_FS_POSIX_ACL $CONFIG_REISERFS_FS_XATTR $CONFIG_FS_POSIX_ACL | |
21 | ||
22 | dep_tristate 'ADFS file system support (EXPERIMENTAL)' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL | |
23 | dep_mbool ' ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL | |
24 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/Makefile linux-2.4.23.xattr/fs/reiserfs/Makefile | |
25 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/Makefile 2003-12-11 13:00:09.958878680 -0500 | |
26 | +++ linux-2.4.23.xattr/fs/reiserfs/Makefile 2003-12-11 13:00:17.429742936 -0500 | |
27 | @@ -14,6 +14,7 @@ lbalance.o ibalance.o stree.o hashes.o b | |
28 | ||
29 | obj-$(CONFIG_REISERFS_FS_XATTR) += xattr.o | |
30 | obj-$(CONFIG_REISERFS_FS_XATTR_USER) += xattr_user.o | |
31 | +obj-$(CONFIG_REISERFS_FS_POSIX_ACL) += xattr_acl.o | |
32 | ||
33 | obj-m := $(O_TARGET) | |
34 | ||
35 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/file.c linux-2.4.23.xattr/fs/reiserfs/file.c | |
36 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/file.c 2003-12-11 13:00:09.958878680 -0500 | |
37 | +++ linux-2.4.23.xattr/fs/reiserfs/file.c 2003-12-11 13:00:17.429742936 -0500 | |
38 | @@ -5,6 +5,7 @@ | |
39 | ||
40 | #include <linux/sched.h> | |
41 | #include <linux/reiserfs_fs.h> | |
42 | +#include <linux/reiserfs_acl.h> | |
43 | #include <linux/reiserfs_xattr.h> | |
44 | #include <linux/smp_lock.h> | |
45 | #include <linux/quotaops.h> | |
46 | @@ -178,6 +179,7 @@ struct inode_operations reiserfs_file_i | |
47 | getxattr: reiserfs_getxattr, | |
48 | listxattr: reiserfs_listxattr, | |
49 | removexattr: reiserfs_removexattr, | |
50 | + permission: reiserfs_permission, | |
51 | }; | |
52 | ||
53 | ||
54 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/inode.c linux-2.4.23.xattr/fs/reiserfs/inode.c | |
55 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/inode.c 2003-12-11 13:00:09.961878224 -0500 | |
56 | +++ linux-2.4.23.xattr/fs/reiserfs/inode.c 2003-12-11 13:04:08.957545360 -0500 | |
57 | @@ -7,6 +7,7 @@ | |
58 | #include <linux/fs.h> | |
59 | #include <linux/reiserfs_fs.h> | |
60 | #include <linux/reiserfs_xattr.h> | |
61 | +#include <linux/reiserfs_acl.h> | |
62 | #include <linux/quotaops.h> | |
63 | #include <linux/locks.h> | |
64 | #include <linux/smp_lock.h> | |
65 | @@ -1851,6 +1852,18 @@ int reiserfs_new_inode (struct reiserfs_ | |
66 | goto out_inserted_sd; | |
67 | } | |
68 | ||
69 | + if (reiserfs_posixacl (inode->i_sb)) { | |
70 | + retval = reiserfs_inherit_default_acl (dir, dentry, inode); | |
71 | + if (retval) { | |
72 | + iput (inode); | |
73 | + err = retval; | |
74 | + reiserfs_check_path(&path_to_key) ; | |
75 | + goto out_inserted_sd; | |
76 | + } | |
77 | + } else if (inode->i_sb->s_flags & MS_POSIXACL) { | |
78 | + reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, but vfs thinks they are!\n"); | |
79 | + } | |
80 | + | |
81 | insert_inode_hash (inode); | |
82 | reiserfs_update_sd(th, inode) ; | |
83 | reiserfs_check_path(&path_to_key) ; | |
84 | @@ -2753,6 +2766,15 @@ int reiserfs_setattr(struct dentry *dent | |
85 | ||
86 | if (!error) | |
87 | error = inode_setattr(inode, attr) ; | |
88 | + if (!error && reiserfs_posixacl (inode->i_sb)) { | |
89 | + if (attr->ia_valid & ATTR_MODE) { | |
90 | + if (!(attr->ia_valid & ATTR_SIZE)) | |
91 | + down (&inode->i_sem); | |
92 | + error = reiserfs_acl_chmod (inode); | |
93 | + if (!(attr->ia_valid & ATTR_SIZE)) | |
94 | + up (&inode->i_sem); | |
95 | + } | |
96 | + } | |
97 | } | |
98 | return error ; | |
99 | } | |
100 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/namei.c linux-2.4.23.xattr/fs/reiserfs/namei.c | |
101 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/namei.c 2003-12-11 13:00:09.962878072 -0500 | |
102 | +++ linux-2.4.23.xattr/fs/reiserfs/namei.c 2003-12-11 13:00:17.434742176 -0500 | |
103 | @@ -6,6 +6,7 @@ | |
104 | #include <linux/sched.h> | |
105 | #include <linux/bitops.h> | |
106 | #include <linux/reiserfs_fs.h> | |
107 | +#include <linux/reiserfs_acl.h> | |
108 | #include <linux/reiserfs_xattr.h> | |
109 | #include <linux/smp_lock.h> | |
110 | #include <linux/quotaops.h> | |
111 | @@ -546,6 +547,7 @@ static int reiserfs_create (struct inode | |
112 | struct inode * inode; | |
113 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ; | |
114 | struct reiserfs_transaction_handle th ; | |
115 | + int locked; | |
116 | ||
117 | if (!(inode = new_inode(dir->i_sb))) { | |
118 | return -ENOMEM ; | |
119 | @@ -554,6 +556,10 @@ static int reiserfs_create (struct inode | |
120 | if (retval) | |
121 | return retval ; | |
122 | ||
123 | + locked = reiserfs_cache_default_acl (dir); | |
124 | + if (locked) | |
125 | + reiserfs_write_lock_xattrs (dir->i_sb); | |
126 | + | |
127 | journal_begin(&th, dir->i_sb, jbegin_count) ; | |
128 | retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); | |
129 | if (retval) { | |
130 | @@ -566,6 +572,9 @@ static int reiserfs_create (struct inode | |
131 | ||
132 | retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, | |
133 | inode, 1/*visible*/); | |
134 | + if (locked) | |
135 | + reiserfs_write_unlock_xattrs (dir->i_sb); | |
136 | + | |
137 | if (retval) { | |
138 | inode->i_nlink--; | |
139 | reiserfs_update_sd (&th, inode); | |
140 | @@ -591,6 +600,7 @@ static int reiserfs_mknod (struct inode | |
141 | struct inode * inode; | |
142 | struct reiserfs_transaction_handle th ; | |
143 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; | |
144 | + int locked; | |
145 | ||
146 | if (!(inode = new_inode(dir->i_sb))) { | |
147 | return -ENOMEM ; | |
148 | @@ -599,9 +609,17 @@ static int reiserfs_mknod (struct inode | |
149 | if (retval) | |
150 | return retval ; | |
151 | ||
152 | + locked = reiserfs_cache_default_acl (dir); | |
153 | + if (locked) | |
154 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
155 | + | |
156 | journal_begin(&th, dir->i_sb, jbegin_count) ; | |
157 | ||
158 | retval = reiserfs_new_inode(&th, dir, mode, 0, 0/*i_size*/, dentry, inode); | |
159 | + | |
160 | + if (locked) | |
161 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
162 | + | |
163 | if (retval) { | |
164 | goto out_failed; | |
165 | } | |
166 | @@ -639,6 +657,7 @@ static int reiserfs_mkdir (struct inode | |
167 | struct inode * inode; | |
168 | struct reiserfs_transaction_handle th ; | |
169 | int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; | |
170 | + int locked; | |
171 | ||
172 | mode = S_IFDIR | mode; | |
173 | if (!(inode = new_inode(dir->i_sb))) { | |
174 | @@ -648,6 +667,10 @@ static int reiserfs_mkdir (struct inode | |
175 | if (retval) | |
176 | return retval ; | |
177 | ||
178 | + locked = reiserfs_cache_default_acl (dir); | |
179 | + if (locked) | |
180 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
181 | + | |
182 | journal_begin(&th, dir->i_sb, jbegin_count) ; | |
183 | ||
184 | /* inc the link count now, so another writer doesn't overflow it while | |
185 | @@ -663,6 +686,9 @@ static int reiserfs_mkdir (struct inode | |
186 | old_format_only (dir->i_sb) ? | |
187 | EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, | |
188 | dentry, inode) ; | |
189 | + if (locked) | |
190 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
191 | + | |
192 | if (retval) { | |
193 | dir->i_nlink-- ; | |
194 | goto out_failed ; | |
195 | @@ -908,6 +934,8 @@ static int reiserfs_symlink (struct inod | |
196 | memcpy (name, symname, strlen (symname)); | |
197 | padd_item (name, item_len, strlen (symname)); | |
198 | ||
199 | + /* We would inherit the default ACL here, but symlinks don't get ACLs */ | |
200 | + | |
201 | journal_begin(&th, parent_dir->i_sb, jbegin_count) ; | |
202 | ||
203 | retval = reiserfs_new_inode(&th, parent_dir, mode, name, | |
204 | @@ -1297,6 +1325,7 @@ struct inode_operations reiserfs_dir_ino | |
205 | getxattr: reiserfs_getxattr, | |
206 | listxattr: reiserfs_listxattr, | |
207 | removexattr: reiserfs_removexattr, | |
208 | + permission: reiserfs_permission, | |
209 | }; | |
210 | ||
211 | /* | |
212 | @@ -1311,4 +1340,5 @@ struct inode_operations reiserfs_symlink | |
213 | getxattr: reiserfs_getxattr, | |
214 | listxattr: reiserfs_listxattr, | |
215 | removexattr: reiserfs_removexattr, | |
216 | + permission: reiserfs_permission, | |
217 | }; | |
218 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/super.c linux-2.4.23.xattr/fs/reiserfs/super.c | |
219 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/super.c 2003-12-11 13:00:09.963877920 -0500 | |
220 | +++ linux-2.4.23.xattr/fs/reiserfs/super.c 2003-12-11 13:00:17.435742024 -0500 | |
221 | @@ -9,6 +9,7 @@ | |
222 | #include <linux/vmalloc.h> | |
223 | #include <asm/uaccess.h> | |
224 | #include <linux/reiserfs_fs.h> | |
225 | +#include <linux/reiserfs_acl.h> | |
226 | #include <linux/reiserfs_xattr.h> | |
227 | #include <linux/smp_lock.h> | |
228 | #include <linux/locks.h> | |
229 | @@ -430,6 +431,22 @@ static void reiserfs_dirty_inode (struct | |
230 | unlock_kernel() ; | |
231 | } | |
232 | ||
233 | +static void reiserfs_clear_inode (struct inode *inode) | |
234 | +{ | |
235 | + struct posix_acl *acl; | |
236 | + | |
237 | + acl = inode->u.reiserfs_i.i_acl_access; | |
238 | + if (acl && !IS_ERR (acl)) | |
239 | + posix_acl_release (acl); | |
240 | + inode->u.reiserfs_i.i_acl_access = NULL; | |
241 | + | |
242 | + acl = inode->u.reiserfs_i.i_acl_default; | |
243 | + if (acl && !IS_ERR (acl)) | |
244 | + posix_acl_release (acl); | |
245 | + inode->u.reiserfs_i.i_acl_default = NULL; | |
246 | +} | |
247 | + | |
248 | + | |
249 | struct super_operations reiserfs_sops = | |
250 | { | |
251 | read_inode: reiserfs_read_inode, | |
252 | @@ -437,6 +454,7 @@ struct super_operations reiserfs_sops = | |
253 | write_inode: reiserfs_write_inode, | |
254 | dirty_inode: reiserfs_dirty_inode, | |
255 | delete_inode: reiserfs_delete_inode, | |
256 | + clear_inode: reiserfs_clear_inode, | |
257 | put_super: reiserfs_put_super, | |
258 | write_super: reiserfs_write_super, | |
259 | write_super_lockfs: reiserfs_write_super_lockfs, | |
260 | @@ -655,6 +673,10 @@ static int reiserfs_parse_options (struc | |
261 | {"user_xattr", 0, 0, 1<<REISERFS_XATTRS_USER, 0}, | |
262 | {"nouser_xattr", 0, 0, 0, 1<<REISERFS_XATTRS_USER}, | |
263 | # endif | |
264 | +# ifdef CONFIG_REISERFS_FS_POSIX_ACL | |
265 | + {"acl", 0, 0, 1<<REISERFS_POSIXACL, 0}, | |
266 | + {"noacl", 0, 0, 0, 1<<REISERFS_POSIXACL}, | |
267 | +# endif | |
268 | #endif | |
269 | {NULL, 0, 0, 0, 0} | |
270 | }; | |
271 | @@ -774,6 +796,7 @@ static int reiserfs_remount (struct supe | |
272 | safe_mask |= 1 << REISERFS_TEST4; | |
273 | safe_mask |= 1 << REISERFS_ATTRS; | |
274 | safe_mask |= 1 << REISERFS_XATTRS_USER; | |
275 | + safe_mask |= 1 << REISERFS_POSIXACL; | |
276 | ||
277 | /* Update the bitmask, taking care to keep | |
278 | * the bits we're not allowed to change here */ | |
279 | @@ -1487,8 +1510,14 @@ static int __init init_reiserfs_fs (void | |
280 | if (ret) | |
281 | goto failed_xattr_user_init; | |
282 | ||
283 | + ret = reiserfs_xattr_posix_acl_init (); | |
284 | + if (ret) | |
285 | + goto failed_xattr_posix_acl_init; | |
286 | + | |
287 | return register_filesystem(&reiserfs_fs_type); | |
288 | ||
289 | +failed_xattr_posix_acl_init: | |
290 | + reiserfs_xattr_user_exit(); | |
291 | failed_xattr_user_init: | |
292 | failed_journal_cache_init: | |
293 | reiserfs_proc_unregister_global( "version" ); | |
294 | @@ -1503,6 +1532,7 @@ MODULE_LICENSE("GPL"); | |
295 | ||
296 | static void __exit exit_reiserfs_fs(void) | |
297 | { | |
298 | + reiserfs_xattr_posix_acl_exit (); | |
299 | reiserfs_xattr_user_exit (); | |
300 | reiserfs_proc_unregister_global( "version" ); | |
301 | reiserfs_proc_info_global_done(); | |
302 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/xattr.c linux-2.4.23.xattr/fs/reiserfs/xattr.c | |
303 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/xattr.c 2003-12-11 13:00:09.966877464 -0500 | |
304 | +++ linux-2.4.23.xattr/fs/reiserfs/xattr.c 2003-12-11 13:00:17.437741720 -0500 | |
305 | @@ -6,7 +6,7 @@ | |
306 | */ | |
307 | ||
308 | /* | |
309 | - * In order to implement EAs in a clean, backwards compatible manner, | |
310 | + * In order to implement EA/ACLs in a clean, backwards compatible manner, | |
311 | * they are implemented as files in a "private" directory. | |
312 | * Each EA is in it's own file, with the directory layout like so (/ is assumed | |
313 | * to be relative to fs root). Inside the /.reiserfs_priv/xattrs directory, | |
314 | @@ -15,12 +15,18 @@ | |
315 | * named with the name of the extended attribute. | |
316 | * | |
317 | * So, for objectid 12648430, we could have: | |
318 | + * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_access | |
319 | + * /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_default | |
320 | * /.reiserfs_priv/xattrs/C0FFEE.0/user.Content-Type | |
321 | * .. or similar. | |
322 | * | |
323 | * The file contents are the text of the EA. The size is known based on the | |
324 | * stat data describing the file. | |
325 | * | |
326 | + * In the case of system.posix_acl_access and system.posix_acl_default, since | |
327 | + * these are special cases for filesystem ACLs, they are interpreted by the | |
328 | + * kernel, in addition, they are negatively and positively cached and attached | |
329 | + * to the inode so that unnecessary lookups are avoided. | |
330 | */ | |
331 | ||
332 | #include <linux/reiserfs_fs.h> | |
333 | @@ -1182,7 +1188,7 @@ reiserfs_xattr_init (struct super_block | |
334 | /* We need generation numbers to ensure that the oid mapping is correct | |
335 | * v3.5 filesystems don't have them. */ | |
336 | if (old_format_only (s)) { | |
337 | - reiserfs_warning (s, "reiserfs: xattrs not supported on pre v3.6 " | |
338 | + reiserfs_warning (s, "reiserfs: xattrs/ACLs not supported on pre v3.6 " | |
339 | "format filesystem. Failing mount.\n"); | |
340 | err = -EOPNOTSUPP; | |
341 | goto error; | |
342 | @@ -1221,7 +1227,7 @@ reiserfs_xattr_init (struct super_block | |
343 | * created. Not an error -- just no xattrs on the fs. We'll | |
344 | * check again if we go read-write */ | |
345 | if (!(mount_flags & MS_RDONLY)) { | |
346 | - reiserfs_warning (s, "reiserfs: xattrs enabled and couldn't " | |
347 | + reiserfs_warning (s, "reiserfs: xattrs/ACLs enabled and couldn't " | |
348 | "find/create .reiserfs_priv. Failing mount.\n"); | |
349 | err = -EOPNOTSUPP; | |
350 | goto error; | |
351 | @@ -1230,6 +1236,7 @@ reiserfs_xattr_init (struct super_block | |
352 | * we're read-only */ | |
353 | clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt)); | |
354 | clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt)); | |
355 | + clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt)); | |
356 | } | |
357 | } | |
358 | } | |
359 | @@ -1241,6 +1248,10 @@ error: | |
360 | if (err) { | |
361 | clear_bit (REISERFS_XATTRS, &(s->u.reiserfs_sb.s_mount_opt)); | |
362 | clear_bit (REISERFS_XATTRS_USER, &(s->u.reiserfs_sb.s_mount_opt)); | |
363 | + clear_bit (REISERFS_POSIXACL, &(s->u.reiserfs_sb.s_mount_opt)); | |
364 | } | |
365 | + | |
366 | + s->s_flags = (s->s_flags & ~MS_POSIXACL) | | |
367 | + (reiserfs_posixacl (s) ? MS_POSIXACL : 0); | |
368 | return err; | |
369 | } | |
370 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/xattr_acl.c linux-2.4.23.xattr/fs/reiserfs/xattr_acl.c | |
371 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/xattr_acl.c 1969-12-31 19:00:00.000000000 -0500 | |
372 | +++ linux-2.4.23.xattr/fs/reiserfs/xattr_acl.c 2003-12-11 13:00:17.438741568 -0500 | |
373 | @@ -0,0 +1,653 @@ | |
374 | +#include <linux/posix_acl.h> | |
375 | +#include <linux/reiserfs_fs.h> | |
376 | +#include <linux/errno.h> | |
377 | +#include <linux/fs.h> | |
378 | +#include <linux/pagemap.h> | |
379 | +#include <linux/xattr.h> | |
380 | +#include <linux/xattr_acl.h> | |
381 | +#include <linux/reiserfs_xattr.h> | |
382 | +#include <linux/reiserfs_acl.h> | |
383 | +#include <asm/uaccess.h> | |
384 | + | |
385 | +static int | |
386 | +xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) | |
387 | +{ | |
388 | + struct posix_acl *acl; | |
389 | + int error; | |
390 | + | |
391 | + if (!reiserfs_posixacl(inode->i_sb)) | |
392 | + return -EOPNOTSUPP; | |
393 | + if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | |
394 | + return -EPERM; | |
395 | + | |
396 | + if (value) { | |
397 | + acl = posix_acl_from_xattr(value, size); | |
398 | + if (IS_ERR(acl)) { | |
399 | + return PTR_ERR(acl); | |
400 | + } else if (acl) { | |
401 | + error = posix_acl_valid(acl); | |
402 | + if (error) | |
403 | + goto release_and_out; | |
404 | + } | |
405 | + } else | |
406 | + acl = NULL; | |
407 | + | |
408 | + error = reiserfs_set_acl (inode, type, acl); | |
409 | + | |
410 | +release_and_out: | |
411 | + posix_acl_release(acl); | |
412 | + return error; | |
413 | +} | |
414 | + | |
415 | + | |
416 | +static int | |
417 | +xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) | |
418 | +{ | |
419 | + struct posix_acl *acl; | |
420 | + int error; | |
421 | + | |
422 | + if (!reiserfs_posixacl(inode->i_sb)) | |
423 | + return -EOPNOTSUPP; | |
424 | + | |
425 | + acl = reiserfs_get_acl (inode, type); | |
426 | + if (IS_ERR(acl)) | |
427 | + return PTR_ERR(acl); | |
428 | + if (acl == NULL) | |
429 | + return -ENODATA; | |
430 | + error = posix_acl_to_xattr(acl, buffer, size); | |
431 | + posix_acl_release(acl); | |
432 | + | |
433 | + return error; | |
434 | +} | |
435 | + | |
436 | + | |
437 | +/* | |
438 | + * Convert from filesystem to in-memory representation. | |
439 | + */ | |
440 | +static struct posix_acl * | |
441 | +posix_acl_from_disk(const void *value, size_t size) | |
442 | +{ | |
443 | + const char *end = (char *)value + size; | |
444 | + int n, count; | |
445 | + struct posix_acl *acl; | |
446 | + | |
447 | + if (!value) | |
448 | + return NULL; | |
449 | + if (size < sizeof(reiserfs_acl_header)) | |
450 | + return ERR_PTR(-EINVAL); | |
451 | + if (((reiserfs_acl_header *)value)->a_version != | |
452 | + cpu_to_le32(REISERFS_ACL_VERSION)) | |
453 | + return ERR_PTR(-EINVAL); | |
454 | + value = (char *)value + sizeof(reiserfs_acl_header); | |
455 | + count = reiserfs_acl_count(size); | |
456 | + if (count < 0) | |
457 | + return ERR_PTR(-EINVAL); | |
458 | + if (count == 0) | |
459 | + return NULL; | |
460 | + acl = posix_acl_alloc(count, GFP_NOFS); | |
461 | + if (!acl) | |
462 | + return ERR_PTR(-ENOMEM); | |
463 | + for (n=0; n < count; n++) { | |
464 | + reiserfs_acl_entry *entry = | |
465 | + (reiserfs_acl_entry *)value; | |
466 | + if ((char *)value + sizeof(reiserfs_acl_entry_short) > end) | |
467 | + goto fail; | |
468 | + acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); | |
469 | + acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); | |
470 | + switch(acl->a_entries[n].e_tag) { | |
471 | + case ACL_USER_OBJ: | |
472 | + case ACL_GROUP_OBJ: | |
473 | + case ACL_MASK: | |
474 | + case ACL_OTHER: | |
475 | + value = (char *)value + | |
476 | + sizeof(reiserfs_acl_entry_short); | |
477 | + acl->a_entries[n].e_id = ACL_UNDEFINED_ID; | |
478 | + break; | |
479 | + | |
480 | + case ACL_USER: | |
481 | + case ACL_GROUP: | |
482 | + value = (char *)value + sizeof(reiserfs_acl_entry); | |
483 | + if ((char *)value > end) | |
484 | + goto fail; | |
485 | + acl->a_entries[n].e_id = | |
486 | + le32_to_cpu(entry->e_id); | |
487 | + break; | |
488 | + | |
489 | + default: | |
490 | + goto fail; | |
491 | + } | |
492 | + } | |
493 | + if (value != end) | |
494 | + goto fail; | |
495 | + return acl; | |
496 | + | |
497 | +fail: | |
498 | + posix_acl_release(acl); | |
499 | + return ERR_PTR(-EINVAL); | |
500 | +} | |
501 | + | |
502 | +/* | |
503 | + * Convert from in-memory to filesystem representation. | |
504 | + */ | |
505 | +static void * | |
506 | +posix_acl_to_disk(const struct posix_acl *acl, size_t *size) | |
507 | +{ | |
508 | + reiserfs_acl_header *ext_acl; | |
509 | + char *e; | |
510 | + int n; | |
511 | + | |
512 | + *size = reiserfs_acl_size(acl->a_count); | |
513 | + ext_acl = (reiserfs_acl_header *)kmalloc(sizeof(reiserfs_acl_header) + | |
514 | + acl->a_count * sizeof(reiserfs_acl_entry), GFP_NOFS); | |
515 | + if (!ext_acl) | |
516 | + return ERR_PTR(-ENOMEM); | |
517 | + ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION); | |
518 | + e = (char *)ext_acl + sizeof(reiserfs_acl_header); | |
519 | + for (n=0; n < acl->a_count; n++) { | |
520 | + reiserfs_acl_entry *entry = (reiserfs_acl_entry *)e; | |
521 | + entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); | |
522 | + entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); | |
523 | + switch(acl->a_entries[n].e_tag) { | |
524 | + case ACL_USER: | |
525 | + case ACL_GROUP: | |
526 | + entry->e_id = | |
527 | + cpu_to_le32(acl->a_entries[n].e_id); | |
528 | + e += sizeof(reiserfs_acl_entry); | |
529 | + break; | |
530 | + | |
531 | + case ACL_USER_OBJ: | |
532 | + case ACL_GROUP_OBJ: | |
533 | + case ACL_MASK: | |
534 | + case ACL_OTHER: | |
535 | + e += sizeof(reiserfs_acl_entry_short); | |
536 | + break; | |
537 | + | |
538 | + default: | |
539 | + goto fail; | |
540 | + } | |
541 | + } | |
542 | + return (char *)ext_acl; | |
543 | + | |
544 | +fail: | |
545 | + kfree(ext_acl); | |
546 | + return ERR_PTR(-EINVAL); | |
547 | +} | |
548 | + | |
549 | +/* | |
550 | + * Inode operation get_posix_acl(). | |
551 | + * | |
552 | + * inode->i_sem: down | |
553 | + * BKL held [before 2.5.x] | |
554 | + */ | |
555 | +struct posix_acl * | |
556 | +reiserfs_get_acl(struct inode *inode, int type) | |
557 | +{ | |
558 | + char *name, *value; | |
559 | + struct posix_acl *acl, **p_acl; | |
560 | + size_t size; | |
561 | + int retval; | |
562 | + | |
563 | + switch (type) { | |
564 | + case ACL_TYPE_ACCESS: | |
565 | + name = XATTR_NAME_ACL_ACCESS; | |
566 | + p_acl = &inode->u.reiserfs_i.i_acl_access; | |
567 | + break; | |
568 | + case ACL_TYPE_DEFAULT: | |
569 | + name = XATTR_NAME_ACL_DEFAULT; | |
570 | + p_acl = &inode->u.reiserfs_i.i_acl_default; | |
571 | + break; | |
572 | + default: | |
573 | + return ERR_PTR (-EINVAL); | |
574 | + } | |
575 | + | |
576 | + if (IS_ERR (*p_acl)) { | |
577 | + if (PTR_ERR (*p_acl) == -ENODATA) | |
578 | + return NULL; | |
579 | + } else if (*p_acl != NULL) | |
580 | + return posix_acl_dup (*p_acl); | |
581 | + | |
582 | + size = reiserfs_xattr_get (inode, name, NULL, 0); | |
583 | + if ((int)size < 0) { | |
584 | + if (size == -ENODATA || size == -ENOSYS) { | |
585 | + *p_acl = ERR_PTR (-ENODATA); | |
586 | + return NULL; | |
587 | + } | |
588 | + return ERR_PTR (size); | |
589 | + } | |
590 | + | |
591 | + value = kmalloc (size, GFP_NOFS); | |
592 | + if (!value) | |
593 | + return ERR_PTR (-ENOMEM); | |
594 | + | |
595 | + retval = reiserfs_xattr_get(inode, name, value, size); | |
596 | + if (retval == -ENODATA || retval == -ENOSYS) { | |
597 | + /* This shouldn't actually happen as it should have | |
598 | + been caught above.. but just in case */ | |
599 | + acl = NULL; | |
600 | + *p_acl = ERR_PTR (-ENODATA); | |
601 | + } else if (retval < 0) { | |
602 | + acl = ERR_PTR(retval); | |
603 | + } else { | |
604 | + acl = posix_acl_from_disk(value, retval); | |
605 | + *p_acl = posix_acl_dup (acl); | |
606 | + } | |
607 | + | |
608 | + kfree(value); | |
609 | + return acl; | |
610 | +} | |
611 | + | |
612 | +/* | |
613 | + * Inode operation set_posix_acl(). | |
614 | + * | |
615 | + * inode->i_sem: down | |
616 | + * BKL held [before 2.5.x] | |
617 | + */ | |
618 | +int | |
619 | +reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |
620 | +{ | |
621 | + char *name; | |
622 | + void *value = NULL; | |
623 | + struct posix_acl **p_acl; | |
624 | + size_t size; | |
625 | + int error; | |
626 | + | |
627 | + if (S_ISLNK(inode->i_mode)) | |
628 | + return -EOPNOTSUPP; | |
629 | + | |
630 | + | |
631 | + switch (type) { | |
632 | + case ACL_TYPE_ACCESS: | |
633 | + name = XATTR_NAME_ACL_ACCESS; | |
634 | + p_acl = &inode->u.reiserfs_i.i_acl_access; | |
635 | + if (acl) { | |
636 | + mode_t mode = inode->i_mode; | |
637 | + error = posix_acl_equiv_mode (acl, &mode); | |
638 | + if (error < 0) | |
639 | + return error; | |
640 | + else { | |
641 | + inode->i_mode = mode; | |
642 | + if (error == 0) | |
643 | + acl = NULL; | |
644 | + } | |
645 | + } | |
646 | + break; | |
647 | + case ACL_TYPE_DEFAULT: | |
648 | + name = XATTR_NAME_ACL_DEFAULT; | |
649 | + p_acl = &inode->u.reiserfs_i.i_acl_default; | |
650 | + if (!S_ISDIR (inode->i_mode)) | |
651 | + return acl ? -EACCES : 0; | |
652 | + break; | |
653 | + default: | |
654 | + return -EINVAL; | |
655 | + } | |
656 | + | |
657 | + if (acl) { | |
658 | + value = posix_acl_to_disk(acl, &size); | |
659 | + if (IS_ERR(value)) | |
660 | + return (int)PTR_ERR(value); | |
661 | + error = reiserfs_xattr_set(inode, name, value, size, 0); | |
662 | + } else { | |
663 | + error = reiserfs_xattr_del (inode, name); | |
664 | + if (error == -ENODATA) | |
665 | + error = 0; | |
666 | + } | |
667 | + | |
668 | + if (value) | |
669 | + kfree(value); | |
670 | + | |
671 | + if (!error) { | |
672 | + /* Release the old one */ | |
673 | + if (!IS_ERR (*p_acl) && *p_acl) | |
674 | + posix_acl_release (*p_acl); | |
675 | + | |
676 | + if (acl == NULL) | |
677 | + *p_acl = ERR_PTR (-ENODATA); | |
678 | + else | |
679 | + *p_acl = posix_acl_dup (acl); | |
680 | + } | |
681 | + | |
682 | + return error; | |
683 | +} | |
684 | + | |
685 | +/* dir->i_sem: down, | |
686 | + * inode is new and not released into the wild yet */ | |
687 | +int | |
688 | +reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode) | |
689 | +{ | |
690 | + struct posix_acl *acl; | |
691 | + int err = 0; | |
692 | + | |
693 | + /* ACLs only get applied to files and directories */ | |
694 | + if (S_ISLNK (inode->i_mode)) | |
695 | + return 0; | |
696 | + | |
697 | + /* ACLs can only be used on "new" objects, so if it's an old object | |
698 | + * there is nothing to inherit from */ | |
699 | + if (get_inode_sd_version (dir) == STAT_DATA_V1) | |
700 | + goto apply_umask; | |
701 | + | |
702 | + /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This | |
703 | + * would be useless since permissions are ignored, and a pain because | |
704 | + * it introduces locking cycles */ | |
705 | + if (is_reiserfs_priv_object (dir)) { | |
706 | + inode->u.reiserfs_i.i_flags |= i_priv_object; | |
707 | + goto apply_umask; | |
708 | + } | |
709 | + | |
710 | + acl = reiserfs_get_acl (dir, ACL_TYPE_DEFAULT); | |
711 | + if (IS_ERR (acl)) { | |
712 | + if (PTR_ERR (acl) == -ENODATA) | |
713 | + goto apply_umask; | |
714 | + return PTR_ERR (acl); | |
715 | + } | |
716 | + | |
717 | + if (acl) { | |
718 | + struct posix_acl *acl_copy; | |
719 | + mode_t mode = inode->i_mode; | |
720 | + int need_acl; | |
721 | + | |
722 | + /* Copy the default ACL to the default ACL of a new directory */ | |
723 | + if (S_ISDIR (inode->i_mode)) { | |
724 | + err = reiserfs_set_acl (inode, ACL_TYPE_DEFAULT, acl); | |
725 | + if (err) | |
726 | + goto cleanup; | |
727 | + } | |
728 | + | |
729 | + /* Now we reconcile the new ACL and the mode, | |
730 | + potentially modifying both */ | |
731 | + acl_copy = posix_acl_clone (acl, GFP_NOFS); | |
732 | + if (!acl_copy) { | |
733 | + err = -ENOMEM; | |
734 | + goto cleanup; | |
735 | + } | |
736 | + | |
737 | + | |
738 | + need_acl = posix_acl_create_masq (acl_copy, &mode); | |
739 | + if (need_acl >= 0) { | |
740 | + if (mode != inode->i_mode) { | |
741 | + inode->i_mode = mode; | |
742 | + } | |
743 | + | |
744 | + /* If we need an ACL.. */ | |
745 | + if (need_acl > 0) { | |
746 | + err = reiserfs_set_acl (inode, ACL_TYPE_ACCESS, acl_copy); | |
747 | + if (err) | |
748 | + goto cleanup_copy; | |
749 | + } | |
750 | + } | |
751 | +cleanup_copy: | |
752 | + posix_acl_release (acl_copy); | |
753 | +cleanup: | |
754 | + posix_acl_release (acl); | |
755 | + } else { | |
756 | +apply_umask: | |
757 | + /* no ACL, apply umask */ | |
758 | + inode->i_mode &= ~current->fs->umask; | |
759 | + } | |
760 | + | |
761 | + return err; | |
762 | +} | |
763 | + | |
764 | +/* Looks up and caches the result of the default ACL. | |
765 | + * We do this so that we don't need to carry the xattr_sem into | |
766 | + * reiserfs_new_inode if we don't need to */ | |
767 | +int | |
768 | +reiserfs_cache_default_acl (struct inode *inode) | |
769 | +{ | |
770 | + int ret = 0; | |
771 | + if (reiserfs_posixacl (inode->i_sb) && | |
772 | + !is_reiserfs_priv_object (inode)) { | |
773 | + struct posix_acl *acl; | |
774 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
775 | + acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT); | |
776 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
777 | + ret = acl ? 1 : 0; | |
778 | + posix_acl_release (acl); | |
779 | + } | |
780 | + | |
781 | + return ret; | |
782 | +} | |
783 | + | |
784 | +static int | |
785 | +__reiserfs_permission (struct inode *inode, int mask, int need_lock) | |
786 | +{ | |
787 | + int mode = inode->i_mode; | |
788 | + | |
789 | + /* Nobody gets write access to a read-only fs */ | |
790 | + if ((mask & MAY_WRITE) && IS_RDONLY(inode) && | |
791 | + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | |
792 | + return -EROFS; | |
793 | + | |
794 | + /* Nobody gets write access to an immutable file */ | |
795 | + if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | |
796 | + return -EACCES; | |
797 | + | |
798 | + /* We don't do permission checks on the internal objects. | |
799 | + * Permissions are determined by the "owning" object. */ | |
800 | + if (is_reiserfs_priv_object (inode)) | |
801 | + return 0; | |
802 | + | |
803 | + if (current->fsuid == inode->i_uid) { | |
804 | + mode >>= 6; | |
805 | + } else if (reiserfs_posixacl(inode->i_sb) && | |
806 | + get_inode_sd_version (inode) != STAT_DATA_V1) { | |
807 | + struct posix_acl *acl; | |
808 | + | |
809 | + /* ACL can't contain additional permissions if | |
810 | + the ACL_MASK entry is 0 */ | |
811 | + if (!(mode & S_IRWXG)) | |
812 | + goto check_groups; | |
813 | + | |
814 | + if (need_lock) | |
815 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
816 | + acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS); | |
817 | + if (need_lock) | |
818 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
819 | + if (IS_ERR (acl)) { | |
820 | + if (PTR_ERR (acl) == -ENODATA) | |
821 | + goto check_groups; | |
822 | + return PTR_ERR (acl); | |
823 | + } | |
824 | + | |
825 | + if (acl) { | |
826 | + int err = posix_acl_permission (inode, acl, mask); | |
827 | + posix_acl_release (acl); | |
828 | + if (err == -EACCES) { | |
829 | + goto check_capabilities; | |
830 | + } | |
831 | + return err; | |
832 | + } else { | |
833 | + goto check_groups; | |
834 | + } | |
835 | + | |
836 | + } else { | |
837 | +check_groups: | |
838 | + if (in_group_p(inode->i_gid)) | |
839 | + mode >>= 3; | |
840 | + } | |
841 | + if ((mode & mask & S_IRWXO) == mask) | |
842 | + return 0; | |
843 | + | |
844 | +check_capabilities: | |
845 | + /* Allowed to override Discretionary Access Control? */ | |
846 | + if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO)) | |
847 | + if (capable(CAP_DAC_OVERRIDE)) | |
848 | + return 0; | |
849 | + /* Read and search granted if capable(CAP_DAC_READ_SEARCH) */ | |
850 | + if (capable(CAP_DAC_READ_SEARCH) && ((mask == MAY_READ) || | |
851 | + (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))) | |
852 | + return 0; | |
853 | + return -EACCES; | |
854 | +} | |
855 | + | |
856 | +int | |
857 | +reiserfs_permission (struct inode *inode, int mask) | |
858 | +{ | |
859 | + return __reiserfs_permission (inode, mask, 1); | |
860 | +} | |
861 | + | |
862 | +int | |
863 | +reiserfs_permission_locked (struct inode *inode, int mask) | |
864 | +{ | |
865 | + return __reiserfs_permission (inode, mask, 0); | |
866 | +} | |
867 | + | |
868 | +int | |
869 | +reiserfs_acl_chmod (struct inode *inode) | |
870 | +{ | |
871 | + struct posix_acl *acl, *clone; | |
872 | + int error; | |
873 | + | |
874 | + if (S_ISLNK(inode->i_mode)) | |
875 | + return -EOPNOTSUPP; | |
876 | + | |
877 | + if (get_inode_sd_version (inode) == STAT_DATA_V1 || | |
878 | + !reiserfs_posixacl(inode->i_sb)) | |
879 | + { | |
880 | + return 0; | |
881 | + } | |
882 | + | |
883 | + reiserfs_read_lock_xattrs (inode->i_sb); | |
884 | + acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | |
885 | + reiserfs_read_unlock_xattrs (inode->i_sb); | |
886 | + if (!acl) | |
887 | + return 0; | |
888 | + if (IS_ERR(acl)) | |
889 | + return PTR_ERR(acl); | |
890 | + clone = posix_acl_clone(acl, GFP_NOFS); | |
891 | + posix_acl_release(acl); | |
892 | + if (!clone) | |
893 | + return -ENOMEM; | |
894 | + error = posix_acl_chmod_masq(clone, inode->i_mode); | |
895 | + if (!error) { | |
896 | + reiserfs_write_lock_xattrs (inode->i_sb); | |
897 | + error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); | |
898 | + reiserfs_write_unlock_xattrs (inode->i_sb); | |
899 | + } | |
900 | + posix_acl_release(clone); | |
901 | + return error; | |
902 | +} | |
903 | + | |
904 | +static int | |
905 | +posix_acl_access_get(struct inode *inode, const char *name, | |
906 | + void *buffer, size_t size) | |
907 | +{ | |
908 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | |
909 | + return -EINVAL; | |
910 | + return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); | |
911 | +} | |
912 | + | |
913 | +static int | |
914 | +posix_acl_access_set(struct inode *inode, const char *name, | |
915 | + const void *value, size_t size, int flags) | |
916 | +{ | |
917 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | |
918 | + return -EINVAL; | |
919 | + return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); | |
920 | +} | |
921 | + | |
922 | +static int | |
923 | +posix_acl_access_del (struct inode *inode, const char *name) | |
924 | +{ | |
925 | + struct posix_acl **acl = &inode->u.reiserfs_i.i_acl_access; | |
926 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) | |
927 | + return -EINVAL; | |
928 | + if (!IS_ERR (*acl) && *acl) { | |
929 | + posix_acl_release (*acl); | |
930 | + *acl = ERR_PTR (-ENODATA); | |
931 | + } | |
932 | + | |
933 | + return 0; | |
934 | +} | |
935 | + | |
936 | +static int | |
937 | +posix_acl_access_list (struct inode *inode, const char *name, int namelen, char *out) | |
938 | +{ | |
939 | + int len = namelen; | |
940 | + if (!reiserfs_posixacl (inode->i_sb)) | |
941 | + return 0; | |
942 | + if (out) | |
943 | + memcpy (out, name, len); | |
944 | + | |
945 | + return len; | |
946 | +} | |
947 | + | |
948 | +struct reiserfs_xattr_handler posix_acl_access_handler = { | |
949 | + prefix: XATTR_NAME_ACL_ACCESS, | |
950 | + get: posix_acl_access_get, | |
951 | + set: posix_acl_access_set, | |
952 | + del: posix_acl_access_del, | |
953 | + list: posix_acl_access_list, | |
954 | +}; | |
955 | + | |
956 | +static int | |
957 | +posix_acl_default_get (struct inode *inode, const char *name, | |
958 | + void *buffer, size_t size) | |
959 | +{ | |
960 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | |
961 | + return -EINVAL; | |
962 | + return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); | |
963 | +} | |
964 | + | |
965 | +static int | |
966 | +posix_acl_default_set(struct inode *inode, const char *name, | |
967 | + const void *value, size_t size, int flags) | |
968 | +{ | |
969 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | |
970 | + return -EINVAL; | |
971 | + return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); | |
972 | +} | |
973 | + | |
974 | +static int | |
975 | +posix_acl_default_del (struct inode *inode, const char *name) | |
976 | +{ | |
977 | + struct posix_acl **acl = &inode->u.reiserfs_i.i_acl_default; | |
978 | + if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) | |
979 | + return -EINVAL; | |
980 | + if (!IS_ERR (*acl) && *acl) { | |
981 | + posix_acl_release (*acl); | |
982 | + *acl = ERR_PTR (-ENODATA); | |
983 | + } | |
984 | + | |
985 | + return 0; | |
986 | +} | |
987 | + | |
988 | +static int | |
989 | +posix_acl_default_list (struct inode *inode, const char *name, int namelen, char *out) | |
990 | +{ | |
991 | + int len = namelen; | |
992 | + if (!reiserfs_posixacl (inode->i_sb)) | |
993 | + return 0; | |
994 | + if (out) | |
995 | + memcpy (out, name, len); | |
996 | + | |
997 | + return len; | |
998 | +} | |
999 | + | |
1000 | +struct reiserfs_xattr_handler posix_acl_default_handler = { | |
1001 | + prefix: XATTR_NAME_ACL_DEFAULT, | |
1002 | + get: posix_acl_default_get, | |
1003 | + set: posix_acl_default_set, | |
1004 | + del: posix_acl_default_del, | |
1005 | + list: posix_acl_default_list, | |
1006 | +}; | |
1007 | + | |
1008 | +int __init | |
1009 | +reiserfs_xattr_posix_acl_init (void) | |
1010 | +{ | |
1011 | + int err; | |
1012 | + err = reiserfs_xattr_register_handler (&posix_acl_access_handler); | |
1013 | + if (!err) | |
1014 | + err = reiserfs_xattr_register_handler (&posix_acl_default_handler); | |
1015 | + return err; | |
1016 | +} | |
1017 | + | |
1018 | +int | |
1019 | +reiserfs_xattr_posix_acl_exit (void) | |
1020 | +{ | |
1021 | + int err; | |
1022 | + err = reiserfs_xattr_unregister_handler (&posix_acl_access_handler); | |
1023 | + if (!err) | |
1024 | + err = reiserfs_xattr_unregister_handler (&posix_acl_default_handler); | |
1025 | + return err; | |
1026 | +} | |
1027 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/fs/reiserfs/xattr_user.c linux-2.4.23.xattr/fs/reiserfs/xattr_user.c | |
1028 | --- linux-2.4.23.datalogging+quota/fs/reiserfs/xattr_user.c 2003-12-11 13:00:09.967877312 -0500 | |
1029 | +++ linux-2.4.23.xattr/fs/reiserfs/xattr_user.c 2003-12-11 13:00:17.439741416 -0500 | |
1030 | @@ -6,6 +6,10 @@ | |
1031 | #include <linux/reiserfs_xattr.h> | |
1032 | #include <asm/uaccess.h> | |
1033 | ||
1034 | +#ifdef CONFIG_REISERFS_FS_POSIX_ACL | |
1035 | +# include <linux/reiserfs_acl.h> | |
1036 | +#endif | |
1037 | + | |
1038 | #define XATTR_USER_PREFIX "user." | |
1039 | ||
1040 | static int | |
1041 | @@ -20,7 +24,7 @@ user_get (struct inode *inode, const cha | |
1042 | if (!reiserfs_xattrs_user (inode->i_sb)) | |
1043 | return -EOPNOTSUPP; | |
1044 | ||
1045 | - error = permission (inode, MAY_READ); | |
1046 | + error = reiserfs_permission_locked (inode, MAY_READ); | |
1047 | if (error) | |
1048 | return error; | |
1049 | ||
1050 | @@ -44,7 +48,7 @@ user_set (struct inode *inode, const cha | |
1051 | (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) | |
1052 | return -EPERM; | |
1053 | ||
1054 | - error = permission (inode, MAY_WRITE); | |
1055 | + error = reiserfs_permission_locked (inode, MAY_WRITE); | |
1056 | if (error) | |
1057 | return error; | |
1058 | ||
1059 | @@ -66,7 +70,7 @@ user_del (struct inode *inode, const cha | |
1060 | (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) | |
1061 | return -EPERM; | |
1062 | ||
1063 | - error = permission (inode, MAY_WRITE); | |
1064 | + error = reiserfs_permission_locked (inode, MAY_WRITE); | |
1065 | if (error) | |
1066 | return error; | |
1067 | ||
1068 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_acl.h linux-2.4.23.xattr/include/linux/reiserfs_acl.h | |
1069 | --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_acl.h 1969-12-31 19:00:00.000000000 -0500 | |
1070 | +++ linux-2.4.23.xattr/include/linux/reiserfs_acl.h 2003-12-11 13:02:54.070929856 -0500 | |
1071 | @@ -0,0 +1,92 @@ | |
1072 | +#include <linux/init.h> | |
1073 | +#include <linux/posix_acl.h> | |
1074 | +#include <linux/xattr_acl.h> | |
1075 | + | |
1076 | +#define REISERFS_ACL_VERSION 0x0001 | |
1077 | + | |
1078 | +typedef struct { | |
1079 | + __u16 e_tag; | |
1080 | + __u16 e_perm; | |
1081 | + __u32 e_id; | |
1082 | +} reiserfs_acl_entry; | |
1083 | + | |
1084 | +typedef struct { | |
1085 | + __u16 e_tag; | |
1086 | + __u16 e_perm; | |
1087 | +} reiserfs_acl_entry_short; | |
1088 | + | |
1089 | +typedef struct { | |
1090 | + __u32 a_version; | |
1091 | +} reiserfs_acl_header; | |
1092 | + | |
1093 | +static inline size_t reiserfs_acl_size(int count) | |
1094 | +{ | |
1095 | + if (count <= 4) { | |
1096 | + return sizeof(reiserfs_acl_header) + | |
1097 | + count * sizeof(reiserfs_acl_entry_short); | |
1098 | + } else { | |
1099 | + return sizeof(reiserfs_acl_header) + | |
1100 | + 4 * sizeof(reiserfs_acl_entry_short) + | |
1101 | + (count - 4) * sizeof(reiserfs_acl_entry); | |
1102 | + } | |
1103 | +} | |
1104 | + | |
1105 | +static inline int reiserfs_acl_count(size_t size) | |
1106 | +{ | |
1107 | + ssize_t s; | |
1108 | + size -= sizeof(reiserfs_acl_header); | |
1109 | + s = size - 4 * sizeof(reiserfs_acl_entry_short); | |
1110 | + if (s < 0) { | |
1111 | + if (size % sizeof(reiserfs_acl_entry_short)) | |
1112 | + return -1; | |
1113 | + return size / sizeof(reiserfs_acl_entry_short); | |
1114 | + } else { | |
1115 | + if (s % sizeof(reiserfs_acl_entry)) | |
1116 | + return -1; | |
1117 | + return s / sizeof(reiserfs_acl_entry) + 4; | |
1118 | + } | |
1119 | +} | |
1120 | + | |
1121 | + | |
1122 | +#ifdef CONFIG_REISERFS_FS_POSIX_ACL | |
1123 | +struct posix_acl * reiserfs_get_acl(struct inode *inode, int type); | |
1124 | +int reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl); | |
1125 | +int reiserfs_permission (struct inode *inode, int mask); | |
1126 | +int reiserfs_permission_locked (struct inode *inode, int mask); | |
1127 | +int reiserfs_acl_chmod (struct inode *inode); | |
1128 | +int reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode); | |
1129 | +int reiserfs_cache_default_acl (struct inode *dir); | |
1130 | +extern int reiserfs_xattr_posix_acl_init (void) __init; | |
1131 | +extern int reiserfs_xattr_posix_acl_exit (void); | |
1132 | +#else | |
1133 | + | |
1134 | +#define reiserfs_permission NULL | |
1135 | +#define reiserfs_set_acl NULL | |
1136 | +#define reiserfs_get_acl NULL | |
1137 | +#define reiserfs_cache_default_acl(inode) 0 | |
1138 | + | |
1139 | +static inline int | |
1140 | +reiserfs_xattr_posix_acl_init (void) | |
1141 | +{ | |
1142 | + return 0; | |
1143 | +} | |
1144 | + | |
1145 | +static inline int | |
1146 | +reiserfs_xattr_posix_acl_exit (void) | |
1147 | +{ | |
1148 | + return 0; | |
1149 | +} | |
1150 | + | |
1151 | +static inline int | |
1152 | +reiserfs_acl_chmod (struct inode *inode) | |
1153 | +{ | |
1154 | + return 0; | |
1155 | +} | |
1156 | + | |
1157 | +static inline int | |
1158 | +reiserfs_inherit_default_acl (const struct inode *dir, struct dentry *dentry, struct inode *inode) | |
1159 | +{ | |
1160 | + return 0; | |
1161 | +} | |
1162 | + | |
1163 | +#endif | |
1164 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_i.h linux-2.4.23.xattr/include/linux/reiserfs_fs_i.h | |
1165 | --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_i.h 2003-12-11 13:00:09.969877008 -0500 | |
1166 | +++ linux-2.4.23.xattr/include/linux/reiserfs_fs_i.h 2003-12-11 13:02:51.667295264 -0500 | |
1167 | @@ -65,6 +65,9 @@ struct reiserfs_inode_info { | |
1168 | */ | |
1169 | unsigned long i_tail_trans_id; | |
1170 | struct reiserfs_journal_list *i_tail_jl; | |
1171 | + | |
1172 | + struct posix_acl *i_acl_access; | |
1173 | + struct posix_acl *i_acl_default; | |
1174 | }; | |
1175 | ||
1176 | #endif | |
1177 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_sb.h linux-2.4.23.xattr/include/linux/reiserfs_fs_sb.h | |
1178 | --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_fs_sb.h 2003-12-11 13:00:09.970876856 -0500 | |
1179 | +++ linux-2.4.23.xattr/include/linux/reiserfs_fs_sb.h 2003-12-11 13:02:51.689291920 -0500 | |
1180 | @@ -492,6 +492,7 @@ enum { | |
1181 | REISERFS_TEST4, | |
1182 | REISERFS_XATTRS, | |
1183 | REISERFS_XATTRS_USER, | |
1184 | + REISERFS_POSIXACL, | |
1185 | }; | |
1186 | ||
1187 | #define reiserfs_r5_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_R5_HASH)) | |
1188 | @@ -515,7 +516,8 @@ enum { | |
1189 | #define convert_reiserfs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_CONVERT)) | |
1190 | #define reiserfs_xattrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS)) | |
1191 | #define reiserfs_xattrs_user(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_XATTRS_USER)) | |
1192 | -#define reiserfs_xattrs_optional(s) reiserfs_xattrs_user(s) | |
1193 | +#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s)) | |
1194 | +#define reiserfs_posixacl(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_POSIXACL)) | |
1195 | ||
1196 | ||
1197 | void reiserfs_file_buffer (struct buffer_head * bh, int list); | |
1198 | diff -ruNp -X ../dontdiff linux-2.4.23.datalogging+quota/include/linux/reiserfs_xattr.h linux-2.4.23.xattr/include/linux/reiserfs_xattr.h | |
1199 | --- linux-2.4.23.datalogging+quota/include/linux/reiserfs_xattr.h 2003-12-11 13:00:09.970876856 -0500 | |
1200 | +++ linux-2.4.23.xattr/include/linux/reiserfs_xattr.h 2003-12-11 13:02:54.072929552 -0500 | |
1201 | @@ -73,6 +73,7 @@ reiserfs_read_unlock_xattrs(struct super | |
1202 | static inline int | |
1203 | reiserfs_xattr_init (struct super_block *s, int mount_flags) | |
1204 | { | |
1205 | + s->s_flags = (s->s_flags & ~MS_POSIXACL); /* to be sure */ | |
1206 | return 0; | |
1207 | } | |
1208 |