summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authornetchild <netchild@FreeBSD.org>2006-12-31 13:16:00 +0000
committernetchild <netchild@FreeBSD.org>2006-12-31 13:16:00 +0000
commit33166d619b8ba364a03bc08fd443ae9627ff9413 (patch)
treec4faa5f6f5d40e35068b4965b47a98bd357029c6 /sys/compat
parent0a7aa5486d493b5160080b800e27c5d2e2c22a97 (diff)
downloadFreeBSD-src-33166d619b8ba364a03bc08fd443ae9627ff9413.zip
FreeBSD-src-33166d619b8ba364a03bc08fd443ae9627ff9413.tar.gz
MFp4 (111746, 108671, 108945, 112352):
- add linux utimes syscall [1] - add linux rt_sigtimedwait syscall [2] Submitted by: "Scot Hetzel" <swhetzel@gmail.com> [1] Submitted by: Bruce Becker <hostmaster@whois.gts.net> [2] PR: 93199 [2]
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linux/linux_misc.c32
-rw-r--r--sys/compat/linux/linux_signal.c85
2 files changed, 117 insertions, 0 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 489b079..e137e6b 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -786,6 +786,38 @@ linux_utime(struct thread *td, struct linux_utime_args *args)
LFREEPATH(fname);
return (error);
}
+
+int
+linux_utimes(struct thread *td, struct linux_utimes_args *args)
+{
+ l_timeval ltv[2];
+ struct timeval tv[2], *tvp = NULL;
+ char *fname;
+ int error;
+
+ LCONVPATHEXIST(td, args->fname, &fname);
+
+#ifdef DEBUG
+ if (ldebug(utimes))
+ printf(ARGS(utimes, "%s, *"), fname);
+#endif
+
+ if (args->tptr != NULL) {
+ if ((error = copyin(args->tptr, ltv, sizeof ltv))) {
+ LFREEPATH(fname);
+ return (error);
+ }
+ tv[0].tv_sec = ltv[0].tv_sec;
+ tv[0].tv_usec = ltv[0].tv_usec;
+ tv[1].tv_sec = ltv[1].tv_sec;
+ tv[1].tv_usec = ltv[1].tv_usec;
+ tvp = tv;
+ }
+
+ error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE);
+ LFREEPATH(fname);
+ return (error);
+}
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
#define __WCLONE 0x80000000
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
index 7b17200..30561d6 100644
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -422,6 +422,91 @@ linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
return (copyout(&lset, args->set, args->sigsetsize));
}
+/*
+ * MPSAFE
+ */
+int
+linux_rt_sigtimedwait(struct thread *td,
+ struct linux_rt_sigtimedwait_args *args)
+{
+ int error;
+ l_timeval ltv;
+ struct timeval tv;
+ struct timespec ts, *tsa;
+ l_sigset_t lset;
+ sigset_t bset;
+ l_siginfo_t linfo;
+ ksiginfo_t info;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(ARGS(rt_sigtimedwait, "*"));
+#endif
+ if (args->sigsetsize != sizeof(l_sigset_t))
+ return (EINVAL);
+
+ if ((error = copyin(args->mask, &lset, sizeof(lset))))
+ return (error);
+ linux_to_bsd_sigset(&lset, &bset);
+
+ tsa = NULL;
+ if (args->timeout) {
+ if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
+ return (error);
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(LMSG("linux_rt_sigtimedwait: incoming timeout (%d/%d)\n"),
+ ltv.tv_sec, ltv.tv_usec);
+#endif
+ tv.tv_sec = (long)ltv.tv_sec;
+ tv.tv_usec = (suseconds_t)ltv.tv_usec;
+ if (itimerfix(&tv)) {
+ /*
+ * The timeout was invalid. Convert it to something
+ * valid that will act as it does under Linux.
+ */
+ tv.tv_sec += tv.tv_usec / 1000000;
+ tv.tv_usec %= 1000000;
+ if (tv.tv_usec < 0) {
+ tv.tv_sec -= 1;
+ tv.tv_usec += 1000000;
+ }
+ if (tv.tv_sec < 0)
+ timevalclear(&tv);
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(LMSG("linux_rt_sigtimedwait: converted timeout (%d/%ld)\n"),
+ tv.tv_sec, tv.tv_usec);
+#endif
+ }
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ tsa = &ts;
+ }
+ error = kern_sigtimedwait(td, bset, &info, tsa);
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(LMSG("linux_rt_sigtimedwait: sigtimedwait returning (%d)\n"), error);
+#endif
+ if (error)
+ return (error);
+
+ if (args->ptr) {
+ memset(&linfo, 0, sizeof(linfo));
+ linfo.lsi_signo = info.ksi_signo;
+ error = copyout(&linfo, args->ptr, sizeof(linfo));
+ }
+
+ /* Repost if we got an error. */
+ if (error && info.ksi_signo) {
+ PROC_LOCK(td->td_proc);
+ tdsignal(td->td_proc, td, info.ksi_signo, &info);
+ PROC_UNLOCK(td->td_proc);
+ } else
+ td->td_retval[0] = info.ksi_signo;
+
+ return (error);
+}
+
int
linux_kill(struct thread *td, struct linux_kill_args *args)
{
OpenPOWER on IntegriCloud