statx: reject unknown flags when using NULL path
[linux-block.git] / fs / stat.c
CommitLineData
1da177e4
LT
1/*
2 * linux/fs/stat.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
6
630d9c47 7#include <linux/export.h>
1da177e4
LT
8#include <linux/mm.h>
9#include <linux/errno.h>
10#include <linux/file.h>
1da177e4
LT
11#include <linux/highuid.h>
12#include <linux/fs.h>
13#include <linux/namei.h>
14#include <linux/security.h>
5b825c3a 15#include <linux/cred.h>
1da177e4 16#include <linux/syscalls.h>
ba52de12 17#include <linux/pagemap.h>
1da177e4 18
7c0f6ba6 19#include <linux/uaccess.h>
1da177e4
LT
20#include <asm/unistd.h>
21
a528d35e
DH
22/**
23 * generic_fillattr - Fill in the basic attributes from the inode struct
24 * @inode: Inode to use as the source
25 * @stat: Where to fill in the attributes
26 *
27 * Fill in the basic attributes in the kstat structure from data that's to be
28 * found on the VFS inode structure. This is the default if no getattr inode
29 * operation is supplied.
30 */
1da177e4
LT
31void generic_fillattr(struct inode *inode, struct kstat *stat)
32{
33 stat->dev = inode->i_sb->s_dev;
34 stat->ino = inode->i_ino;
35 stat->mode = inode->i_mode;
36 stat->nlink = inode->i_nlink;
37 stat->uid = inode->i_uid;
38 stat->gid = inode->i_gid;
39 stat->rdev = inode->i_rdev;
3ddcd056 40 stat->size = i_size_read(inode);
1da177e4
LT
41 stat->atime = inode->i_atime;
42 stat->mtime = inode->i_mtime;
43 stat->ctime = inode->i_ctime;
93407472 44 stat->blksize = i_blocksize(inode);
3ddcd056 45 stat->blocks = inode->i_blocks;
1da177e4 46
a528d35e
DH
47 if (IS_NOATIME(inode))
48 stat->result_mask &= ~STATX_ATIME;
49 if (IS_AUTOMOUNT(inode))
50 stat->attributes |= STATX_ATTR_AUTOMOUNT;
51}
1da177e4
LT
52EXPORT_SYMBOL(generic_fillattr);
53
b7a6ec52
BF
54/**
55 * vfs_getattr_nosec - getattr without security checks
56 * @path: file to get attributes from
57 * @stat: structure to return attributes in
a528d35e
DH
58 * @request_mask: STATX_xxx flags indicating what the caller wants
59 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
b7a6ec52
BF
60 *
61 * Get attributes without calling security_inode_getattr.
62 *
63 * Currently the only caller other than vfs_getattr is internal to the
a528d35e
DH
64 * filehandle lookup code, which uses only the inode number and returns no
65 * attributes to any user. Any other code probably wants vfs_getattr.
b7a6ec52 66 */
a528d35e
DH
67int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
68 u32 request_mask, unsigned int query_flags)
1da177e4 69{
bb668734 70 struct inode *inode = d_backing_inode(path->dentry);
1da177e4 71
a528d35e
DH
72 memset(stat, 0, sizeof(*stat));
73 stat->result_mask |= STATX_BASIC_STATS;
74 request_mask &= STATX_ALL;
75 query_flags &= KSTAT_QUERY_FLAGS;
1da177e4 76 if (inode->i_op->getattr)
a528d35e
DH
77 return inode->i_op->getattr(path, stat, request_mask,
78 query_flags);
1da177e4
LT
79
80 generic_fillattr(inode, stat);
1da177e4
LT
81 return 0;
82}
b7a6ec52
BF
83EXPORT_SYMBOL(vfs_getattr_nosec);
84
a528d35e
DH
85/*
86 * vfs_getattr - Get the enhanced basic attributes of a file
87 * @path: The file of interest
88 * @stat: Where to return the statistics
89 * @request_mask: STATX_xxx flags indicating what the caller wants
90 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
91 *
92 * Ask the filesystem for a file's attributes. The caller must indicate in
93 * request_mask and query_flags to indicate what they want.
94 *
95 * If the file is remote, the filesystem can be forced to update the attributes
96 * from the backing store by passing AT_STATX_FORCE_SYNC in query_flags or can
97 * suppress the update by passing AT_STATX_DONT_SYNC.
98 *
99 * Bits must have been set in request_mask to indicate which attributes the
100 * caller wants retrieving. Any such attribute not requested may be returned
101 * anyway, but the value may be approximate, and, if remote, may not have been
102 * synchronised with the server.
103 *
104 * 0 will be returned on success, and a -ve error code if unsuccessful.
105 */
106int vfs_getattr(const struct path *path, struct kstat *stat,
107 u32 request_mask, unsigned int query_flags)
b7a6ec52
BF
108{
109 int retval;
110
3f7036a0 111 retval = security_inode_getattr(path);
b7a6ec52
BF
112 if (retval)
113 return retval;
a528d35e 114 return vfs_getattr_nosec(path, stat, request_mask, query_flags);
b7a6ec52 115}
1da177e4
LT
116EXPORT_SYMBOL(vfs_getattr);
117
a528d35e
DH
118/**
119 * vfs_statx_fd - Get the enhanced basic attributes by file descriptor
120 * @fd: The file descriptor referring to the file of interest
121 * @stat: The result structure to fill in.
122 * @request_mask: STATX_xxx flags indicating what the caller wants
123 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
124 *
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)
1da177e4 132{
8c7493aa 133 struct fd f;
1da177e4
LT
134 int error = -EBADF;
135
8c7493aa
EB
136 if (query_flags & ~KSTAT_QUERY_FLAGS)
137 return -EINVAL;
138
139 f = fdget_raw(fd);
2903ff01 140 if (f.file) {
a528d35e
DH
141 error = vfs_getattr(&f.file->f_path, stat,
142 request_mask, query_flags);
2903ff01 143 fdput(f);
1da177e4
LT
144 }
145 return error;
146}
a528d35e 147EXPORT_SYMBOL(vfs_statx_fd);
1da177e4 148
a528d35e
DH
149/**
150 * vfs_statx - Get basic and extra attributes by filename
151 * @dfd: A file descriptor representing the base dir for a relative filename
152 * @filename: The name of the file of interest
153 * @flags: Flags to control the query
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 *
162 * The caller must have preset stat->request_mask as for vfs_getattr(). The
163 * flags are also used to load up stat->query_flags.
164 *
165 * 0 will be returned on success, and a -ve error code if unsuccessful.
166 */
167int vfs_statx(int dfd, const char __user *filename, int flags,
168 struct kstat *stat, u32 request_mask)
0112fc22 169{
2eae7a18 170 struct path path;
0112fc22 171 int error = -EINVAL;
a528d35e 172 unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
0112fc22 173
a528d35e
DH
174 if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
175 AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0)
176 return -EINVAL;
0112fc22 177
a528d35e
DH
178 if (flags & AT_SYMLINK_NOFOLLOW)
179 lookup_flags &= ~LOOKUP_FOLLOW;
180 if (flags & AT_NO_AUTOMOUNT)
181 lookup_flags &= ~LOOKUP_AUTOMOUNT;
182 if (flags & AT_EMPTY_PATH)
65cfc672 183 lookup_flags |= LOOKUP_EMPTY;
a528d35e 184
836fb7e7 185retry:
2eae7a18
CH
186 error = user_path_at(dfd, filename, lookup_flags, &path);
187 if (error)
188 goto out;
189
a528d35e 190 error = vfs_getattr(&path, stat, request_mask, flags);
2eae7a18 191 path_put(&path);
836fb7e7
JL
192 if (retry_estale(error, lookup_flags)) {
193 lookup_flags |= LOOKUP_REVAL;
194 goto retry;
195 }
0112fc22
OD
196out:
197 return error;
198}
a528d35e 199EXPORT_SYMBOL(vfs_statx);
2eae7a18 200
0112fc22 201
1da177e4
LT
202#ifdef __ARCH_WANT_OLD_STAT
203
204/*
205 * For backward compatibility? Maybe this should be moved
206 * into arch/i386 instead?
207 */
208static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
209{
210 static int warncount = 5;
211 struct __old_kernel_stat tmp;
a528d35e 212
1da177e4
LT
213 if (warncount > 0) {
214 warncount--;
215 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
216 current->comm);
217 } else if (warncount < 0) {
218 /* it's laughable, but... */
219 warncount = 0;
220 }
221
222 memset(&tmp, 0, sizeof(struct __old_kernel_stat));
223 tmp.st_dev = old_encode_dev(stat->dev);
224 tmp.st_ino = stat->ino;
afefdbb2
DH
225 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
226 return -EOVERFLOW;
1da177e4
LT
227 tmp.st_mode = stat->mode;
228 tmp.st_nlink = stat->nlink;
229 if (tmp.st_nlink != stat->nlink)
230 return -EOVERFLOW;
a7c1938e
EB
231 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
232 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
1da177e4
LT
233 tmp.st_rdev = old_encode_dev(stat->rdev);
234#if BITS_PER_LONG == 32
235 if (stat->size > MAX_NON_LFS)
236 return -EOVERFLOW;
a528d35e 237#endif
1da177e4
LT
238 tmp.st_size = stat->size;
239 tmp.st_atime = stat->atime.tv_sec;
240 tmp.st_mtime = stat->mtime.tv_sec;
241 tmp.st_ctime = stat->ctime.tv_sec;
242 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
243}
244
c7887325
DH
245SYSCALL_DEFINE2(stat, const char __user *, filename,
246 struct __old_kernel_stat __user *, statbuf)
1da177e4
LT
247{
248 struct kstat stat;
2eae7a18 249 int error;
1da177e4 250
2eae7a18
CH
251 error = vfs_stat(filename, &stat);
252 if (error)
253 return error;
1da177e4 254
2eae7a18 255 return cp_old_stat(&stat, statbuf);
1da177e4 256}
257ac264 257
c7887325
DH
258SYSCALL_DEFINE2(lstat, const char __user *, filename,
259 struct __old_kernel_stat __user *, statbuf)
1da177e4
LT
260{
261 struct kstat stat;
2eae7a18 262 int error;
1da177e4 263
2eae7a18
CH
264 error = vfs_lstat(filename, &stat);
265 if (error)
266 return error;
1da177e4 267
2eae7a18 268 return cp_old_stat(&stat, statbuf);
1da177e4 269}
257ac264
HC
270
271SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
1da177e4
LT
272{
273 struct kstat stat;
274 int error = vfs_fstat(fd, &stat);
275
276 if (!error)
277 error = cp_old_stat(&stat, statbuf);
278
279 return error;
280}
281
282#endif /* __ARCH_WANT_OLD_STAT */
283
a52dd971
LT
284#if BITS_PER_LONG == 32
285# define choose_32_64(a,b) a
286#else
287# define choose_32_64(a,b) b
288#endif
289
4c416f42 290#define valid_dev(x) choose_32_64(old_valid_dev(x),true)
a52dd971
LT
291#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
292
8529f613
LT
293#ifndef INIT_STRUCT_STAT_PADDING
294# define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
295#endif
296
1da177e4
LT
297static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
298{
299 struct stat tmp;
300
a52dd971 301 if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
1da177e4 302 return -EOVERFLOW;
a52dd971
LT
303#if BITS_PER_LONG == 32
304 if (stat->size > MAX_NON_LFS)
1da177e4
LT
305 return -EOVERFLOW;
306#endif
307
8529f613 308 INIT_STRUCT_STAT_PADDING(tmp);
a52dd971 309 tmp.st_dev = encode_dev(stat->dev);
1da177e4 310 tmp.st_ino = stat->ino;
afefdbb2
DH
311 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
312 return -EOVERFLOW;
1da177e4
LT
313 tmp.st_mode = stat->mode;
314 tmp.st_nlink = stat->nlink;
315 if (tmp.st_nlink != stat->nlink)
316 return -EOVERFLOW;
a7c1938e
EB
317 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
318 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
a52dd971 319 tmp.st_rdev = encode_dev(stat->rdev);
1da177e4
LT
320 tmp.st_size = stat->size;
321 tmp.st_atime = stat->atime.tv_sec;
322 tmp.st_mtime = stat->mtime.tv_sec;
323 tmp.st_ctime = stat->ctime.tv_sec;
324#ifdef STAT_HAVE_NSEC
325 tmp.st_atime_nsec = stat->atime.tv_nsec;
326 tmp.st_mtime_nsec = stat->mtime.tv_nsec;
327 tmp.st_ctime_nsec = stat->ctime.tv_nsec;
328#endif
329 tmp.st_blocks = stat->blocks;
330 tmp.st_blksize = stat->blksize;
331 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
332}
333
c7887325
DH
334SYSCALL_DEFINE2(newstat, const char __user *, filename,
335 struct stat __user *, statbuf)
5590ff0d
UD
336{
337 struct kstat stat;
2eae7a18 338 int error = vfs_stat(filename, &stat);
5590ff0d 339
2eae7a18
CH
340 if (error)
341 return error;
342 return cp_new_stat(&stat, statbuf);
5590ff0d
UD
343}
344
c7887325
DH
345SYSCALL_DEFINE2(newlstat, const char __user *, filename,
346 struct stat __user *, statbuf)
1da177e4
LT
347{
348 struct kstat stat;
2eae7a18 349 int error;
1da177e4 350
2eae7a18
CH
351 error = vfs_lstat(filename, &stat);
352 if (error)
353 return error;
1da177e4 354
2eae7a18 355 return cp_new_stat(&stat, statbuf);
1da177e4 356}
5590ff0d 357
2833c28a 358#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
c7887325 359SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
6559eed8 360 struct stat __user *, statbuf, int, flag)
1da177e4
LT
361{
362 struct kstat stat;
0112fc22 363 int error;
1da177e4 364
0112fc22
OD
365 error = vfs_fstatat(dfd, filename, &stat, flag);
366 if (error)
367 return error;
368 return cp_new_stat(&stat, statbuf);
1da177e4 369}
cff2b760 370#endif
5590ff0d 371
257ac264 372SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
1da177e4
LT
373{
374 struct kstat stat;
375 int error = vfs_fstat(fd, &stat);
376
377 if (!error)
378 error = cp_new_stat(&stat, statbuf);
379
380 return error;
381}
382
6559eed8
HC
383SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
384 char __user *, buf, int, bufsiz)
1da177e4 385{
2d8f3038 386 struct path path;
1da177e4 387 int error;
1fa1e7f6 388 int empty = 0;
7955119e 389 unsigned int lookup_flags = LOOKUP_EMPTY;
1da177e4
LT
390
391 if (bufsiz <= 0)
392 return -EINVAL;
393
7955119e
JL
394retry:
395 error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty);
1da177e4 396 if (!error) {
bb668734 397 struct inode *inode = d_backing_inode(path.dentry);
1da177e4 398
1fa1e7f6 399 error = empty ? -ENOENT : -EINVAL;
fd4a0edf
MS
400 /*
401 * AFS mountpoints allow readlink(2) but are not symlinks
402 */
403 if (d_is_symlink(path.dentry) || inode->i_op->readlink) {
2d8f3038 404 error = security_inode_readlink(path.dentry);
1da177e4 405 if (!error) {
68ac1234 406 touch_atime(&path);
fd4a0edf 407 error = vfs_readlink(path.dentry, buf, bufsiz);
1da177e4
LT
408 }
409 }
2d8f3038 410 path_put(&path);
7955119e
JL
411 if (retry_estale(error, lookup_flags)) {
412 lookup_flags |= LOOKUP_REVAL;
413 goto retry;
414 }
1da177e4
LT
415 }
416 return error;
417}
418
002c8976
HC
419SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
420 int, bufsiz)
5590ff0d
UD
421{
422 return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
423}
424
1da177e4
LT
425
426/* ---------- LFS-64 ----------- */
0753f70f 427#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
1da177e4 428
8529f613
LT
429#ifndef INIT_STRUCT_STAT64_PADDING
430# define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st))
431#endif
432
1da177e4
LT
433static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
434{
435 struct stat64 tmp;
436
8529f613 437 INIT_STRUCT_STAT64_PADDING(tmp);
1da177e4
LT
438#ifdef CONFIG_MIPS
439 /* mips has weird padding, so we don't get 64 bits there */
1da177e4
LT
440 tmp.st_dev = new_encode_dev(stat->dev);
441 tmp.st_rdev = new_encode_dev(stat->rdev);
442#else
443 tmp.st_dev = huge_encode_dev(stat->dev);
444 tmp.st_rdev = huge_encode_dev(stat->rdev);
445#endif
446 tmp.st_ino = stat->ino;
afefdbb2
DH
447 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
448 return -EOVERFLOW;
1da177e4
LT
449#ifdef STAT64_HAS_BROKEN_ST_INO
450 tmp.__st_ino = stat->ino;
451#endif
452 tmp.st_mode = stat->mode;
453 tmp.st_nlink = stat->nlink;
a7c1938e
EB
454 tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
455 tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
1da177e4
LT
456 tmp.st_atime = stat->atime.tv_sec;
457 tmp.st_atime_nsec = stat->atime.tv_nsec;
458 tmp.st_mtime = stat->mtime.tv_sec;
459 tmp.st_mtime_nsec = stat->mtime.tv_nsec;
460 tmp.st_ctime = stat->ctime.tv_sec;
461 tmp.st_ctime_nsec = stat->ctime.tv_nsec;
462 tmp.st_size = stat->size;
463 tmp.st_blocks = stat->blocks;
464 tmp.st_blksize = stat->blksize;
465 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
466}
467
c7887325
DH
468SYSCALL_DEFINE2(stat64, const char __user *, filename,
469 struct stat64 __user *, statbuf)
1da177e4
LT
470{
471 struct kstat stat;
472 int error = vfs_stat(filename, &stat);
473
474 if (!error)
475 error = cp_new_stat64(&stat, statbuf);
476
477 return error;
478}
257ac264 479
c7887325
DH
480SYSCALL_DEFINE2(lstat64, const char __user *, filename,
481 struct stat64 __user *, statbuf)
1da177e4
LT
482{
483 struct kstat stat;
484 int error = vfs_lstat(filename, &stat);
485
486 if (!error)
487 error = cp_new_stat64(&stat, statbuf);
488
489 return error;
490}
257ac264
HC
491
492SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
1da177e4
LT
493{
494 struct kstat stat;
495 int error = vfs_fstat(fd, &stat);
496
497 if (!error)
498 error = cp_new_stat64(&stat, statbuf);
499
500 return error;
501}
502
c7887325 503SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
6559eed8 504 struct stat64 __user *, statbuf, int, flag)
cff2b760
UD
505{
506 struct kstat stat;
0112fc22 507 int error;
cff2b760 508
0112fc22
OD
509 error = vfs_fstatat(dfd, filename, &stat, flag);
510 if (error)
511 return error;
512 return cp_new_stat64(&stat, statbuf);
cff2b760 513}
0753f70f 514#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
1da177e4 515
a528d35e
DH
516static inline int __put_timestamp(struct timespec *kts,
517 struct statx_timestamp __user *uts)
518{
519 return (__put_user(kts->tv_sec, &uts->tv_sec ) ||
520 __put_user(kts->tv_nsec, &uts->tv_nsec ) ||
521 __put_user(0, &uts->__reserved ));
522}
523
524/*
525 * Set the statx results.
526 */
527static long statx_set_result(struct kstat *stat, struct statx __user *buffer)
528{
529 uid_t uid = from_kuid_munged(current_user_ns(), stat->uid);
530 gid_t gid = from_kgid_munged(current_user_ns(), stat->gid);
531
532 if (__put_user(stat->result_mask, &buffer->stx_mask ) ||
533 __put_user(stat->mode, &buffer->stx_mode ) ||
534 __clear_user(&buffer->__spare0, sizeof(buffer->__spare0)) ||
535 __put_user(stat->nlink, &buffer->stx_nlink ) ||
536 __put_user(uid, &buffer->stx_uid ) ||
537 __put_user(gid, &buffer->stx_gid ) ||
538 __put_user(stat->attributes, &buffer->stx_attributes ) ||
539 __put_user(stat->blksize, &buffer->stx_blksize ) ||
540 __put_user(MAJOR(stat->rdev), &buffer->stx_rdev_major ) ||
541 __put_user(MINOR(stat->rdev), &buffer->stx_rdev_minor ) ||
542 __put_user(MAJOR(stat->dev), &buffer->stx_dev_major ) ||
543 __put_user(MINOR(stat->dev), &buffer->stx_dev_minor ) ||
544 __put_timestamp(&stat->atime, &buffer->stx_atime ) ||
545 __put_timestamp(&stat->btime, &buffer->stx_btime ) ||
546 __put_timestamp(&stat->ctime, &buffer->stx_ctime ) ||
547 __put_timestamp(&stat->mtime, &buffer->stx_mtime ) ||
548 __put_user(stat->ino, &buffer->stx_ino ) ||
549 __put_user(stat->size, &buffer->stx_size ) ||
550 __put_user(stat->blocks, &buffer->stx_blocks ) ||
551 __clear_user(&buffer->__spare1, sizeof(buffer->__spare1)) ||
552 __clear_user(&buffer->__spare2, sizeof(buffer->__spare2)))
553 return -EFAULT;
554
555 return 0;
556}
557
558/**
559 * sys_statx - System call to get enhanced stats
560 * @dfd: Base directory to pathwalk from *or* fd to stat.
561 * @filename: File to stat *or* NULL.
562 * @flags: AT_* flags to control pathwalk.
563 * @mask: Parts of statx struct actually required.
564 * @buffer: Result buffer.
565 *
566 * Note that if filename is NULL, then it does the equivalent of fstat() using
567 * dfd to indicate the file of interest.
568 */
569SYSCALL_DEFINE5(statx,
570 int, dfd, const char __user *, filename, unsigned, flags,
571 unsigned int, mask,
572 struct statx __user *, buffer)
573{
574 struct kstat stat;
575 int error;
576
577 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
578 return -EINVAL;
579 if (!access_ok(VERIFY_WRITE, buffer, sizeof(*buffer)))
580 return -EFAULT;
581
582 if (filename)
583 error = vfs_statx(dfd, filename, flags, &stat, mask);
584 else
585 error = vfs_statx_fd(dfd, &stat, mask, flags);
586 if (error)
587 return error;
588 return statx_set_result(&stat, buffer);
589}
590
b462707e
DM
591/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
592void __inode_add_bytes(struct inode *inode, loff_t bytes)
1da177e4 593{
1da177e4
LT
594 inode->i_blocks += bytes >> 9;
595 bytes &= 511;
596 inode->i_bytes += bytes;
597 if (inode->i_bytes >= 512) {
598 inode->i_blocks++;
599 inode->i_bytes -= 512;
600 }
b462707e
DM
601}
602
603void inode_add_bytes(struct inode *inode, loff_t bytes)
604{
605 spin_lock(&inode->i_lock);
606 __inode_add_bytes(inode, bytes);
1da177e4
LT
607 spin_unlock(&inode->i_lock);
608}
609
610EXPORT_SYMBOL(inode_add_bytes);
611
1c8924eb 612void __inode_sub_bytes(struct inode *inode, loff_t bytes)
1da177e4 613{
1da177e4
LT
614 inode->i_blocks -= bytes >> 9;
615 bytes &= 511;
616 if (inode->i_bytes < bytes) {
617 inode->i_blocks--;
618 inode->i_bytes += 512;
619 }
620 inode->i_bytes -= bytes;
1c8924eb
JK
621}
622
623EXPORT_SYMBOL(__inode_sub_bytes);
624
625void inode_sub_bytes(struct inode *inode, loff_t bytes)
626{
627 spin_lock(&inode->i_lock);
628 __inode_sub_bytes(inode, bytes);
1da177e4
LT
629 spin_unlock(&inode->i_lock);
630}
631
632EXPORT_SYMBOL(inode_sub_bytes);
633
634loff_t inode_get_bytes(struct inode *inode)
635{
636 loff_t ret;
637
638 spin_lock(&inode->i_lock);
639 ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
640 spin_unlock(&inode->i_lock);
641 return ret;
642}
643
644EXPORT_SYMBOL(inode_get_bytes);
645
646void inode_set_bytes(struct inode *inode, loff_t bytes)
647{
648 /* Caller is here responsible for sufficient locking
649 * (ie. inode->i_lock) */
650 inode->i_blocks = bytes >> 9;
651 inode->i_bytes = bytes & 511;
652}
653
654EXPORT_SYMBOL(inode_set_bytes);