linux-user: respect timezone for settimeofday
The settimeofday syscall accepts a tz argument indicating the desired timezone to the kernel. QEMU previously ignored any argument provided by the target program & always passed NULL to the kernel. Instead, translate the argument & pass along the data userland provided. Although this argument is described by the settimeofday man page as obsolete, it is used by systemd as of version 213. Signed-off-by: Paul Burton <paul@archlinuxmips.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
parent
fd76783243
commit
ef4467e911
@ -935,6 +935,23 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline abi_long copy_from_user_timezone(struct timezone *tz,
|
||||||
|
abi_ulong target_tz_addr)
|
||||||
|
{
|
||||||
|
struct target_timezone *target_tz;
|
||||||
|
|
||||||
|
if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
__get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
|
||||||
|
__get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
|
||||||
|
|
||||||
|
unlock_user_struct(target_tz, target_tz_addr, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
|
#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
|
||||||
#include <mqueue.h>
|
#include <mqueue.h>
|
||||||
|
|
||||||
@ -6385,9 +6402,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||||||
case TARGET_NR_settimeofday:
|
case TARGET_NR_settimeofday:
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
struct timezone tz, *ptz = NULL;
|
||||||
|
|
||||||
if (copy_from_user_timeval(&tv, arg1))
|
if (copy_from_user_timeval(&tv, arg1))
|
||||||
goto efault;
|
goto efault;
|
||||||
ret = get_errno(settimeofday(&tv, NULL));
|
|
||||||
|
if (arg2) {
|
||||||
|
if (copy_from_user_timezone(&tz, arg2)) {
|
||||||
|
goto efault;
|
||||||
|
}
|
||||||
|
ptz = &tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = get_errno(settimeofday(&tv, ptz));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if defined(TARGET_NR_select)
|
#if defined(TARGET_NR_select)
|
||||||
|
@ -165,6 +165,11 @@ struct target_timespec {
|
|||||||
abi_long tv_nsec;
|
abi_long tv_nsec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct target_timezone {
|
||||||
|
abi_int tz_minuteswest;
|
||||||
|
abi_int tz_dsttime;
|
||||||
|
};
|
||||||
|
|
||||||
struct target_itimerval {
|
struct target_itimerval {
|
||||||
struct target_timeval it_interval;
|
struct target_timeval it_interval;
|
||||||
struct target_timeval it_value;
|
struct target_timeval it_value;
|
||||||
|
Loading…
Reference in New Issue
Block a user