stat.c (9095bf25ea08135a5b74875dd0e3eeaddc4218a0) stat.c (1e2f82d1e9d12223b4cbd1feb3f2b5596f8049eb)
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>

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

125 * This function is a wrapper around vfs_getattr(). The main difference is
126 * that it uses a file descriptor to determine the file location.
127 *
128 * 0 will be returned on success, and a -ve error code if unsuccessful.
129 */
130int vfs_statx_fd(unsigned int fd, struct kstat *stat,
131 u32 request_mask, unsigned int query_flags)
132{
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>

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

125 * This function is a wrapper around vfs_getattr(). The main difference is
126 * that it uses a file descriptor to determine the file location.
127 *
128 * 0 will be returned on success, and a -ve error code if unsuccessful.
129 */
130int vfs_statx_fd(unsigned int fd, struct kstat *stat,
131 u32 request_mask, unsigned int query_flags)
132{
133 struct fd f = fdget_raw(fd);
133 struct fd f;
134 int error = -EBADF;
135
134 int error = -EBADF;
135
136 if (query_flags & ~KSTAT_QUERY_FLAGS)
137 return -EINVAL;
138
139 f = fdget_raw(fd);
136 if (f.file) {
137 error = vfs_getattr(&f.file->f_path, stat,
138 request_mask, query_flags);
139 fdput(f);
140 }
141 return error;
142}
143EXPORT_SYMBOL(vfs_statx_fd);

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

150 * @stat: The result structure to fill in.
151 * @request_mask: STATX_xxx flags indicating what the caller wants
152 *
153 * This function is a wrapper around vfs_getattr(). The main difference is
154 * that it uses a filename and base directory to determine the file location.
155 * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
156 * at the given name from being referenced.
157 *
140 if (f.file) {
141 error = vfs_getattr(&f.file->f_path, stat,
142 request_mask, query_flags);
143 fdput(f);
144 }
145 return error;
146}
147EXPORT_SYMBOL(vfs_statx_fd);

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

154 * @stat: The result structure to fill in.
155 * @request_mask: STATX_xxx flags indicating what the caller wants
156 *
157 * This function is a wrapper around vfs_getattr(). The main difference is
158 * that it uses a filename and base directory to determine the file location.
159 * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
160 * at the given name from being referenced.
161 *
158 * The caller must have preset stat->request_mask as for vfs_getattr(). The
159 * flags are also used to load up stat->query_flags.
160 *
161 * 0 will be returned on success, and a -ve error code if unsuccessful.
162 */
163int vfs_statx(int dfd, const char __user *filename, int flags,
164 struct kstat *stat, u32 request_mask)
165{
166 struct path path;
167 int error = -EINVAL;
168 unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;

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

504
505 error = vfs_fstatat(dfd, filename, &stat, flag);
506 if (error)
507 return error;
508 return cp_new_stat64(&stat, statbuf);
509}
510#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
511
162 * 0 will be returned on success, and a -ve error code if unsuccessful.
163 */
164int vfs_statx(int dfd, const char __user *filename, int flags,
165 struct kstat *stat, u32 request_mask)
166{
167 struct path path;
168 int error = -EINVAL;
169 unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;

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

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

--- 58 unchanged lines hidden ---
578}
579
580/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
581void __inode_add_bytes(struct inode *inode, loff_t bytes)
582{
583 inode->i_blocks += bytes >> 9;
584 bytes &= 511;
585 inode->i_bytes += bytes;

--- 58 unchanged lines hidden ---