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 --- |