Root/fs/stat.c

Source at commit 9845c1745d3d531a5b9544f5322c62bfb4d4e9bc created 1 year 2 months ago.
By Xiangfu, rtc: jz4740 fix hwclock give time out
1/*
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
21void 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->size = i_size_read(inode);
31    stat->atime = inode->i_atime;
32    stat->mtime = inode->i_mtime;
33    stat->ctime = inode->i_ctime;
34    stat->blksize = (1 << inode->i_blkbits);
35    stat->blocks = inode->i_blocks;
36}
37
38EXPORT_SYMBOL(generic_fillattr);
39
40int 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
56EXPORT_SYMBOL(vfs_getattr);
57
58int vfs_fstat(unsigned int fd, struct kstat *stat)
59{
60    struct file *f = fget(fd);
61    int error = -EBADF;
62
63    if (f) {
64        error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
65        fput(f);
66    }
67    return error;
68}
69EXPORT_SYMBOL(vfs_fstat);
70
71int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
72        int flag)
73{
74    struct path path;
75    int error = -EINVAL;
76    int lookup_flags = 0;
77
78    if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
79              AT_EMPTY_PATH)) != 0)
80        goto out;
81
82    if (!(flag & AT_SYMLINK_NOFOLLOW))
83        lookup_flags |= LOOKUP_FOLLOW;
84    if (flag & AT_EMPTY_PATH)
85        lookup_flags |= LOOKUP_EMPTY;
86
87    error = user_path_at(dfd, filename, lookup_flags, &path);
88    if (error)
89        goto out;
90
91    error = vfs_getattr(path.mnt, path.dentry, stat);
92    path_put(&path);
93out:
94    return error;
95}
96EXPORT_SYMBOL(vfs_fstatat);
97
98int vfs_stat(const char __user *name, struct kstat *stat)
99{
100    return vfs_fstatat(AT_FDCWD, name, stat, 0);
101}
102EXPORT_SYMBOL(vfs_stat);
103
104int vfs_lstat(const char __user *name, struct kstat *stat)
105{
106    return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW);
107}
108EXPORT_SYMBOL(vfs_lstat);
109
110
111#ifdef __ARCH_WANT_OLD_STAT
112
113/*
114 * For backward compatibility? Maybe this should be moved
115 * into arch/i386 instead?
116 */
117static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
118{
119    static int warncount = 5;
120    struct __old_kernel_stat tmp;
121    
122    if (warncount > 0) {
123        warncount--;
124        printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
125            current->comm);
126    } else if (warncount < 0) {
127        /* it's laughable, but... */
128        warncount = 0;
129    }
130
131    memset(&tmp, 0, sizeof(struct __old_kernel_stat));
132    tmp.st_dev = old_encode_dev(stat->dev);
133    tmp.st_ino = stat->ino;
134    if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
135        return -EOVERFLOW;
136    tmp.st_mode = stat->mode;
137    tmp.st_nlink = stat->nlink;
138    if (tmp.st_nlink != stat->nlink)
139        return -EOVERFLOW;
140    SET_UID(tmp.st_uid, stat->uid);
141    SET_GID(tmp.st_gid, stat->gid);
142    tmp.st_rdev = old_encode_dev(stat->rdev);
143#if BITS_PER_LONG == 32
144    if (stat->size > MAX_NON_LFS)
145        return -EOVERFLOW;
146#endif
147    tmp.st_size = stat->size;
148    tmp.st_atime = stat->atime.tv_sec;
149    tmp.st_mtime = stat->mtime.tv_sec;
150    tmp.st_ctime = stat->ctime.tv_sec;
151    return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
152}
153
154SYSCALL_DEFINE2(stat, const char __user *, filename,
155        struct __old_kernel_stat __user *, statbuf)
156{
157    struct kstat stat;
158    int error;
159
160    error = vfs_stat(filename, &stat);
161    if (error)
162        return error;
163
164    return cp_old_stat(&stat, statbuf);
165}
166
167SYSCALL_DEFINE2(lstat, const char __user *, filename,
168        struct __old_kernel_stat __user *, statbuf)
169{
170    struct kstat stat;
171    int error;
172
173    error = vfs_lstat(filename, &stat);
174    if (error)
175        return error;
176
177    return cp_old_stat(&stat, statbuf);
178}
179
180SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
181{
182    struct kstat stat;
183    int error = vfs_fstat(fd, &stat);
184
185    if (!error)
186        error = cp_old_stat(&stat, statbuf);
187
188    return error;
189}
190
191#endif /* __ARCH_WANT_OLD_STAT */
192
193static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
194{
195    struct stat tmp;
196
197#if BITS_PER_LONG == 32
198    if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
199        return -EOVERFLOW;
200#else
201    if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
202        return -EOVERFLOW;
203#endif
204
205    memset(&tmp, 0, sizeof(tmp));
206#if BITS_PER_LONG == 32
207    tmp.st_dev = old_encode_dev(stat->dev);
208#else
209    tmp.st_dev = new_encode_dev(stat->dev);
210#endif
211    tmp.st_ino = stat->ino;
212    if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
213        return -EOVERFLOW;
214    tmp.st_mode = stat->mode;
215    tmp.st_nlink = stat->nlink;
216    if (tmp.st_nlink != stat->nlink)
217        return -EOVERFLOW;
218    SET_UID(tmp.st_uid, stat->uid);
219    SET_GID(tmp.st_gid, stat->gid);
220#if BITS_PER_LONG == 32
221    tmp.st_rdev = old_encode_dev(stat->rdev);
222#else
223    tmp.st_rdev = new_encode_dev(stat->rdev);
224#endif
225#if BITS_PER_LONG == 32
226    if (stat->size > MAX_NON_LFS)
227        return -EOVERFLOW;
228#endif
229    tmp.st_size = stat->size;
230    tmp.st_atime = stat->atime.tv_sec;
231    tmp.st_mtime = stat->mtime.tv_sec;
232    tmp.st_ctime = stat->ctime.tv_sec;
233#ifdef STAT_HAVE_NSEC
234    tmp.st_atime_nsec = stat->atime.tv_nsec;
235    tmp.st_mtime_nsec = stat->mtime.tv_nsec;
236    tmp.st_ctime_nsec = stat->ctime.tv_nsec;
237#endif
238    tmp.st_blocks = stat->blocks;
239    tmp.st_blksize = stat->blksize;
240    return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
241}
242
243SYSCALL_DEFINE2(newstat, const char __user *, filename,
244        struct stat __user *, statbuf)
245{
246    struct kstat stat;
247    int error = vfs_stat(filename, &stat);
248
249    if (error)
250        return error;
251    return cp_new_stat(&stat, statbuf);
252}
253
254SYSCALL_DEFINE2(newlstat, const char __user *, filename,
255        struct stat __user *, statbuf)
256{
257    struct kstat stat;
258    int error;
259
260    error = vfs_lstat(filename, &stat);
261    if (error)
262        return error;
263
264    return cp_new_stat(&stat, statbuf);
265}
266
267#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
268SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
269        struct stat __user *, statbuf, int, flag)
270{
271    struct kstat stat;
272    int error;
273
274    error = vfs_fstatat(dfd, filename, &stat, flag);
275    if (error)
276        return error;
277    return cp_new_stat(&stat, statbuf);
278}
279#endif
280
281SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
282{
283    struct kstat stat;
284    int error = vfs_fstat(fd, &stat);
285
286    if (!error)
287        error = cp_new_stat(&stat, statbuf);
288
289    return error;
290}
291
292SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
293        char __user *, buf, int, bufsiz)
294{
295    struct path path;
296    int error;
297    int empty = 0;
298
299    if (bufsiz <= 0)
300        return -EINVAL;
301
302    error = user_path_at_empty(dfd, pathname, LOOKUP_EMPTY, &path, &empty);
303    if (!error) {
304        struct inode *inode = path.dentry->d_inode;
305
306        error = empty ? -ENOENT : -EINVAL;
307        if (inode->i_op->readlink) {
308            error = security_inode_readlink(path.dentry);
309            if (!error) {
310                touch_atime(path.mnt, path.dentry);
311                error = inode->i_op->readlink(path.dentry,
312                                  buf, bufsiz);
313            }
314        }
315        path_put(&path);
316    }
317    return error;
318}
319
320SYSCALL_DEFINE3(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
330static 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
367SYSCALL_DEFINE2(stat64, const char __user *, filename,
368        struct stat64 __user *, statbuf)
369{
370    struct kstat stat;
371    int error = vfs_stat(filename, &stat);
372
373    if (!error)
374        error = cp_new_stat64(&stat, statbuf);
375
376    return error;
377}
378
379SYSCALL_DEFINE2(lstat64, const char __user *, filename,
380        struct stat64 __user *, statbuf)
381{
382    struct kstat stat;
383    int error = vfs_lstat(filename, &stat);
384
385    if (!error)
386        error = cp_new_stat64(&stat, statbuf);
387
388    return error;
389}
390
391SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
392{
393    struct kstat stat;
394    int error = vfs_fstat(fd, &stat);
395
396    if (!error)
397        error = cp_new_stat64(&stat, statbuf);
398
399    return error;
400}
401
402SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
403        struct stat64 __user *, statbuf, int, flag)
404{
405    struct kstat stat;
406    int error;
407
408    error = vfs_fstatat(dfd, filename, &stat, flag);
409    if (error)
410        return error;
411    return cp_new_stat64(&stat, statbuf);
412}
413#endif /* __ARCH_WANT_STAT64 */
414
415/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
416void __inode_add_bytes(struct inode *inode, loff_t bytes)
417{
418    inode->i_blocks += bytes >> 9;
419    bytes &= 511;
420    inode->i_bytes += bytes;
421    if (inode->i_bytes >= 512) {
422        inode->i_blocks++;
423        inode->i_bytes -= 512;
424    }
425}
426
427void inode_add_bytes(struct inode *inode, loff_t bytes)
428{
429    spin_lock(&inode->i_lock);
430    __inode_add_bytes(inode, bytes);
431    spin_unlock(&inode->i_lock);
432}
433
434EXPORT_SYMBOL(inode_add_bytes);
435
436void inode_sub_bytes(struct inode *inode, loff_t bytes)
437{
438    spin_lock(&inode->i_lock);
439    inode->i_blocks -= bytes >> 9;
440    bytes &= 511;
441    if (inode->i_bytes < bytes) {
442        inode->i_blocks--;
443        inode->i_bytes += 512;
444    }
445    inode->i_bytes -= bytes;
446    spin_unlock(&inode->i_lock);
447}
448
449EXPORT_SYMBOL(inode_sub_bytes);
450
451loff_t inode_get_bytes(struct inode *inode)
452{
453    loff_t ret;
454
455    spin_lock(&inode->i_lock);
456    ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
457    spin_unlock(&inode->i_lock);
458    return ret;
459}
460
461EXPORT_SYMBOL(inode_get_bytes);
462
463void inode_set_bytes(struct inode *inode, loff_t bytes)
464{
465    /* Caller is here responsible for sufficient locking
466     * (ie. inode->i_lock) */
467    inode->i_blocks = bytes >> 9;
468    inode->i_bytes = bytes & 511;
469}
470
471EXPORT_SYMBOL(inode_set_bytes);
472

Archive Download this file



interactive