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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [stat.c] - Blame information for rev 79

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  linux/fs/stat.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
#include <linux/module.h>
8
#include <linux/mm.h>
9
#include <linux/errno.h>
10
#include <linux/file.h>
11
#include <linux/highuid.h>
12
#include <linux/fs.h>
13
#include <linux/namei.h>
14
#include <linux/security.h>
15
#include <linux/syscalls.h>
16
#include <linux/pagemap.h>
17
 
18
#include <asm/uaccess.h>
19
#include <asm/unistd.h>
20
 
21
void generic_fillattr(struct inode *inode, struct kstat *stat)
22
{
23
        stat->dev = inode->i_sb->s_dev;
24
        stat->ino = inode->i_ino;
25
        stat->mode = inode->i_mode;
26
        stat->nlink = inode->i_nlink;
27
        stat->uid = inode->i_uid;
28
        stat->gid = inode->i_gid;
29
        stat->rdev = inode->i_rdev;
30
        stat->atime = inode->i_atime;
31
        stat->mtime = inode->i_mtime;
32
        stat->ctime = inode->i_ctime;
33
        stat->size = i_size_read(inode);
34
        stat->blocks = inode->i_blocks;
35
        stat->blksize = (1 << inode->i_blkbits);
36
}
37
 
38
EXPORT_SYMBOL(generic_fillattr);
39
 
40
int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
41
{
42
        struct inode *inode = dentry->d_inode;
43
        int retval;
44
 
45
        retval = security_inode_getattr(mnt, dentry);
46
        if (retval)
47
                return retval;
48
 
49
        if (inode->i_op->getattr)
50
                return inode->i_op->getattr(mnt, dentry, stat);
51
 
52
        generic_fillattr(inode, stat);
53
        return 0;
54
}
55
 
56
EXPORT_SYMBOL(vfs_getattr);
57
 
58
int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
59
{
60
        struct nameidata nd;
61
        int error;
62
 
63
        error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
64
        if (!error) {
65
                error = vfs_getattr(nd.mnt, nd.dentry, stat);
66
                path_release(&nd);
67
        }
68
        return error;
69
}
70
 
71
int vfs_stat(char __user *name, struct kstat *stat)
72
{
73
        return vfs_stat_fd(AT_FDCWD, name, stat);
74
}
75
 
76
EXPORT_SYMBOL(vfs_stat);
77
 
78
int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
79
{
80
        struct nameidata nd;
81
        int error;
82
 
83
        error = __user_walk_fd(dfd, name, 0, &nd);
84
        if (!error) {
85
                error = vfs_getattr(nd.mnt, nd.dentry, stat);
86
                path_release(&nd);
87
        }
88
        return error;
89
}
90
 
91
int vfs_lstat(char __user *name, struct kstat *stat)
92
{
93
        return vfs_lstat_fd(AT_FDCWD, name, stat);
94
}
95
 
96
EXPORT_SYMBOL(vfs_lstat);
97
 
98
int vfs_fstat(unsigned int fd, struct kstat *stat)
99
{
100
        struct file *f = fget(fd);
101
        int error = -EBADF;
102
 
103
        if (f) {
104
                error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
105
                fput(f);
106
        }
107
        return error;
108
}
109
 
110
EXPORT_SYMBOL(vfs_fstat);
111
 
112
#ifdef __ARCH_WANT_OLD_STAT
113
 
114
/*
115
 * For backward compatibility?  Maybe this should be moved
116
 * into arch/i386 instead?
117
 */
118
static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
119
{
120
        static int warncount = 5;
121
        struct __old_kernel_stat tmp;
122
 
123
        if (warncount > 0) {
124
                warncount--;
125
                printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
126
                        current->comm);
127
        } else if (warncount < 0) {
128
                /* it's laughable, but... */
129
                warncount = 0;
130
        }
131
 
132
        memset(&tmp, 0, sizeof(struct __old_kernel_stat));
133
        tmp.st_dev = old_encode_dev(stat->dev);
134
        tmp.st_ino = stat->ino;
135
        if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
136
                return -EOVERFLOW;
137
        tmp.st_mode = stat->mode;
138
        tmp.st_nlink = stat->nlink;
139
        if (tmp.st_nlink != stat->nlink)
140
                return -EOVERFLOW;
141
        SET_UID(tmp.st_uid, stat->uid);
142
        SET_GID(tmp.st_gid, stat->gid);
143
        tmp.st_rdev = old_encode_dev(stat->rdev);
144
#if BITS_PER_LONG == 32
145
        if (stat->size > MAX_NON_LFS)
146
                return -EOVERFLOW;
147
#endif  
148
        tmp.st_size = stat->size;
149
        tmp.st_atime = stat->atime.tv_sec;
150
        tmp.st_mtime = stat->mtime.tv_sec;
151
        tmp.st_ctime = stat->ctime.tv_sec;
152
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
153
}
154
 
155
asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf)
156
{
157
        struct kstat stat;
158
        int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
159
 
160
        if (!error)
161
                error = cp_old_stat(&stat, statbuf);
162
 
163
        return error;
164
}
165
asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf)
166
{
167
        struct kstat stat;
168
        int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
169
 
170
        if (!error)
171
                error = cp_old_stat(&stat, statbuf);
172
 
173
        return error;
174
}
175
asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat __user * statbuf)
176
{
177
        struct kstat stat;
178
        int error = vfs_fstat(fd, &stat);
179
 
180
        if (!error)
181
                error = cp_old_stat(&stat, statbuf);
182
 
183
        return error;
184
}
185
 
186
#endif /* __ARCH_WANT_OLD_STAT */
187
 
188
static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
189
{
190
        struct stat tmp;
191
 
192
#if BITS_PER_LONG == 32
193
        if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
194
                return -EOVERFLOW;
195
#else
196
        if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
197
                return -EOVERFLOW;
198
#endif
199
 
200
        memset(&tmp, 0, sizeof(tmp));
201
#if BITS_PER_LONG == 32
202
        tmp.st_dev = old_encode_dev(stat->dev);
203
#else
204
        tmp.st_dev = new_encode_dev(stat->dev);
205
#endif
206
        tmp.st_ino = stat->ino;
207
        if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
208
                return -EOVERFLOW;
209
        tmp.st_mode = stat->mode;
210
        tmp.st_nlink = stat->nlink;
211
        if (tmp.st_nlink != stat->nlink)
212
                return -EOVERFLOW;
213
        SET_UID(tmp.st_uid, stat->uid);
214
        SET_GID(tmp.st_gid, stat->gid);
215
#if BITS_PER_LONG == 32
216
        tmp.st_rdev = old_encode_dev(stat->rdev);
217
#else
218
        tmp.st_rdev = new_encode_dev(stat->rdev);
219
#endif
220
#if BITS_PER_LONG == 32
221
        if (stat->size > MAX_NON_LFS)
222
                return -EOVERFLOW;
223
#endif  
224
        tmp.st_size = stat->size;
225
        tmp.st_atime = stat->atime.tv_sec;
226
        tmp.st_mtime = stat->mtime.tv_sec;
227
        tmp.st_ctime = stat->ctime.tv_sec;
228
#ifdef STAT_HAVE_NSEC
229
        tmp.st_atime_nsec = stat->atime.tv_nsec;
230
        tmp.st_mtime_nsec = stat->mtime.tv_nsec;
231
        tmp.st_ctime_nsec = stat->ctime.tv_nsec;
232
#endif
233
        tmp.st_blocks = stat->blocks;
234
        tmp.st_blksize = stat->blksize;
235
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
236
}
237
 
238
asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf)
239
{
240
        struct kstat stat;
241
        int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
242
 
243
        if (!error)
244
                error = cp_new_stat(&stat, statbuf);
245
 
246
        return error;
247
}
248
 
249
asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
250
{
251
        struct kstat stat;
252
        int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
253
 
254
        if (!error)
255
                error = cp_new_stat(&stat, statbuf);
256
 
257
        return error;
258
}
259
 
260
#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
261
asmlinkage long sys_newfstatat(int dfd, char __user *filename,
262
                                struct stat __user *statbuf, int flag)
263
{
264
        struct kstat stat;
265
        int error = -EINVAL;
266
 
267
        if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
268
                goto out;
269
 
270
        if (flag & AT_SYMLINK_NOFOLLOW)
271
                error = vfs_lstat_fd(dfd, filename, &stat);
272
        else
273
                error = vfs_stat_fd(dfd, filename, &stat);
274
 
275
        if (!error)
276
                error = cp_new_stat(&stat, statbuf);
277
 
278
out:
279
        return error;
280
}
281
#endif
282
 
283
asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
284
{
285
        struct kstat stat;
286
        int error = vfs_fstat(fd, &stat);
287
 
288
        if (!error)
289
                error = cp_new_stat(&stat, statbuf);
290
 
291
        return error;
292
}
293
 
294
asmlinkage long sys_readlinkat(int dfd, const char __user *path,
295
                                char __user *buf, int bufsiz)
296
{
297
        struct nameidata nd;
298
        int error;
299
 
300
        if (bufsiz <= 0)
301
                return -EINVAL;
302
 
303
        error = __user_walk_fd(dfd, path, 0, &nd);
304
        if (!error) {
305
                struct inode * inode = nd.dentry->d_inode;
306
 
307
                error = -EINVAL;
308
                if (inode->i_op && inode->i_op->readlink) {
309
                        error = security_inode_readlink(nd.dentry);
310
                        if (!error) {
311
                                touch_atime(nd.mnt, nd.dentry);
312
                                error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
313
                        }
314
                }
315
                path_release(&nd);
316
        }
317
        return error;
318
}
319
 
320
asmlinkage long sys_readlink(const char __user *path, char __user *buf,
321
                                int bufsiz)
322
{
323
        return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
324
}
325
 
326
 
327
/* ---------- LFS-64 ----------- */
328
#ifdef __ARCH_WANT_STAT64
329
 
330
static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
331
{
332
        struct stat64 tmp;
333
 
334
        memset(&tmp, 0, sizeof(struct stat64));
335
#ifdef CONFIG_MIPS
336
        /* mips has weird padding, so we don't get 64 bits there */
337
        if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
338
                return -EOVERFLOW;
339
        tmp.st_dev = new_encode_dev(stat->dev);
340
        tmp.st_rdev = new_encode_dev(stat->rdev);
341
#else
342
        tmp.st_dev = huge_encode_dev(stat->dev);
343
        tmp.st_rdev = huge_encode_dev(stat->rdev);
344
#endif
345
        tmp.st_ino = stat->ino;
346
        if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
347
                return -EOVERFLOW;
348
#ifdef STAT64_HAS_BROKEN_ST_INO
349
        tmp.__st_ino = stat->ino;
350
#endif
351
        tmp.st_mode = stat->mode;
352
        tmp.st_nlink = stat->nlink;
353
        tmp.st_uid = stat->uid;
354
        tmp.st_gid = stat->gid;
355
        tmp.st_atime = stat->atime.tv_sec;
356
        tmp.st_atime_nsec = stat->atime.tv_nsec;
357
        tmp.st_mtime = stat->mtime.tv_sec;
358
        tmp.st_mtime_nsec = stat->mtime.tv_nsec;
359
        tmp.st_ctime = stat->ctime.tv_sec;
360
        tmp.st_ctime_nsec = stat->ctime.tv_nsec;
361
        tmp.st_size = stat->size;
362
        tmp.st_blocks = stat->blocks;
363
        tmp.st_blksize = stat->blksize;
364
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
365
}
366
 
367
asmlinkage long sys_stat64(char __user * filename, struct stat64 __user * statbuf)
368
{
369
        struct kstat stat;
370
        int error = vfs_stat(filename, &stat);
371
 
372
        if (!error)
373
                error = cp_new_stat64(&stat, statbuf);
374
 
375
        return error;
376
}
377
asmlinkage long sys_lstat64(char __user * filename, struct stat64 __user * statbuf)
378
{
379
        struct kstat stat;
380
        int error = vfs_lstat(filename, &stat);
381
 
382
        if (!error)
383
                error = cp_new_stat64(&stat, statbuf);
384
 
385
        return error;
386
}
387
asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf)
388
{
389
        struct kstat stat;
390
        int error = vfs_fstat(fd, &stat);
391
 
392
        if (!error)
393
                error = cp_new_stat64(&stat, statbuf);
394
 
395
        return error;
396
}
397
 
398
asmlinkage long sys_fstatat64(int dfd, char __user *filename,
399
                               struct stat64 __user *statbuf, int flag)
400
{
401
        struct kstat stat;
402
        int error = -EINVAL;
403
 
404
        if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
405
                goto out;
406
 
407
        if (flag & AT_SYMLINK_NOFOLLOW)
408
                error = vfs_lstat_fd(dfd, filename, &stat);
409
        else
410
                error = vfs_stat_fd(dfd, filename, &stat);
411
 
412
        if (!error)
413
                error = cp_new_stat64(&stat, statbuf);
414
 
415
out:
416
        return error;
417
}
418
#endif /* __ARCH_WANT_STAT64 */
419
 
420
void inode_add_bytes(struct inode *inode, loff_t bytes)
421
{
422
        spin_lock(&inode->i_lock);
423
        inode->i_blocks += bytes >> 9;
424
        bytes &= 511;
425
        inode->i_bytes += bytes;
426
        if (inode->i_bytes >= 512) {
427
                inode->i_blocks++;
428
                inode->i_bytes -= 512;
429
        }
430
        spin_unlock(&inode->i_lock);
431
}
432
 
433
EXPORT_SYMBOL(inode_add_bytes);
434
 
435
void inode_sub_bytes(struct inode *inode, loff_t bytes)
436
{
437
        spin_lock(&inode->i_lock);
438
        inode->i_blocks -= bytes >> 9;
439
        bytes &= 511;
440
        if (inode->i_bytes < bytes) {
441
                inode->i_blocks--;
442
                inode->i_bytes += 512;
443
        }
444
        inode->i_bytes -= bytes;
445
        spin_unlock(&inode->i_lock);
446
}
447
 
448
EXPORT_SYMBOL(inode_sub_bytes);
449
 
450
loff_t inode_get_bytes(struct inode *inode)
451
{
452
        loff_t ret;
453
 
454
        spin_lock(&inode->i_lock);
455
        ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
456
        spin_unlock(&inode->i_lock);
457
        return ret;
458
}
459
 
460
EXPORT_SYMBOL(inode_get_bytes);
461
 
462
void inode_set_bytes(struct inode *inode, loff_t bytes)
463
{
464
        /* Caller is here responsible for sufficient locking
465
         * (ie. inode->i_lock) */
466
        inode->i_blocks = bytes >> 9;
467
        inode->i_bytes = bytes & 511;
468
}
469
 
470
EXPORT_SYMBOL(inode_set_bytes);

powered by: WebSVN 2.1.0

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