summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux/linux_stats.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linux/linux_stats.c')
-rw-r--r--sys/compat/linux/linux_stats.c59
1 files changed, 49 insertions, 10 deletions
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
index 84ade7b..3638c6b 100644
--- a/sys/compat/linux/linux_stats.c
+++ b/sys/compat/linux/linux_stats.c
@@ -257,7 +257,7 @@ static int
stat_copyout(struct stat *buf, void *ubuf)
{
struct l_stat lbuf;
-
+
bzero(&lbuf, sizeof(lbuf));
lbuf.st_dev = buf->st_dev;
lbuf.st_ino = buf->st_ino;
@@ -303,7 +303,7 @@ linux_stat(struct thread *td, struct linux_stat_args *args)
return (error);
}
LFREEPATH(path);
- return(stat_copyout(&buf, args->up));
+ return (stat_copyout(&buf, args->up));
}
int
@@ -325,7 +325,7 @@ linux_lstat(struct thread *td, struct linux_lstat_args *args)
return (error);
}
LFREEPATH(path);
- return(stat_copyout(&buf, args->up));
+ return (stat_copyout(&buf, args->up));
}
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
@@ -381,10 +381,22 @@ bsd_to_linux_ftype(const char *fstypename)
return (0L);
}
-static void
+static int
bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
{
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+ uint64_t tmp;
+#define LINUX_HIBITS 0xffffffff00000000ULL
+
+ tmp = bsd_statfs->f_blocks | bsd_statfs->f_bfree | bsd_statfs->f_files |
+ bsd_statfs->f_bsize;
+ if ((bsd_statfs->f_bavail != -1 && (bsd_statfs->f_bavail & LINUX_HIBITS)) ||
+ (bsd_statfs->f_ffree != -1 && (bsd_statfs->f_ffree & LINUX_HIBITS)) ||
+ (tmp & LINUX_HIBITS))
+ return (EOVERFLOW);
+#undef LINUX_HIBITS
+#endif
linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
linux_statfs->f_bsize = bsd_statfs->f_bsize;
linux_statfs->f_blocks = bsd_statfs->f_blocks;
@@ -395,6 +407,8 @@ bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
linux_statfs->f_namelen = MAXNAMLEN;
+
+ return (0);
}
int
@@ -415,8 +429,10 @@ linux_statfs(struct thread *td, struct linux_statfs_args *args)
LFREEPATH(path);
if (error)
return (error);
- bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
- return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+ error = bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+ if (error)
+ return (error);
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
}
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
@@ -458,7 +474,28 @@ linux_statfs64(struct thread *td, struct linux_statfs64_args *args)
if (error)
return (error);
bsd_to_linux_statfs64(&bsd_statfs, &linux_statfs);
- return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
+}
+
+int
+linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args)
+{
+ struct l_statfs64 linux_statfs;
+ struct statfs bsd_statfs;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(fstatfs64))
+ printf(ARGS(fstatfs64, "%d, *"), args->fd);
+#endif
+ if (args->bufsize != sizeof(struct l_statfs64))
+ return (EINVAL);
+
+ error = kern_fstatfs(td, args->fd, &bsd_statfs);
+ if (error)
+ return error;
+ bsd_to_linux_statfs64(&bsd_statfs, &linux_statfs);
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
}
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
@@ -475,9 +512,11 @@ linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
#endif
error = kern_fstatfs(td, args->fd, &bsd_statfs);
if (error)
- return error;
- bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
- return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+ return (error);
+ error = bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+ if (error)
+ return (error);
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
}
struct l_ustat
OpenPOWER on IntegriCloud