stat.c (5b825c3af1d8a0af4deb4a5eb349d0d0050c62e5) stat.c (a528d35e8bfcc521d7cb70aaf03e1bd296c8493f)
1/*
2 * linux/fs/stat.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
6
7#include <linux/export.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>
1/*
2 * linux/fs/stat.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
6
7#include <linux/export.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/cred.h>
16#include <linux/syscalls.h>
17#include <linux/pagemap.h>
18
19#include <linux/uaccess.h>
20#include <asm/unistd.h>
21
15#include <linux/syscalls.h>
16#include <linux/pagemap.h>
17
18#include <linux/uaccess.h>
19#include <asm/unistd.h>
20
21/**
22 * generic_fillattr - Fill in the basic attributes from the inode struct
23 * @inode: Inode to use as the source
24 * @stat: Where to fill in the attributes
25 *
26 * Fill in the basic attributes in the kstat structure from data that's to be
27 * found on the VFS inode structure. This is the default if no getattr inode
28 * operation is supplied.
29 */
22void generic_fillattr(struct inode *inode, struct kstat *stat)
23{
24 stat->dev = inode->i_sb->s_dev;
25 stat->ino = inode->i_ino;
26 stat->mode = inode->i_mode;
27 stat->nlink = inode->i_nlink;
28 stat->uid = inode->i_uid;
29 stat->gid = inode->i_gid;
30 stat->rdev = inode->i_rdev;
31 stat->size = i_size_read(inode);
32 stat->atime = inode->i_atime;
33 stat->mtime = inode->i_mtime;
34 stat->ctime = inode->i_ctime;
35 stat->blksize = i_blocksize(inode);
36 stat->blocks = inode->i_blocks;
30void generic_fillattr(struct inode *inode, struct kstat *stat)
31{
32 stat->dev = inode->i_sb->s_dev;
33 stat->ino = inode->i_ino;
34 stat->mode = inode->i_mode;
35 stat->nlink = inode->i_nlink;
36 stat->uid = inode->i_uid;
37 stat->gid = inode->i_gid;
38 stat->rdev = inode->i_rdev;
39 stat->size = i_size_read(inode);
40 stat->atime = inode->i_atime;
41 stat->mtime = inode->i_mtime;
42 stat->ctime = inode->i_ctime;
43 stat->blksize = i_blocksize(inode);
44 stat->blocks = inode->i_blocks;
37}
38
45
46 if (IS_NOATIME(inode))
47 stat->result_mask &= ~STATX_ATIME;
48 if (IS_AUTOMOUNT(inode))
49 stat->attributes |= STATX_ATTR_AUTOMOUNT;
50}
39EXPORT_SYMBOL(generic_fillattr);
40
41/**
42 * vfs_getattr_nosec - getattr without security checks
43 * @path: file to get attributes from
44 * @stat: structure to return attributes in
51EXPORT_SYMBOL(generic_fillattr);
52
53/**
54 * vfs_getattr_nosec - getattr without security checks
55 * @path: file to get attributes from
56 * @stat: structure to return attributes in
57 * @request_mask: STATX_xxx flags indicating what the caller wants
58 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
45 *
46 * Get attributes without calling security_inode_getattr.
47 *
48 * Currently the only caller other than vfs_getattr is internal to the
59 *
60 * Get attributes without calling security_inode_getattr.
61 *
62 * Currently the only caller other than vfs_getattr is internal to the
49 * filehandle lookup code, which uses only the inode number and returns
50 * no attributes to any user. Any other code probably wants
51 * vfs_getattr.
63 * filehandle lookup code, which uses only the inode number and returns no
64 * attributes to any user. Any other code probably wants vfs_getattr.
52 */
65 */
53int vfs_getattr_nosec(struct path *path, struct kstat *stat)
66int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
67 u32 request_mask, unsigned int query_flags)
54{
55 struct inode *inode = d_backing_inode(path->dentry);
56
68{
69 struct inode *inode = d_backing_inode(path->dentry);
70
71 memset(stat, 0, sizeof(*stat));
72 stat->result_mask |= STATX_BASIC_STATS;
73 request_mask &= STATX_ALL;
74 query_flags &= KSTAT_QUERY_FLAGS;
57 if (inode->i_op->getattr)
75 if (inode->i_op->getattr)
58 return inode->i_op->getattr(path->mnt, path->dentry, stat);
76 return inode->i_op->getattr(path, stat, request_mask,
77 query_flags);
59
60 generic_fillattr(inode, stat);
61 return 0;
62}
78
79 generic_fillattr(inode, stat);
80 return 0;
81}
63
64EXPORT_SYMBOL(vfs_getattr_nosec);
65
82EXPORT_SYMBOL(vfs_getattr_nosec);
83
66int vfs_getattr(struct path *path, struct kstat *stat)
84/*
85 * vfs_getattr - Get the enhanced basic attributes of a file
86 * @path: The file of interest
87 * @stat: Where to return the statistics
88 * @request_mask: STATX_xxx flags indicating what the caller wants
89 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
90 *
91 * Ask the filesystem for a file's attributes. The caller must indicate in
92 * request_mask and query_flags to indicate what they want.
93 *
94 * If the file is remote, the filesystem can be forced to update the attributes
95 * from the backing store by passing AT_STATX_FORCE_SYNC in query_flags or can
96 * suppress the update by passing AT_STATX_DONT_SYNC.
97 *
98 * Bits must have been set in request_mask to indicate which attributes the
99 * caller wants retrieving. Any such attribute not requested may be returned
100 * anyway, but the value may be approximate, and, if remote, may not have been
101 * synchronised with the server.
102 *
103 * 0 will be returned on success, and a -ve error code if unsuccessful.
104 */
105int vfs_getattr(const struct path *path, struct kstat *stat,
106 u32 request_mask, unsigned int query_flags)
67{
68 int retval;
69
70 retval = security_inode_getattr(path);
71 if (retval)
72 return retval;
107{
108 int retval;
109
110 retval = security_inode_getattr(path);
111 if (retval)
112 return retval;
73 return vfs_getattr_nosec(path, stat);
113 return vfs_getattr_nosec(path, stat, request_mask, query_flags);
74}
114}
75
76EXPORT_SYMBOL(vfs_getattr);
77
115EXPORT_SYMBOL(vfs_getattr);
116
78int vfs_fstat(unsigned int fd, struct kstat *stat)
117/**
118 * vfs_statx_fd - Get the enhanced basic attributes by file descriptor
119 * @fd: The file descriptor referring to the file of interest
120 * @stat: The result structure to fill in.
121 * @request_mask: STATX_xxx flags indicating what the caller wants
122 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
123 *
124 * This function is a wrapper around vfs_getattr(). The main difference is
125 * that it uses a file descriptor to determine the file location.
126 *
127 * 0 will be returned on success, and a -ve error code if unsuccessful.
128 */
129int vfs_statx_fd(unsigned int fd, struct kstat *stat,
130 u32 request_mask, unsigned int query_flags)
79{
80 struct fd f = fdget_raw(fd);
81 int error = -EBADF;
82
83 if (f.file) {
131{
132 struct fd f = fdget_raw(fd);
133 int error = -EBADF;
134
135 if (f.file) {
84 error = vfs_getattr(&f.file->f_path, stat);
136 error = vfs_getattr(&f.file->f_path, stat,
137 request_mask, query_flags);
85 fdput(f);
86 }
87 return error;
88}
138 fdput(f);
139 }
140 return error;
141}
89EXPORT_SYMBOL(vfs_fstat);
142EXPORT_SYMBOL(vfs_statx_fd);
90
143
91int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
92 int flag)
144/**
145 * vfs_statx - Get basic and extra attributes by filename
146 * @dfd: A file descriptor representing the base dir for a relative filename
147 * @filename: The name of the file of interest
148 * @flags: Flags to control the query
149 * @stat: The result structure to fill in.
150 * @request_mask: STATX_xxx flags indicating what the caller wants
151 *
152 * This function is a wrapper around vfs_getattr(). The main difference is
153 * that it uses a filename and base directory to determine the file location.
154 * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
155 * at the given name from being referenced.
156 *
157 * The caller must have preset stat->request_mask as for vfs_getattr(). The
158 * flags are also used to load up stat->query_flags.
159 *
160 * 0 will be returned on success, and a -ve error code if unsuccessful.
161 */
162int vfs_statx(int dfd, const char __user *filename, int flags,
163 struct kstat *stat, u32 request_mask)
93{
94 struct path path;
95 int error = -EINVAL;
164{
165 struct path path;
166 int error = -EINVAL;
96 unsigned int lookup_flags = 0;
167 unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
97
168
98 if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
99 AT_EMPTY_PATH)) != 0)
100 goto out;
169 if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
170 AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0)
171 return -EINVAL;
101
172
102 if (!(flag & AT_SYMLINK_NOFOLLOW))
103 lookup_flags |= LOOKUP_FOLLOW;
104 if (flag & AT_EMPTY_PATH)
173 if (flags & AT_SYMLINK_NOFOLLOW)
174 lookup_flags &= ~LOOKUP_FOLLOW;
175 if (flags & AT_NO_AUTOMOUNT)
176 lookup_flags &= ~LOOKUP_AUTOMOUNT;
177 if (flags & AT_EMPTY_PATH)
105 lookup_flags |= LOOKUP_EMPTY;
178 lookup_flags |= LOOKUP_EMPTY;
179
106retry:
107 error = user_path_at(dfd, filename, lookup_flags, &path);
108 if (error)
109 goto out;
110
180retry:
181 error = user_path_at(dfd, filename, lookup_flags, &path);
182 if (error)
183 goto out;
184
111 error = vfs_getattr(&path, stat);
185 error = vfs_getattr(&path, stat, request_mask, flags);
112 path_put(&path);
113 if (retry_estale(error, lookup_flags)) {
114 lookup_flags |= LOOKUP_REVAL;
115 goto retry;
116 }
117out:
118 return error;
119}
186 path_put(&path);
187 if (retry_estale(error, lookup_flags)) {
188 lookup_flags |= LOOKUP_REVAL;
189 goto retry;
190 }
191out:
192 return error;
193}
120EXPORT_SYMBOL(vfs_fstatat);
194EXPORT_SYMBOL(vfs_statx);
121
195
122int vfs_stat(const char __user *name, struct kstat *stat)
123{
124 return vfs_fstatat(AT_FDCWD, name, stat, 0);
125}
126EXPORT_SYMBOL(vfs_stat);
127
196
128int vfs_lstat(const char __user *name, struct kstat *stat)
129{
130 return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW);
131}
132EXPORT_SYMBOL(vfs_lstat);
133
134
135#ifdef __ARCH_WANT_OLD_STAT
136
137/*
138 * For backward compatibility? Maybe this should be moved
139 * into arch/i386 instead?
140 */
141static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
142{
143 static int warncount = 5;
144 struct __old_kernel_stat tmp;
197#ifdef __ARCH_WANT_OLD_STAT
198
199/*
200 * For backward compatibility? Maybe this should be moved
201 * into arch/i386 instead?
202 */
203static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
204{
205 static int warncount = 5;
206 struct __old_kernel_stat tmp;
145
207
146 if (warncount > 0) {
147 warncount--;
148 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
149 current->comm);
150 } else if (warncount < 0) {
151 /* it's laughable, but... */
152 warncount = 0;
153 }

--- 8 unchanged lines hidden (view full) ---

162 if (tmp.st_nlink != stat->nlink)
163 return -EOVERFLOW;
164 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
165 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
166 tmp.st_rdev = old_encode_dev(stat->rdev);
167#if BITS_PER_LONG == 32
168 if (stat->size > MAX_NON_LFS)
169 return -EOVERFLOW;
208 if (warncount > 0) {
209 warncount--;
210 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
211 current->comm);
212 } else if (warncount < 0) {
213 /* it's laughable, but... */
214 warncount = 0;
215 }

--- 8 unchanged lines hidden (view full) ---

224 if (tmp.st_nlink != stat->nlink)
225 return -EOVERFLOW;
226 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
227 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
228 tmp.st_rdev = old_encode_dev(stat->rdev);
229#if BITS_PER_LONG == 32
230 if (stat->size > MAX_NON_LFS)
231 return -EOVERFLOW;
170#endif
232#endif
171 tmp.st_size = stat->size;
172 tmp.st_atime = stat->atime.tv_sec;
173 tmp.st_mtime = stat->mtime.tv_sec;
174 tmp.st_ctime = stat->ctime.tv_sec;
175 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
176}
177
178SYSCALL_DEFINE2(stat, const char __user *, filename,

--- 262 unchanged lines hidden (view full) ---

441
442 error = vfs_fstatat(dfd, filename, &stat, flag);
443 if (error)
444 return error;
445 return cp_new_stat64(&stat, statbuf);
446}
447#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
448
233 tmp.st_size = stat->size;
234 tmp.st_atime = stat->atime.tv_sec;
235 tmp.st_mtime = stat->mtime.tv_sec;
236 tmp.st_ctime = stat->ctime.tv_sec;
237 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
238}
239
240SYSCALL_DEFINE2(stat, const char __user *, filename,

--- 262 unchanged lines hidden (view full) ---

503
504 error = vfs_fstatat(dfd, filename, &stat, flag);
505 if (error)
506 return error;
507 return cp_new_stat64(&stat, statbuf);
508}
509#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
510
511static inline int __put_timestamp(struct timespec *kts,
512 struct statx_timestamp __user *uts)
513{
514 return (__put_user(kts->tv_sec, &uts->tv_sec ) ||
515 __put_user(kts->tv_nsec, &uts->tv_nsec ) ||
516 __put_user(0, &uts->__reserved ));
517}
518
519/*
520 * Set the statx results.
521 */
522static long statx_set_result(struct kstat *stat, struct statx __user *buffer)
523{
524 uid_t uid = from_kuid_munged(current_user_ns(), stat->uid);
525 gid_t gid = from_kgid_munged(current_user_ns(), stat->gid);
526
527 if (__put_user(stat->result_mask, &buffer->stx_mask ) ||
528 __put_user(stat->mode, &buffer->stx_mode ) ||
529 __clear_user(&buffer->__spare0, sizeof(buffer->__spare0)) ||
530 __put_user(stat->nlink, &buffer->stx_nlink ) ||
531 __put_user(uid, &buffer->stx_uid ) ||
532 __put_user(gid, &buffer->stx_gid ) ||
533 __put_user(stat->attributes, &buffer->stx_attributes ) ||
534 __put_user(stat->blksize, &buffer->stx_blksize ) ||
535 __put_user(MAJOR(stat->rdev), &buffer->stx_rdev_major ) ||
536 __put_user(MINOR(stat->rdev), &buffer->stx_rdev_minor ) ||
537 __put_user(MAJOR(stat->dev), &buffer->stx_dev_major ) ||
538 __put_user(MINOR(stat->dev), &buffer->stx_dev_minor ) ||
539 __put_timestamp(&stat->atime, &buffer->stx_atime ) ||
540 __put_timestamp(&stat->btime, &buffer->stx_btime ) ||
541 __put_timestamp(&stat->ctime, &buffer->stx_ctime ) ||
542 __put_timestamp(&stat->mtime, &buffer->stx_mtime ) ||
543 __put_user(stat->ino, &buffer->stx_ino ) ||
544 __put_user(stat->size, &buffer->stx_size ) ||
545 __put_user(stat->blocks, &buffer->stx_blocks ) ||
546 __clear_user(&buffer->__spare1, sizeof(buffer->__spare1)) ||
547 __clear_user(&buffer->__spare2, sizeof(buffer->__spare2)))
548 return -EFAULT;
549
550 return 0;
551}
552
553/**
554 * sys_statx - System call to get enhanced stats
555 * @dfd: Base directory to pathwalk from *or* fd to stat.
556 * @filename: File to stat *or* NULL.
557 * @flags: AT_* flags to control pathwalk.
558 * @mask: Parts of statx struct actually required.
559 * @buffer: Result buffer.
560 *
561 * Note that if filename is NULL, then it does the equivalent of fstat() using
562 * dfd to indicate the file of interest.
563 */
564SYSCALL_DEFINE5(statx,
565 int, dfd, const char __user *, filename, unsigned, flags,
566 unsigned int, mask,
567 struct statx __user *, buffer)
568{
569 struct kstat stat;
570 int error;
571
572 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
573 return -EINVAL;
574 if (!access_ok(VERIFY_WRITE, buffer, sizeof(*buffer)))
575 return -EFAULT;
576
577 if (filename)
578 error = vfs_statx(dfd, filename, flags, &stat, mask);
579 else
580 error = vfs_statx_fd(dfd, &stat, mask, flags);
581 if (error)
582 return error;
583 return statx_set_result(&stat, buffer);
584}
585
449/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
450void __inode_add_bytes(struct inode *inode, loff_t bytes)
451{
452 inode->i_blocks += bytes >> 9;
453 bytes &= 511;
454 inode->i_bytes += bytes;
455 if (inode->i_bytes >= 512) {
456 inode->i_blocks++;

--- 56 unchanged lines hidden ---
586/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
587void __inode_add_bytes(struct inode *inode, loff_t bytes)
588{
589 inode->i_blocks += bytes >> 9;
590 bytes &= 511;
591 inode->i_bytes += bytes;
592 if (inode->i_bytes >= 512) {
593 inode->i_blocks++;

--- 56 unchanged lines hidden ---