@@ -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 */