diff options
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linux/linux_misc.c | 32 | ||||
-rw-r--r-- | sys/compat/linux/linux_signal.c | 85 |
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, <v, 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) { |