summaryrefslogtreecommitdiff
path: root/sys/compat/linux/linux_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linux/linux_misc.c')
-rw-r--r--sys/compat/linux/linux_misc.c150
1 files changed, 95 insertions, 55 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index d78c56f9989..48d41a20c6e 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_misc.c,v 1.81 2013/08/13 05:52:21 guenther Exp $ */
+/* $OpenBSD: linux_misc.c,v 1.82 2013/10/25 04:51:39 guenther Exp $ */
/* $NetBSD: linux_misc.c,v 1.27 1996/05/20 01:59:21 fvdl Exp $ */
/*-
@@ -70,6 +70,7 @@
#include <uvm/uvm_extern.h>
#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_time.h>
#include <compat/linux/linux_fcntl.h>
#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_mmap.h>
@@ -83,12 +84,16 @@
#include <compat/common/compat_dir.h>
/* linux_misc.c */
-static void bsd_to_linux_statfs(struct statfs *, struct linux_statfs *);
+void bsd_to_linux_statfs(const struct statfs *, struct linux_statfs *);
+void bsd_to_linux_statfs64(const struct statfs *, struct linux_statfs64 *);
int linux_select1(struct proc *, register_t *, int, fd_set *,
- fd_set *, fd_set *, struct timeval *);
-static int getdents_common(struct proc *, void *, register_t *, int);
-static void linux_to_bsd_mmap_args(struct sys_mmap_args *,
- const struct linux_sys_mmap2_args *);
+ fd_set *, fd_set *, struct linux_timeval *);
+int getdents_common(struct proc *, void *, register_t *, int);
+void linux_to_bsd_mmap_args(struct sys_mmap_args *,
+ const struct linux_sys_mmap2_args *);
+void bsd_to_linux_rusage(struct linux_rusage *, const struct rusage *);
+void bsd_to_linux_wstat(int *);
+
/*
* The information on a terminated (or stopped) process needs
@@ -109,6 +114,20 @@ bsd_to_linux_wstat(status)
}
/*
+ * Convert an rusage to Linux format: small time_t in the timevals
+ */
+void
+bsd_to_linux_rusage(struct linux_rusage *lrup, const struct rusage *rup)
+{
+ bsd_to_linux_timeval(&lrup->ru_utime, &rup->ru_utime);
+ bsd_to_linux_timeval(&lrup->ru_utime, &rup->ru_utime);
+ memcpy(&lrup->ru_maxrss, &rup->ru_maxrss,
+ offsetof(struct rusage, ru_nivcsw) -
+ offsetof(struct rusage, ru_maxrss) +
+ sizeof(lrup->ru_nivcsw));
+}
+
+/*
* waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage.
*/
int
@@ -133,9 +152,8 @@ linux_sys_waitpid(p, v, retval)
}
/*
- * wait4(2). Passed on to the OpenBSD call, surrounded by code to reserve
- * some space for an OpenBSD-style wait status, and converting it to what
- * Linux wants.
+ * wait4(2): handle conversion of the options on entry and status and rusage
+ * on return.
*/
int
linux_sys_wait4(p, v, retval)
@@ -147,17 +165,10 @@ linux_sys_wait4(p, v, retval)
syscallarg(int) pid;
syscallarg(int *) status;
syscallarg(int) options;
- syscallarg(struct rusage *) rusage;
+ syscallarg(struct linux_rusage *) rusage;
} */ *uap = v;
- struct sys_wait4_args w4a;
- int error, *status, tstat, linux_options, options;
- caddr_t sg;
-
- if (SCARG(uap, status) != NULL) {
- sg = stackgap_init(p->p_emul);
- status = (int *) stackgap_alloc(&sg, sizeof *status);
- } else
- status = NULL;
+ struct rusage ru;
+ int error, status, linux_options, options;
linux_options = SCARG(uap, options);
options = 0;
@@ -172,27 +183,55 @@ linux_sys_wait4(p, v, retval)
if (linux_options & LINUX_WAIT4_WCLONE)
options |= WALTSIG;
- SCARG(&w4a, pid) = SCARG(uap, pid);
- SCARG(&w4a, status) = status;
- SCARG(&w4a, options) = options;
- SCARG(&w4a, rusage) = SCARG(uap, rusage);
-
- if ((error = sys_wait4(p, &w4a, retval)))
+ if ((error = dowait4(p, SCARG(uap, pid),
+ SCARG(uap, status) ? &status : NULL, options,
+ SCARG(uap, rusage) ? &ru : NULL, retval)))
return error;
atomic_clearbits_int(&p->p_siglist, sigmask(SIGCHLD));
- if (status != NULL) {
- if ((error = copyin(status, &tstat, sizeof tstat)))
- return error;
+ if (SCARG(uap, rusage) != NULL) {
+ struct linux_rusage lru;
- bsd_to_linux_wstat(&tstat);
- return copyout(&tstat, SCARG(uap, status), sizeof tstat);
+ bsd_to_linux_rusage(&lru, &ru);
+ if ((error = copyout(&lru, SCARG(uap, rusage), sizeof lru)))
+ return error;
+ }
+ if (SCARG(uap, status) != NULL) {
+ bsd_to_linux_wstat(&status);
+ return copyout(&status, SCARG(uap, status), sizeof status);
}
return 0;
}
+/*
+ * getrusage(2): convert rusage on return
+ */
+int
+linux_sys_getrusage(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_getrusage_args /* {
+ syscallarg(int) who;
+ syscallarg(struct linux_rusage *) rusage;
+ } */ *uap = v;
+ struct rusage ru;
+ int error;
+
+ error = dogetrusage(p, SCARG(uap, who), &ru);
+ if (error == 0) {
+ struct linux_rusage lru;
+
+ bsd_to_linux_rusage(&lru, &ru);
+ error = copyout(&lru, SCARG(uap, rusage), sizeof lru);
+ }
+ return error;
+}
+
+
int
linux_sys_setresgid16(p, v, retval)
struct proc *p;
@@ -365,8 +404,8 @@ linux_sys_time(p, v, retval)
* the length of a name in a dir entry in a field, which
* we fake (probably the wrong way).
*/
-static void
-bsd_to_linux_statfs(struct statfs *bsp, struct linux_statfs *lsp)
+void
+bsd_to_linux_statfs(const struct statfs *bsp, struct linux_statfs *lsp)
{
/*
@@ -447,8 +486,8 @@ linux_sys_statfs(p, v, retval)
return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
}
-static void
-bsd_to_linux_statfs64(struct statfs *bsp, struct linux_statfs64 *lsp)
+void
+bsd_to_linux_statfs64(const struct statfs *bsp, struct linux_statfs64 *lsp)
{
/*
@@ -763,7 +802,7 @@ linux_sys_mmap2(p, v, retval)
return sys_mmap(p, &cma, retval);
}
-static void
+void
linux_to_bsd_mmap_args(cma, uap)
struct sys_mmap_args *cma;
const struct linux_sys_mmap2_args *uap;
@@ -853,7 +892,7 @@ linux_sys_times(p, v, retval)
register_t *retval;
{
struct linux_sys_times_args /* {
- syscallarg(struct times *) tms;
+ syscallarg(struct linux_tms *) tms;
} */ *uap = v;
struct timeval t, ut, st;
struct linux_tms ltms;
@@ -1135,7 +1174,7 @@ linux_sys_getdents(p, v, retval)
return getdents_common(p, v, retval, 0);
}
-static int
+int
getdents_common(p, v, retval, is64bit)
struct proc *p;
void *v;
@@ -1222,7 +1261,7 @@ linux_sys_select(p, v, retval)
syscallarg(fd_set *) readfds;
syscallarg(fd_set *) writefds;
syscallarg(fd_set *) exceptfds;
- syscallarg(struct timeval *) timeout;
+ syscallarg(struct linux_timeval *) timeout;
} */ *uap = v;
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
@@ -1236,14 +1275,11 @@ linux_sys_select(p, v, retval)
* 2) select never returns ERESTART on Linux, always return EINTR
*/
int
-linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
- struct proc *p;
- register_t *retval;
- int nfds;
- fd_set *readfds, *writefds, *exceptfds;
- struct timeval *timeout;
+linux_select1(struct proc *p, register_t *retval, int nfds, fd_set *readfds,
+ fd_set *writefds, fd_set *exceptfds, struct linux_timeval *timeout)
{
struct sys_select_args bsa;
+ struct linux_timeval lutv;
struct timeval tv0, tv1, utv, *tvp;
caddr_t sg;
int error;
@@ -1252,22 +1288,20 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
SCARG(&bsa, in) = readfds;
SCARG(&bsa, ou) = writefds;
SCARG(&bsa, ex) = exceptfds;
- SCARG(&bsa, tv) = timeout;
/*
* Store current time for computation of the amount of
* time left.
*/
if (timeout) {
- if ((error = copyin(timeout, &utv, sizeof(utv))))
+ if ((error = copyin(timeout, &lutv, sizeof(lutv))))
return error;
+ linux_to_bsd_timeval(&utv, &lutv);
if (itimerfix(&utv)) {
/*
* The timeval was invalid. Convert it to something
* valid that will act as it does under Linux.
*/
- sg = stackgap_init(p->p_emul);
- tvp = stackgap_alloc(&sg, sizeof(utv));
utv.tv_sec += utv.tv_usec / 1000000;
utv.tv_usec %= 1000000;
if (utv.tv_usec < 0) {
@@ -1276,12 +1310,16 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
}
if (utv.tv_sec < 0)
timerclear(&utv);
- if ((error = copyout(&utv, tvp, sizeof(utv))))
- return error;
- SCARG(&bsa, tv) = tvp;
}
+
+ sg = stackgap_init(p->p_emul);
+ tvp = stackgap_alloc(&sg, sizeof(utv));
+ if ((error = copyout(&utv, tvp, sizeof(utv))))
+ return error;
+ SCARG(&bsa, tv) = tvp;
microtime(&tv0);
- }
+ } else
+ SCARG(&bsa, tv) = NULL;
error = sys_select(p, &bsa, retval);
if (error) {
@@ -1291,7 +1329,8 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
*/
if (error == ERESTART)
error = EINTR;
- return error;
+ else if (error != EINTR)
+ return error;
}
if (timeout) {
@@ -1309,11 +1348,12 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
timerclear(&utv);
} else
timerclear(&utv);
- if ((error = copyout(&utv, timeout, sizeof(utv))))
+ bsd_to_linux_timeval(&lutv, &utv); /* can't fail */
+ if ((error = copyout(&lutv, timeout, sizeof(lutv))))
return error;
}
- return 0;
+ return (error);
}
/*