18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/syscalls.h>
38c2ecf20Sopenharmony_ci#include <linux/export.h>
48c2ecf20Sopenharmony_ci#include <linux/fs.h>
58c2ecf20Sopenharmony_ci#include <linux/file.h>
68c2ecf20Sopenharmony_ci#include <linux/mount.h>
78c2ecf20Sopenharmony_ci#include <linux/namei.h>
88c2ecf20Sopenharmony_ci#include <linux/statfs.h>
98c2ecf20Sopenharmony_ci#include <linux/security.h>
108c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
118c2ecf20Sopenharmony_ci#include <linux/compat.h>
128c2ecf20Sopenharmony_ci#include "internal.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic int flags_by_mnt(int mnt_flags)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	int flags = 0;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_READONLY)
198c2ecf20Sopenharmony_ci		flags |= ST_RDONLY;
208c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_NOSUID)
218c2ecf20Sopenharmony_ci		flags |= ST_NOSUID;
228c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_NODEV)
238c2ecf20Sopenharmony_ci		flags |= ST_NODEV;
248c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_NOEXEC)
258c2ecf20Sopenharmony_ci		flags |= ST_NOEXEC;
268c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_NOATIME)
278c2ecf20Sopenharmony_ci		flags |= ST_NOATIME;
288c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_NODIRATIME)
298c2ecf20Sopenharmony_ci		flags |= ST_NODIRATIME;
308c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_RELATIME)
318c2ecf20Sopenharmony_ci		flags |= ST_RELATIME;
328c2ecf20Sopenharmony_ci	if (mnt_flags & MNT_NOSYMFOLLOW)
338c2ecf20Sopenharmony_ci		flags |= ST_NOSYMFOLLOW;
348c2ecf20Sopenharmony_ci	return flags;
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic int flags_by_sb(int s_flags)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	int flags = 0;
408c2ecf20Sopenharmony_ci	if (s_flags & SB_SYNCHRONOUS)
418c2ecf20Sopenharmony_ci		flags |= ST_SYNCHRONOUS;
428c2ecf20Sopenharmony_ci	if (s_flags & SB_MANDLOCK)
438c2ecf20Sopenharmony_ci		flags |= ST_MANDLOCK;
448c2ecf20Sopenharmony_ci	if (s_flags & SB_RDONLY)
458c2ecf20Sopenharmony_ci		flags |= ST_RDONLY;
468c2ecf20Sopenharmony_ci	return flags;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic int calculate_f_flags(struct vfsmount *mnt)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
528c2ecf20Sopenharmony_ci		flags_by_sb(mnt->mnt_sb->s_flags);
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	int retval;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	if (!dentry->d_sb->s_op->statfs)
608c2ecf20Sopenharmony_ci		return -ENOSYS;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	memset(buf, 0, sizeof(*buf));
638c2ecf20Sopenharmony_ci	retval = security_sb_statfs(dentry);
648c2ecf20Sopenharmony_ci	if (retval)
658c2ecf20Sopenharmony_ci		return retval;
668c2ecf20Sopenharmony_ci	retval = dentry->d_sb->s_op->statfs(dentry, buf);
678c2ecf20Sopenharmony_ci	if (retval == 0 && buf->f_frsize == 0)
688c2ecf20Sopenharmony_ci		buf->f_frsize = buf->f_bsize;
698c2ecf20Sopenharmony_ci	return retval;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ciint vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct kstatfs st;
758c2ecf20Sopenharmony_ci	int error;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	error = statfs_by_dentry(dentry, &st);
788c2ecf20Sopenharmony_ci	if (error)
798c2ecf20Sopenharmony_ci		return error;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	*fsid = st.f_fsid;
828c2ecf20Sopenharmony_ci	return 0;
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vfs_get_fsid);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ciint vfs_statfs(const struct path *path, struct kstatfs *buf)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	int error;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	error = statfs_by_dentry(path->dentry, buf);
918c2ecf20Sopenharmony_ci	if (!error)
928c2ecf20Sopenharmony_ci		buf->f_flags = calculate_f_flags(path->mnt);
938c2ecf20Sopenharmony_ci	return error;
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vfs_statfs);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciint user_statfs(const char __user *pathname, struct kstatfs *st)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	struct path path;
1008c2ecf20Sopenharmony_ci	int error;
1018c2ecf20Sopenharmony_ci	unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
1028c2ecf20Sopenharmony_ciretry:
1038c2ecf20Sopenharmony_ci	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1048c2ecf20Sopenharmony_ci	if (!error) {
1058c2ecf20Sopenharmony_ci		error = vfs_statfs(&path, st);
1068c2ecf20Sopenharmony_ci		path_put(&path);
1078c2ecf20Sopenharmony_ci		if (retry_estale(error, lookup_flags)) {
1088c2ecf20Sopenharmony_ci			lookup_flags |= LOOKUP_REVAL;
1098c2ecf20Sopenharmony_ci			goto retry;
1108c2ecf20Sopenharmony_ci		}
1118c2ecf20Sopenharmony_ci	}
1128c2ecf20Sopenharmony_ci	return error;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciint fd_statfs(int fd, struct kstatfs *st)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct fd f = fdget_raw(fd);
1188c2ecf20Sopenharmony_ci	int error = -EBADF;
1198c2ecf20Sopenharmony_ci	if (f.file) {
1208c2ecf20Sopenharmony_ci		error = vfs_statfs(&f.file->f_path, st);
1218c2ecf20Sopenharmony_ci		fdput(f);
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci	return error;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct statfs buf;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	if (sizeof(buf) == sizeof(*st))
1318c2ecf20Sopenharmony_ci		memcpy(&buf, st, sizeof(*st));
1328c2ecf20Sopenharmony_ci	else {
1338c2ecf20Sopenharmony_ci		memset(&buf, 0, sizeof(buf));
1348c2ecf20Sopenharmony_ci		if (sizeof buf.f_blocks == 4) {
1358c2ecf20Sopenharmony_ci			if ((st->f_blocks | st->f_bfree | st->f_bavail |
1368c2ecf20Sopenharmony_ci			     st->f_bsize | st->f_frsize) &
1378c2ecf20Sopenharmony_ci			    0xffffffff00000000ULL)
1388c2ecf20Sopenharmony_ci				return -EOVERFLOW;
1398c2ecf20Sopenharmony_ci			/*
1408c2ecf20Sopenharmony_ci			 * f_files and f_ffree may be -1; it's okay to stuff
1418c2ecf20Sopenharmony_ci			 * that into 32 bits
1428c2ecf20Sopenharmony_ci			 */
1438c2ecf20Sopenharmony_ci			if (st->f_files != -1 &&
1448c2ecf20Sopenharmony_ci			    (st->f_files & 0xffffffff00000000ULL))
1458c2ecf20Sopenharmony_ci				return -EOVERFLOW;
1468c2ecf20Sopenharmony_ci			if (st->f_ffree != -1 &&
1478c2ecf20Sopenharmony_ci			    (st->f_ffree & 0xffffffff00000000ULL))
1488c2ecf20Sopenharmony_ci				return -EOVERFLOW;
1498c2ecf20Sopenharmony_ci		}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci		buf.f_type = st->f_type;
1528c2ecf20Sopenharmony_ci		buf.f_bsize = st->f_bsize;
1538c2ecf20Sopenharmony_ci		buf.f_blocks = st->f_blocks;
1548c2ecf20Sopenharmony_ci		buf.f_bfree = st->f_bfree;
1558c2ecf20Sopenharmony_ci		buf.f_bavail = st->f_bavail;
1568c2ecf20Sopenharmony_ci		buf.f_files = st->f_files;
1578c2ecf20Sopenharmony_ci		buf.f_ffree = st->f_ffree;
1588c2ecf20Sopenharmony_ci		buf.f_fsid = st->f_fsid;
1598c2ecf20Sopenharmony_ci		buf.f_namelen = st->f_namelen;
1608c2ecf20Sopenharmony_ci		buf.f_frsize = st->f_frsize;
1618c2ecf20Sopenharmony_ci		buf.f_flags = st->f_flags;
1628c2ecf20Sopenharmony_ci	}
1638c2ecf20Sopenharmony_ci	if (copy_to_user(p, &buf, sizeof(buf)))
1648c2ecf20Sopenharmony_ci		return -EFAULT;
1658c2ecf20Sopenharmony_ci	return 0;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	struct statfs64 buf;
1718c2ecf20Sopenharmony_ci	if (sizeof(buf) == sizeof(*st))
1728c2ecf20Sopenharmony_ci		memcpy(&buf, st, sizeof(*st));
1738c2ecf20Sopenharmony_ci	else {
1748c2ecf20Sopenharmony_ci		memset(&buf, 0, sizeof(buf));
1758c2ecf20Sopenharmony_ci		buf.f_type = st->f_type;
1768c2ecf20Sopenharmony_ci		buf.f_bsize = st->f_bsize;
1778c2ecf20Sopenharmony_ci		buf.f_blocks = st->f_blocks;
1788c2ecf20Sopenharmony_ci		buf.f_bfree = st->f_bfree;
1798c2ecf20Sopenharmony_ci		buf.f_bavail = st->f_bavail;
1808c2ecf20Sopenharmony_ci		buf.f_files = st->f_files;
1818c2ecf20Sopenharmony_ci		buf.f_ffree = st->f_ffree;
1828c2ecf20Sopenharmony_ci		buf.f_fsid = st->f_fsid;
1838c2ecf20Sopenharmony_ci		buf.f_namelen = st->f_namelen;
1848c2ecf20Sopenharmony_ci		buf.f_frsize = st->f_frsize;
1858c2ecf20Sopenharmony_ci		buf.f_flags = st->f_flags;
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci	if (copy_to_user(p, &buf, sizeof(buf)))
1888c2ecf20Sopenharmony_ci		return -EFAULT;
1898c2ecf20Sopenharmony_ci	return 0;
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct kstatfs st;
1958c2ecf20Sopenharmony_ci	int error = user_statfs(pathname, &st);
1968c2ecf20Sopenharmony_ci	if (!error)
1978c2ecf20Sopenharmony_ci		error = do_statfs_native(&st, buf);
1988c2ecf20Sopenharmony_ci	return error;
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	struct kstatfs st;
2048c2ecf20Sopenharmony_ci	int error;
2058c2ecf20Sopenharmony_ci	if (sz != sizeof(*buf))
2068c2ecf20Sopenharmony_ci		return -EINVAL;
2078c2ecf20Sopenharmony_ci	error = user_statfs(pathname, &st);
2088c2ecf20Sopenharmony_ci	if (!error)
2098c2ecf20Sopenharmony_ci		error = do_statfs64(&st, buf);
2108c2ecf20Sopenharmony_ci	return error;
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	struct kstatfs st;
2168c2ecf20Sopenharmony_ci	int error = fd_statfs(fd, &st);
2178c2ecf20Sopenharmony_ci	if (!error)
2188c2ecf20Sopenharmony_ci		error = do_statfs_native(&st, buf);
2198c2ecf20Sopenharmony_ci	return error;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct kstatfs st;
2258c2ecf20Sopenharmony_ci	int error;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (sz != sizeof(*buf))
2288c2ecf20Sopenharmony_ci		return -EINVAL;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	error = fd_statfs(fd, &st);
2318c2ecf20Sopenharmony_ci	if (!error)
2328c2ecf20Sopenharmony_ci		error = do_statfs64(&st, buf);
2338c2ecf20Sopenharmony_ci	return error;
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct super_block *s = user_get_super(dev);
2398c2ecf20Sopenharmony_ci	int err;
2408c2ecf20Sopenharmony_ci	if (!s)
2418c2ecf20Sopenharmony_ci		return -EINVAL;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	err = statfs_by_dentry(s->s_root, sbuf);
2448c2ecf20Sopenharmony_ci	drop_super(s);
2458c2ecf20Sopenharmony_ci	return err;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	struct ustat tmp;
2518c2ecf20Sopenharmony_ci	struct kstatfs sbuf;
2528c2ecf20Sopenharmony_ci	int err = vfs_ustat(new_decode_dev(dev), &sbuf);
2538c2ecf20Sopenharmony_ci	if (err)
2548c2ecf20Sopenharmony_ci		return err;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	memset(&tmp,0,sizeof(struct ustat));
2578c2ecf20Sopenharmony_ci	tmp.f_tfree = sbuf.f_bfree;
2588c2ecf20Sopenharmony_ci	tmp.f_tinode = sbuf.f_ffree;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
2648c2ecf20Sopenharmony_cistatic int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	struct compat_statfs buf;
2678c2ecf20Sopenharmony_ci	if (sizeof ubuf->f_blocks == 4) {
2688c2ecf20Sopenharmony_ci		if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
2698c2ecf20Sopenharmony_ci		     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
2708c2ecf20Sopenharmony_ci			return -EOVERFLOW;
2718c2ecf20Sopenharmony_ci		/* f_files and f_ffree may be -1; it's okay
2728c2ecf20Sopenharmony_ci		 * to stuff that into 32 bits */
2738c2ecf20Sopenharmony_ci		if (kbuf->f_files != 0xffffffffffffffffULL
2748c2ecf20Sopenharmony_ci		 && (kbuf->f_files & 0xffffffff00000000ULL))
2758c2ecf20Sopenharmony_ci			return -EOVERFLOW;
2768c2ecf20Sopenharmony_ci		if (kbuf->f_ffree != 0xffffffffffffffffULL
2778c2ecf20Sopenharmony_ci		 && (kbuf->f_ffree & 0xffffffff00000000ULL))
2788c2ecf20Sopenharmony_ci			return -EOVERFLOW;
2798c2ecf20Sopenharmony_ci	}
2808c2ecf20Sopenharmony_ci	memset(&buf, 0, sizeof(struct compat_statfs));
2818c2ecf20Sopenharmony_ci	buf.f_type = kbuf->f_type;
2828c2ecf20Sopenharmony_ci	buf.f_bsize = kbuf->f_bsize;
2838c2ecf20Sopenharmony_ci	buf.f_blocks = kbuf->f_blocks;
2848c2ecf20Sopenharmony_ci	buf.f_bfree = kbuf->f_bfree;
2858c2ecf20Sopenharmony_ci	buf.f_bavail = kbuf->f_bavail;
2868c2ecf20Sopenharmony_ci	buf.f_files = kbuf->f_files;
2878c2ecf20Sopenharmony_ci	buf.f_ffree = kbuf->f_ffree;
2888c2ecf20Sopenharmony_ci	buf.f_namelen = kbuf->f_namelen;
2898c2ecf20Sopenharmony_ci	buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
2908c2ecf20Sopenharmony_ci	buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
2918c2ecf20Sopenharmony_ci	buf.f_frsize = kbuf->f_frsize;
2928c2ecf20Sopenharmony_ci	buf.f_flags = kbuf->f_flags;
2938c2ecf20Sopenharmony_ci	if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs)))
2948c2ecf20Sopenharmony_ci		return -EFAULT;
2958c2ecf20Sopenharmony_ci	return 0;
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci/*
2998c2ecf20Sopenharmony_ci * The following statfs calls are copies of code from fs/statfs.c and
3008c2ecf20Sopenharmony_ci * should be checked against those from time to time
3018c2ecf20Sopenharmony_ci */
3028c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	struct kstatfs tmp;
3058c2ecf20Sopenharmony_ci	int error = user_statfs(pathname, &tmp);
3068c2ecf20Sopenharmony_ci	if (!error)
3078c2ecf20Sopenharmony_ci		error = put_compat_statfs(buf, &tmp);
3088c2ecf20Sopenharmony_ci	return error;
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	struct kstatfs tmp;
3148c2ecf20Sopenharmony_ci	int error = fd_statfs(fd, &tmp);
3158c2ecf20Sopenharmony_ci	if (!error)
3168c2ecf20Sopenharmony_ci		error = put_compat_statfs(buf, &tmp);
3178c2ecf20Sopenharmony_ci	return error;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	struct compat_statfs64 buf;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
3258c2ecf20Sopenharmony_ci		return -EOVERFLOW;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	memset(&buf, 0, sizeof(struct compat_statfs64));
3288c2ecf20Sopenharmony_ci	buf.f_type = kbuf->f_type;
3298c2ecf20Sopenharmony_ci	buf.f_bsize = kbuf->f_bsize;
3308c2ecf20Sopenharmony_ci	buf.f_blocks = kbuf->f_blocks;
3318c2ecf20Sopenharmony_ci	buf.f_bfree = kbuf->f_bfree;
3328c2ecf20Sopenharmony_ci	buf.f_bavail = kbuf->f_bavail;
3338c2ecf20Sopenharmony_ci	buf.f_files = kbuf->f_files;
3348c2ecf20Sopenharmony_ci	buf.f_ffree = kbuf->f_ffree;
3358c2ecf20Sopenharmony_ci	buf.f_namelen = kbuf->f_namelen;
3368c2ecf20Sopenharmony_ci	buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
3378c2ecf20Sopenharmony_ci	buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
3388c2ecf20Sopenharmony_ci	buf.f_frsize = kbuf->f_frsize;
3398c2ecf20Sopenharmony_ci	buf.f_flags = kbuf->f_flags;
3408c2ecf20Sopenharmony_ci	if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64)))
3418c2ecf20Sopenharmony_ci		return -EFAULT;
3428c2ecf20Sopenharmony_ci	return 0;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ciint kcompat_sys_statfs64(const char __user * pathname, compat_size_t sz, struct compat_statfs64 __user * buf)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	struct kstatfs tmp;
3488c2ecf20Sopenharmony_ci	int error;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	if (sz != sizeof(*buf))
3518c2ecf20Sopenharmony_ci		return -EINVAL;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	error = user_statfs(pathname, &tmp);
3548c2ecf20Sopenharmony_ci	if (!error)
3558c2ecf20Sopenharmony_ci		error = put_compat_statfs64(buf, &tmp);
3568c2ecf20Sopenharmony_ci	return error;
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	return kcompat_sys_statfs64(pathname, sz, buf);
3628c2ecf20Sopenharmony_ci}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ciint kcompat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user * buf)
3658c2ecf20Sopenharmony_ci{
3668c2ecf20Sopenharmony_ci	struct kstatfs tmp;
3678c2ecf20Sopenharmony_ci	int error;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	if (sz != sizeof(*buf))
3708c2ecf20Sopenharmony_ci		return -EINVAL;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	error = fd_statfs(fd, &tmp);
3738c2ecf20Sopenharmony_ci	if (!error)
3748c2ecf20Sopenharmony_ci		error = put_compat_statfs64(buf, &tmp);
3758c2ecf20Sopenharmony_ci	return error;
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	return kcompat_sys_fstatfs64(fd, sz, buf);
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci/*
3848c2ecf20Sopenharmony_ci * This is a copy of sys_ustat, just dealing with a structure layout.
3858c2ecf20Sopenharmony_ci * Given how simple this syscall is that apporach is more maintainable
3868c2ecf20Sopenharmony_ci * than the various conversion hacks.
3878c2ecf20Sopenharmony_ci */
3888c2ecf20Sopenharmony_ciCOMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	struct compat_ustat tmp;
3918c2ecf20Sopenharmony_ci	struct kstatfs sbuf;
3928c2ecf20Sopenharmony_ci	int err = vfs_ustat(new_decode_dev(dev), &sbuf);
3938c2ecf20Sopenharmony_ci	if (err)
3948c2ecf20Sopenharmony_ci		return err;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	memset(&tmp, 0, sizeof(struct compat_ustat));
3978c2ecf20Sopenharmony_ci	tmp.f_tfree = sbuf.f_bfree;
3988c2ecf20Sopenharmony_ci	tmp.f_tinode = sbuf.f_ffree;
3998c2ecf20Sopenharmony_ci	if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
4008c2ecf20Sopenharmony_ci		return -EFAULT;
4018c2ecf20Sopenharmony_ci	return 0;
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci#endif
404