MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / fs / xattr.c
blob24bd5427d4f4d2be2a0095a62095165de826ec80
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/smp_lock.h>
12 #include <linux/file.h>
13 #include <linux/xattr.h>
14 #include <linux/namei.h>
15 #include <linux/security.h>
16 #include <asm/uaccess.h>
19 * Extended attribute SET operations
21 static long
22 setxattr(struct dentry *d, char __user *name, void __user *value,
23 size_t size, int flags)
25 int error;
26 void *kvalue = NULL;
27 char kname[XATTR_NAME_MAX + 1];
29 if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
30 return -EINVAL;
32 error = strncpy_from_user(kname, name, sizeof(kname));
33 if (error == 0 || error == sizeof(kname))
34 error = -ERANGE;
35 if (error < 0)
36 return error;
38 if (size) {
39 if (size > XATTR_SIZE_MAX)
40 return -E2BIG;
41 kvalue = kmalloc(size, GFP_KERNEL);
42 if (!kvalue)
43 return -ENOMEM;
44 if (copy_from_user(kvalue, value, size)) {
45 kfree(kvalue);
46 return -EFAULT;
50 error = -EOPNOTSUPP;
51 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
52 down(&d->d_inode->i_sem);
53 error = security_inode_setxattr(d, kname, kvalue, size, flags);
54 if (error)
55 goto out;
56 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
57 if (!error)
58 security_inode_post_setxattr(d, kname, kvalue, size, flags);
59 out:
60 up(&d->d_inode->i_sem);
62 if (kvalue)
63 kfree(kvalue);
64 return error;
67 asmlinkage long
68 sys_setxattr(char __user *path, char __user *name, void __user *value,
69 size_t size, int flags)
71 struct nameidata nd;
72 int error;
74 error = user_path_walk(path, &nd);
75 if (error)
76 return error;
77 error = setxattr(nd.dentry, name, value, size, flags);
78 path_release(&nd);
79 return error;
82 asmlinkage long
83 sys_lsetxattr(char __user *path, char __user *name, void __user *value,
84 size_t size, int flags)
86 struct nameidata nd;
87 int error;
89 error = user_path_walk_link(path, &nd);
90 if (error)
91 return error;
92 error = setxattr(nd.dentry, name, value, size, flags);
93 path_release(&nd);
94 return error;
97 asmlinkage long
98 sys_fsetxattr(int fd, char __user *name, void __user *value,
99 size_t size, int flags)
101 struct file *f;
102 int error = -EBADF;
104 f = fget(fd);
105 if (!f)
106 return error;
107 error = setxattr(f->f_dentry, name, value, size, flags);
108 fput(f);
109 return error;
113 * Extended attribute GET operations
115 static ssize_t
116 getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
118 ssize_t error;
119 void *kvalue = NULL;
120 char kname[XATTR_NAME_MAX + 1];
122 error = strncpy_from_user(kname, name, sizeof(kname));
123 if (error == 0 || error == sizeof(kname))
124 error = -ERANGE;
125 if (error < 0)
126 return error;
128 if (size) {
129 if (size > XATTR_SIZE_MAX)
130 size = XATTR_SIZE_MAX;
131 kvalue = kmalloc(size, GFP_KERNEL);
132 if (!kvalue)
133 return -ENOMEM;
136 error = -EOPNOTSUPP;
137 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
138 error = security_inode_getxattr(d, kname);
139 if (error)
140 goto out;
141 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
142 if (error > 0) {
143 if (size && copy_to_user(value, kvalue, error))
144 error = -EFAULT;
145 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
146 /* The file system tried to returned a value bigger
147 than XATTR_SIZE_MAX bytes. Not possible. */
148 error = -E2BIG;
151 out:
152 if (kvalue)
153 kfree(kvalue);
154 return error;
157 asmlinkage ssize_t
158 sys_getxattr(char __user *path, char __user *name, void __user *value,
159 size_t size)
161 struct nameidata nd;
162 ssize_t error;
164 error = user_path_walk(path, &nd);
165 if (error)
166 return error;
167 error = getxattr(nd.dentry, name, value, size);
168 path_release(&nd);
169 return error;
172 asmlinkage ssize_t
173 sys_lgetxattr(char __user *path, char __user *name, void __user *value,
174 size_t size)
176 struct nameidata nd;
177 ssize_t error;
179 error = user_path_walk_link(path, &nd);
180 if (error)
181 return error;
182 error = getxattr(nd.dentry, name, value, size);
183 path_release(&nd);
184 return error;
187 asmlinkage ssize_t
188 sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
190 struct file *f;
191 ssize_t error = -EBADF;
193 f = fget(fd);
194 if (!f)
195 return error;
196 error = getxattr(f->f_dentry, name, value, size);
197 fput(f);
198 return error;
202 * Extended attribute LIST operations
204 static ssize_t
205 listxattr(struct dentry *d, char __user *list, size_t size)
207 ssize_t error;
208 char *klist = NULL;
210 if (size) {
211 if (size > XATTR_LIST_MAX)
212 size = XATTR_LIST_MAX;
213 klist = kmalloc(size, GFP_KERNEL);
214 if (!klist)
215 return -ENOMEM;
218 error = -EOPNOTSUPP;
219 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
220 error = security_inode_listxattr(d);
221 if (error)
222 goto out;
223 error = d->d_inode->i_op->listxattr(d, klist, size);
224 if (error > 0) {
225 if (size && copy_to_user(list, klist, error))
226 error = -EFAULT;
227 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
228 /* The file system tried to returned a list bigger
229 than XATTR_LIST_MAX bytes. Not possible. */
230 error = -E2BIG;
233 out:
234 if (klist)
235 kfree(klist);
236 return error;
239 asmlinkage ssize_t
240 sys_listxattr(char __user *path, char __user *list, size_t size)
242 struct nameidata nd;
243 ssize_t error;
245 error = user_path_walk(path, &nd);
246 if (error)
247 return error;
248 error = listxattr(nd.dentry, list, size);
249 path_release(&nd);
250 return error;
253 asmlinkage ssize_t
254 sys_llistxattr(char __user *path, char __user *list, size_t size)
256 struct nameidata nd;
257 ssize_t error;
259 error = user_path_walk_link(path, &nd);
260 if (error)
261 return error;
262 error = listxattr(nd.dentry, list, size);
263 path_release(&nd);
264 return error;
267 asmlinkage ssize_t
268 sys_flistxattr(int fd, char __user *list, size_t size)
270 struct file *f;
271 ssize_t error = -EBADF;
273 f = fget(fd);
274 if (!f)
275 return error;
276 error = listxattr(f->f_dentry, list, size);
277 fput(f);
278 return error;
282 * Extended attribute REMOVE operations
284 static long
285 removexattr(struct dentry *d, char __user *name)
287 int error;
288 char kname[XATTR_NAME_MAX + 1];
290 error = strncpy_from_user(kname, name, sizeof(kname));
291 if (error == 0 || error == sizeof(kname))
292 error = -ERANGE;
293 if (error < 0)
294 return error;
296 error = -EOPNOTSUPP;
297 if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
298 error = security_inode_removexattr(d, kname);
299 if (error)
300 goto out;
301 down(&d->d_inode->i_sem);
302 error = d->d_inode->i_op->removexattr(d, kname);
303 up(&d->d_inode->i_sem);
305 out:
306 return error;
309 asmlinkage long
310 sys_removexattr(char __user *path, char __user *name)
312 struct nameidata nd;
313 int error;
315 error = user_path_walk(path, &nd);
316 if (error)
317 return error;
318 error = removexattr(nd.dentry, name);
319 path_release(&nd);
320 return error;
323 asmlinkage long
324 sys_lremovexattr(char __user *path, char __user *name)
326 struct nameidata nd;
327 int error;
329 error = user_path_walk_link(path, &nd);
330 if (error)
331 return error;
332 error = removexattr(nd.dentry, name);
333 path_release(&nd);
334 return error;
337 asmlinkage long
338 sys_fremovexattr(int fd, char __user *name)
340 struct file *f;
341 int error = -EBADF;
343 f = fget(fd);
344 if (!f)
345 return error;
346 error = removexattr(f->f_dentry, name);
347 fput(f);
348 return error;