OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [xattr.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
  File: fs/xattr.c
3
 
4
  Extended attribute handling.
5
 
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>
16
 
17
/*
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.
26
 */
27
static void *
28
xattr_alloc(size_t size, size_t limit)
29
{
30
        void *ptr;
31
 
32
        if (size > limit)
33
                return ERR_PTR(-E2BIG);
34
 
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;
44
}
45
 
46
static void
47
xattr_free(void *ptr, size_t size)
48
{
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);
55
}
56
 
57
/*
58
 * Extended attribute SET operations
59
 */
60
static long
61
setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
62
{
63
        int error;
64
        void *kvalue;
65
        char kname[XATTR_NAME_MAX + 1];
66
 
67
        if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
68
                return -EINVAL;
69
 
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;
75
 
76
        kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
77
        if (IS_ERR(kvalue))
78
                return PTR_ERR(kvalue);
79
 
80
        if (size > 0 && copy_from_user(kvalue, value, size)) {
81
                xattr_free(kvalue, size);
82
                return -EFAULT;
83
        }
84
 
85
        error = -EOPNOTSUPP;
86
        if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
87
                down(&d->d_inode->i_sem);
88
                lock_kernel();
89
                error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
90
                unlock_kernel();
91
                up(&d->d_inode->i_sem);
92
        }
93
 
94
        xattr_free(kvalue, size);
95
        return error;
96
}
97
 
98
asmlinkage long
99
sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
100
{
101
        struct nameidata nd;
102
        int error;
103
 
104
        error = user_path_walk(path, &nd);
105
        if (error)
106
                return error;
107
        error = setxattr(nd.dentry, name, value, size, flags);
108
        path_release(&nd);
109
        return error;
110
}
111
 
112
asmlinkage long
113
sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
114
{
115
        struct nameidata nd;
116
        int error;
117
 
118
        error = user_path_walk_link(path, &nd);
119
        if (error)
120
                return error;
121
        error = setxattr(nd.dentry, name, value, size, flags);
122
        path_release(&nd);
123
        return error;
124
}
125
 
126
asmlinkage long
127
sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
128
{
129
        struct file *f;
130
        int error = -EBADF;
131
 
132
        f = fget(fd);
133
        if (!f)
134
                return error;
135
        error = setxattr(f->f_dentry, name, value, size, flags);
136
        fput(f);
137
        return error;
138
}
139
 
140
/*
141
 * Extended attribute GET operations
142
 */
143
static ssize_t
144
getxattr(struct dentry *d, char *name, void *value, size_t size)
145
{
146
        ssize_t error;
147
        void *kvalue;
148
        char kname[XATTR_NAME_MAX + 1];
149
 
150
        error = strncpy_from_user(kname, name, sizeof(kname));
151
        if (error == 0 || error == sizeof(kname))
152
                error = -ERANGE;
153
        if (error < 0)
154
                return error;
155
 
156
        kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
157
        if (IS_ERR(kvalue))
158
                return PTR_ERR(kvalue);
159
 
160
        error = -EOPNOTSUPP;
161
        if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
162
                down(&d->d_inode->i_sem);
163
                lock_kernel();
164
                error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
165
                unlock_kernel();
166
                up(&d->d_inode->i_sem);
167
        }
168
 
169
        if (kvalue && error > 0)
170
                if (copy_to_user(value, kvalue, error))
171
                        error = -EFAULT;
172
        xattr_free(kvalue, size);
173
        return error;
174
}
175
 
176
asmlinkage ssize_t
177
sys_getxattr(char *path, char *name, void *value, size_t size)
178
{
179
        struct nameidata nd;
180
        ssize_t error;
181
 
182
        error = user_path_walk(path, &nd);
183
        if (error)
184
                return error;
185
        error = getxattr(nd.dentry, name, value, size);
186
        path_release(&nd);
187
        return error;
188
}
189
 
190
asmlinkage ssize_t
191
sys_lgetxattr(char *path, char *name, void *value, size_t size)
192
{
193
        struct nameidata nd;
194
        ssize_t error;
195
 
196
        error = user_path_walk_link(path, &nd);
197
        if (error)
198
                return error;
199
        error = getxattr(nd.dentry, name, value, size);
200
        path_release(&nd);
201
        return error;
202
}
203
 
204
asmlinkage ssize_t
205
sys_fgetxattr(int fd, char *name, void *value, size_t size)
206
{
207
        struct file *f;
208
        ssize_t error = -EBADF;
209
 
210
        f = fget(fd);
211
        if (!f)
212
                return error;
213
        error = getxattr(f->f_dentry, name, value, size);
214
        fput(f);
215
        return error;
216
}
217
 
218
/*
219
 * Extended attribute LIST operations
220
 */
221
static ssize_t
222
listxattr(struct dentry *d, char *list, size_t size)
223
{
224
        ssize_t error;
225
        char *klist;
226
 
227
        klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
228
        if (IS_ERR(klist))
229
                return PTR_ERR(klist);
230
 
231
        error = -EOPNOTSUPP;
232
        if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
233
                down(&d->d_inode->i_sem);
234
                lock_kernel();
235
                error = d->d_inode->i_op->listxattr(d, klist, size);
236
                unlock_kernel();
237
                up(&d->d_inode->i_sem);
238
        }
239
 
240
        if (klist && error > 0)
241
                if (copy_to_user(list, klist, error))
242
                        error = -EFAULT;
243
        xattr_free(klist, size);
244
        return error;
245
}
246
 
247
asmlinkage ssize_t
248
sys_listxattr(char *path, char *list, size_t size)
249
{
250
        struct nameidata nd;
251
        ssize_t error;
252
 
253
        error = user_path_walk(path, &nd);
254
        if (error)
255
                return error;
256
        error = listxattr(nd.dentry, list, size);
257
        path_release(&nd);
258
        return error;
259
}
260
 
261
asmlinkage ssize_t
262
sys_llistxattr(char *path, char *list, size_t size)
263
{
264
        struct nameidata nd;
265
        ssize_t error;
266
 
267
        error = user_path_walk_link(path, &nd);
268
        if (error)
269
                return error;
270
        error = listxattr(nd.dentry, list, size);
271
        path_release(&nd);
272
        return error;
273
}
274
 
275
asmlinkage ssize_t
276
sys_flistxattr(int fd, char *list, size_t size)
277
{
278
        struct file *f;
279
        ssize_t error = -EBADF;
280
 
281
        f = fget(fd);
282
        if (!f)
283
                return error;
284
        error = listxattr(f->f_dentry, list, size);
285
        fput(f);
286
        return error;
287
}
288
 
289
/*
290
 * Extended attribute REMOVE operations
291
 */
292
static long
293
removexattr(struct dentry *d, char *name)
294
{
295
        int error;
296
        char kname[XATTR_NAME_MAX + 1];
297
 
298
        error = strncpy_from_user(kname, name, sizeof(kname));
299
        if (error == 0 || error == sizeof(kname))
300
                error = -ERANGE;
301
        if (error < 0)
302
                return error;
303
 
304
        error = -EOPNOTSUPP;
305
        if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
306
                down(&d->d_inode->i_sem);
307
                lock_kernel();
308
                error = d->d_inode->i_op->removexattr(d, kname);
309
                unlock_kernel();
310
                up(&d->d_inode->i_sem);
311
        }
312
        return error;
313
}
314
 
315
asmlinkage long
316
sys_removexattr(char *path, char *name)
317
{
318
        struct nameidata nd;
319
        int error;
320
 
321
        error = user_path_walk(path, &nd);
322
        if (error)
323
                return error;
324
        error = removexattr(nd.dentry, name);
325
        path_release(&nd);
326
        return error;
327
}
328
 
329
asmlinkage long
330
sys_lremovexattr(char *path, char *name)
331
{
332
        struct nameidata nd;
333
        int error;
334
 
335
        error = user_path_walk_link(path, &nd);
336
        if (error)
337
                return error;
338
        error = removexattr(nd.dentry, name);
339
        path_release(&nd);
340
        return error;
341
}
342
 
343
asmlinkage long
344
sys_fremovexattr(int fd, char *name)
345
{
346
        struct file *f;
347
        int error = -EBADF;
348
 
349
        f = fget(fd);
350
        if (!f)
351
                return error;
352
        error = removexattr(f->f_dentry, name);
353
        fput(f);
354
        return error;
355
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.