From: Andi Kleen <ak@suse.de>

Add compat_* functions for statfs64. The 32bit layout unfortunately
does not match x86-64.

Only generic code.



 fs/compat.c            |   58 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/compat.h |   14 +++++++++++
 2 files changed, 72 insertions(+)

diff -puN fs/compat.c~compat-statfs64 fs/compat.c
--- 25/fs/compat.c~compat-statfs64	2003-08-10 14:39:41.000000000 -0700
+++ 25-akpm/fs/compat.c	2003-08-10 14:39:41.000000000 -0700
@@ -150,6 +150,64 @@ out:
 	return error;
 }
 
+static int put_compat_statfs64(struct compat_statfs64 *ubuf, struct kstatfs *kbuf)
+{
+
+	if (sizeof ubuf->f_blocks == 4) {
+		if ((kbuf->f_blocks | kbuf->f_bfree |
+		     kbuf->f_bavail | kbuf->f_files | kbuf->f_ffree) &
+		    0xffffffff00000000ULL)
+			return -EOVERFLOW;
+	}
+	if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
+	    __put_user(kbuf->f_type, &ubuf->f_type) ||
+	    __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
+	    __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
+	    __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
+	    __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
+	    __put_user(kbuf->f_files, &ubuf->f_files) ||
+	    __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
+	    __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
+	    __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
+	    __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
+	    __put_user(kbuf->f_frsize, &ubuf->f_frsize))
+		return -EFAULT;
+	return 0;
+}
+
+asmlinkage long compat_statfs64(const char *path, struct compat_statfs64 *buf)
+{
+	struct nameidata nd;
+	int error;
+
+	error = user_path_walk(path, &nd);
+	if (!error) {
+		struct kstatfs tmp;
+		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
+		if (!error && put_compat_statfs64(buf, &tmp))
+			error = -EFAULT;
+		path_release(&nd);
+	}
+	return error;
+}
+
+asmlinkage long compat_fstatfs64(unsigned int fd, struct compat_statfs64 *buf)
+{
+	struct file * file;
+	struct kstatfs tmp;
+	int error;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+	if (!error && put_compat_statfs64(buf, &tmp))
+		error = -EFAULT;
+	fput(file);
+out:
+	return error;
+}
 
 /* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64 */
 
diff -puN include/linux/compat.h~compat-statfs64 include/linux/compat.h
--- 25/include/linux/compat.h~compat-statfs64	2003-08-10 14:39:41.000000000 -0700
+++ 25-akpm/include/linux/compat.h	2003-08-10 14:39:41.000000000 -0700
@@ -71,5 +71,19 @@ struct compat_rusage {
 	compat_long_t	ru_nivcsw;
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */

_