[PATCH] m68k: bitops update [3/20]
[linux-2.6/history.git] / fs / xattr.c
blob20a7f5b049f98ec4b75a48f33ce7bb796be6456a
1 /*
2 File: fs/xattr.c
4 Extended attribute handling.
6 Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
7 Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
8 */
9 #include <linux/fs.h>
10 #include <linux/slab.h>
11 #include <linux/vmalloc.h>
12 #include <linux/smp_lock.h>
13 #include <linux/file.h>
14 #include <linux/xattr.h>
15 #include <asm/uaccess.h>
18 * Extended attribute memory allocation wrappers, originally
19 * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
20 * The vmalloc use here is very uncommon - extended attributes
21 * are supposed to be small chunks of metadata, and it is quite
22 * unusual to have very many extended attributes, so lists tend
23 * to be quite short as well. The 64K upper limit is derived
24 * from the extended attribute size limit used by XFS.
25 * Intentionally allow zero @size for value/list size requests.
27 static void *
28 xattr_alloc(size_t size, size_t limit)
30 void *ptr;
32 if (size > limit)
33 return ERR_PTR(-E2BIG);
35 if (!size) /* size request, no buffer is needed */
36 return NULL;
37 else if (size <= PAGE_SIZE)
38 ptr = kmalloc((unsigned long) size, GFP_KERNEL);
39 else
40 ptr = vmalloc((unsigned long) size);
41 if (!ptr)
42 return ERR_PTR(-ENOMEM);
43 return ptr;
46 static void
47 xattr_free(void *ptr, size_t size)
49 if (!size) /* size request, no buffer was needed */
50 return;
51 else if (size <= PAGE_SIZE)
52 kfree(ptr);
53 else
54 vfree(ptr);
58 * Extended attribute SET operations
60 static long
61 setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
63 int error;
64 void *kvalue;
65 char kname[XATTR_NAME_MAX + 1];
67 if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
68 return -EINVAL;
70 error = strncpy_from_user(kname, name, sizeof(kname));
71 if (error == 0 || error == sizeof(kname))
72 error = -ERANGE;
73 if (error < 0)
74 return error;
76 kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
77 if (IS_ERR(kvalue))
78 return PTR_ERR(kvalue);
80 if (size > 0 && copy_from_user(kvalue, value, size)) {
81 xattr_free(kvalue, size);
82 return -EFAULT;
85 error = -EOPNOTSUPP;
86 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
87 down(&d->d_inode->i_sem);
88 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
89 up(&d->d_inode->i_sem);
92 xattr_free(kvalue, size);
93 return error;
96 asmlinkage long
97 sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
99 struct nameidata nd;
100 int error;
102 error = user_path_walk(path, &nd);
103 if (error)
104 return error;
105 error = setxattr(nd.dentry, name, value, size, flags);
106 path_release(&nd);
107 return error;
110 asmlinkage long
111 sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
113 struct nameidata nd;
114 int error;
116 error = user_path_walk_link(path, &nd);
117 if (error)
118 return error;
119 error = setxattr(nd.dentry, name, value, size, flags);
120 path_release(&nd);
121 return error;
124 asmlinkage long
125 sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
127 struct file *f;
128 int error = -EBADF;
130 f = fget(fd);
131 if (!f)
132 return error;
133 error = setxattr(f->f_dentry, name, value, size, flags);
134 fput(f);
135 return error;
139 * Extended attribute GET operations
141 static ssize_t
142 getxattr(struct dentry *d, char *name, void *value, size_t size)
144 ssize_t error;
145 void *kvalue;
146 char kname[XATTR_NAME_MAX + 1];
148 error = strncpy_from_user(kname, name, sizeof(kname));
149 if (error == 0 || error == sizeof(kname))
150 error = -ERANGE;
151 if (error < 0)
152 return error;
154 kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
155 if (IS_ERR(kvalue))
156 return PTR_ERR(kvalue);
158 error = -EOPNOTSUPP;
159 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
160 down(&d->d_inode->i_sem);
161 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
162 up(&d->d_inode->i_sem);
165 if (kvalue && error > 0)
166 if (copy_to_user(value, kvalue, error))
167 error = -EFAULT;
168 xattr_free(kvalue, size);
169 return error;
172 asmlinkage ssize_t
173 sys_getxattr(char *path, char *name, void *value, size_t size)
175 struct nameidata nd;
176 ssize_t error;
178 error = user_path_walk(path, &nd);
179 if (error)
180 return error;
181 error = getxattr(nd.dentry, name, value, size);
182 path_release(&nd);
183 return error;
186 asmlinkage ssize_t
187 sys_lgetxattr(char *path, char *name, void *value, size_t size)
189 struct nameidata nd;
190 ssize_t error;
192 error = user_path_walk_link(path, &nd);
193 if (error)
194 return error;
195 error = getxattr(nd.dentry, name, value, size);
196 path_release(&nd);
197 return error;
200 asmlinkage ssize_t
201 sys_fgetxattr(int fd, char *name, void *value, size_t size)
203 struct file *f;
204 ssize_t error = -EBADF;
206 f = fget(fd);
207 if (!f)
208 return error;
209 error = getxattr(f->f_dentry, name, value, size);
210 fput(f);
211 return error;
215 * Extended attribute LIST operations
217 static ssize_t
218 listxattr(struct dentry *d, char *list, size_t size)
220 ssize_t error;
221 char *klist;
223 klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
224 if (IS_ERR(klist))
225 return PTR_ERR(klist);
227 error = -EOPNOTSUPP;
228 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
229 down(&d->d_inode->i_sem);
230 error = d->d_inode->i_op->listxattr(d, klist, size);
231 up(&d->d_inode->i_sem);
234 if (klist && error > 0)
235 if (copy_to_user(list, klist, error))
236 error = -EFAULT;
237 xattr_free(klist, size);
238 return error;
241 asmlinkage ssize_t
242 sys_listxattr(char *path, char *list, size_t size)
244 struct nameidata nd;
245 ssize_t error;
247 error = user_path_walk(path, &nd);
248 if (error)
249 return error;
250 error = listxattr(nd.dentry, list, size);
251 path_release(&nd);
252 return error;
255 asmlinkage ssize_t
256 sys_llistxattr(char *path, char *list, size_t size)
258 struct nameidata nd;
259 ssize_t error;
261 error = user_path_walk_link(path, &nd);
262 if (error)
263 return error;
264 error = listxattr(nd.dentry, list, size);
265 path_release(&nd);
266 return error;
269 asmlinkage ssize_t
270 sys_flistxattr(int fd, char *list, size_t size)
272 struct file *f;
273 ssize_t error = -EBADF;
275 f = fget(fd);
276 if (!f)
277 return error;
278 error = listxattr(f->f_dentry, list, size);
279 fput(f);
280 return error;
284 * Extended attribute REMOVE operations
286 static long
287 removexattr(struct dentry *d, char *name)
289 int error;
290 char kname[XATTR_NAME_MAX + 1];
292 error = strncpy_from_user(kname, name, sizeof(kname));
293 if (error == 0 || error == sizeof(kname))
294 error = -ERANGE;
295 if (error < 0)
296 return error;
298 error = -EOPNOTSUPP;
299 if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
300 down(&d->d_inode->i_sem);
301 error = d->d_inode->i_op->removexattr(d, kname);
302 up(&d->d_inode->i_sem);
304 return error;
307 asmlinkage long
308 sys_removexattr(char *path, char *name)
310 struct nameidata nd;
311 int error;
313 error = user_path_walk(path, &nd);
314 if (error)
315 return error;
316 error = removexattr(nd.dentry, name);
317 path_release(&nd);
318 return error;
321 asmlinkage long
322 sys_lremovexattr(char *path, char *name)
324 struct nameidata nd;
325 int error;
327 error = user_path_walk_link(path, &nd);
328 if (error)
329 return error;
330 error = removexattr(nd.dentry, name);
331 path_release(&nd);
332 return error;
335 asmlinkage long
336 sys_fremovexattr(int fd, char *name)
338 struct file *f;
339 int error = -EBADF;
341 f = fget(fd);
342 if (!f)
343 return error;
344 error = removexattr(f->f_dentry, name);
345 fput(f);
346 return error;