Add time-related system call shims: utimes, lutimes, futimes, futimesat, ktimer_create, ktimer_delete, ktimer_settime, and ktimer_gettime.
Signed-off-by: Stacey Son <[email protected]> Signed-off-by: Mikaƫl Urankar <[email protected]> Signed-off-by: Kyle Evans <[email protected]> Signed-off-by: Warner Losh <[email protected]> Assisted-by: Claude Opus 4.6 (1M context) --- bsd-user/freebsd/os-time.h | 210 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/bsd-user/freebsd/os-time.h b/bsd-user/freebsd/os-time.h index bcc1a826a7..f1f8da90ba 100644 --- a/bsd-user/freebsd/os-time.h +++ b/bsd-user/freebsd/os-time.h @@ -217,5 +217,215 @@ static inline abi_long do_freebsd_ntp_gettime(abi_ulong target_ntv_addr) } +/* utimes(2) */ +static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + struct timeval *tvp, tv[2]; + + if (arg2 != 0) { + if (t2h_freebsd_timeval(&tv[0], arg2) || + t2h_freebsd_timeval(&tv[1], arg2 + + sizeof(struct target_freebsd_timeval))) { + return -TARGET_EFAULT; + } + tvp = tv; + } else { + tvp = NULL; + } + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(utimes(p, tvp)); + unlock_user(p, arg1, 0); + + return ret; +} + +/* lutimes(2) */ +static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + struct timeval *tvp, tv[2]; + + if (arg2 != 0) { + if (t2h_freebsd_timeval(&tv[0], arg2) || + t2h_freebsd_timeval(&tv[1], arg2 + + sizeof(struct target_freebsd_timeval))) { + return -TARGET_EFAULT; + } + tvp = tv; + } else { + tvp = NULL; + } + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(lutimes(p, tvp)); + unlock_user(p, arg1, 0); + + return ret; +} + +/* futimes(2) */ +static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2) +{ + struct timeval *tvp, tv[2]; + + if (arg2 != 0) { + if (t2h_freebsd_timeval(&tv[0], arg2) || + t2h_freebsd_timeval(&tv[1], arg2 + + sizeof(struct target_freebsd_timeval))) { + return -TARGET_EFAULT; + } + tvp = tv; + } else { + tvp = NULL; + } + + return get_errno(futimes(arg1, tvp)); +} + +/* futimesat(2) */ +static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_long ret; + void *p; + struct timeval *tvp, tv[2]; + + if (arg3 != 0) { + if (t2h_freebsd_timeval(&tv[0], arg3) || + t2h_freebsd_timeval(&tv[1], arg3 + + sizeof(struct target_freebsd_timeval))) { + return -TARGET_EFAULT; + } + tvp = tv; + } else { + tvp = NULL; + } + + p = lock_user_string(arg2); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(futimesat(arg1, p, tvp)); + unlock_user(p, arg2, 0); + + return ret; +} + +/* timer_create(2) */ +static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + /* args: clockid_t clockid, struct sigevent *sevp, int *timerid */ + abi_long ret; + + struct sigevent host_sevp = { 0 }, *phost_sevp = NULL; + + int clkid = arg1; + int timer_index = next_free_host_timer(); + + if (timer_index < 0) { + ret = -TARGET_EAGAIN; + } else { + int *phtimer = g_posix_timers + timer_index; + + if (arg2) { + phost_sevp = &host_sevp; + ret = target_to_host_sigevent(phost_sevp, arg2); + if (ret != 0) { + return -TARGET_EFAULT; + } + } + + ret = get_errno(__sys_ktimer_create(clkid, phost_sevp, phtimer)); + if (ret) { + phtimer = NULL; + } else { + if (put_user(TIMER_MAGIC | timer_index, arg3, int)) { + ret = -TARGET_EFAULT; + } + } + } + return ret; +} + +/* timer_delete(2) */ +static inline abi_long do_freebsd_ktimer_delete(abi_long arg1) +{ + /* args: int timerid */ + abi_long ret; + int timerid = get_timer_id(arg1); + + if (timerid < 0) { + ret = timerid; + } else { + int htimer = g_posix_timers[timerid]; + ret = get_errno(__sys_ktimer_delete(htimer)); + g_posix_timers[timerid] = 0; + } + return ret; +} + +/* timer_settime(2) */ +static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + /* + * args: int timerid, int flags, const struct itimerspec *new_value, + * struct itimerspec * old_value + */ + abi_long ret; + int timerid = get_timer_id(arg1); + + if (timerid < 0) { + ret = timerid; + } else if (arg3 == 0) { + ret = -TARGET_EINVAL; + } else { + int htimer = g_posix_timers[timerid]; + struct itimerspec hspec_new = {{0},}, hspec_old = {{0},}; + + if (target_to_host_itimerspec(&hspec_new, arg3)) { + return -TARGET_EFAULT; + } + ret = get_errno( + __sys_ktimer_settime(htimer, arg2, &hspec_new, &hspec_old)); + if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) { + return -TARGET_EFAULT; + } + } + return ret; +} + +/* timer_gettime(2) */ +static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long arg2) +{ + /* args: int timerid, struct itimerspec *curr_value */ + abi_long ret; + int timerid = get_timer_id(arg1); + + if (timerid < 0) { + ret = timerid; + } else if (!arg2) { + ret = -TARGET_EFAULT; + } else { + int htimer = g_posix_timers[timerid]; + struct itimerspec hspec; + ret = get_errno(__sys_ktimer_gettime(htimer, &hspec)); + + if (host_to_target_itimerspec(arg2, &hspec)) { + ret = -TARGET_EFAULT; + } + } + return ret; +} + #endif /* FREEBSD_OS_TIME_H */ -- 2.52.0
