From 2e554617e5a6a41bf3f6c6306c753cd53abf728c Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 30 Jul 2019 23:48:25 -0400 Subject: [PATCH] ioctl: add fallback for new time64 SIOCGSTAMP[NS] without this, the SIOCGSTAMP and SIOCGSTAMPNS ioctl commands, for obtaining timestamps, would stop working on pre-5.1 kernels after time_t is switched to 64-bit and their values are changed to the new time64 versions. new code is written such that it's statically unreachable on 64-bit archs, and on existing 32-bit archs until the macro values are changed to activate 64-bit time_t. --- arch/sh/syscall_arch.h | 3 +++ src/internal/syscall.h | 7 +++++++ src/misc/ioctl.c | 25 ++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/arch/sh/syscall_arch.h b/arch/sh/syscall_arch.h index 48f61d94..628d8d37 100644 --- a/arch/sh/syscall_arch.h +++ b/arch/sh/syscall_arch.h @@ -88,3 +88,6 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo } #define SYSCALL_IPC_BROKEN_MODE + +#define SIOCGSTAMP_OLD (2U<<30 | 's'<<8 | 100 | 8<<16) +#define SIOCGSTAMPNS_OLD (2U<<30 | 's'<<8 | 101 | 8<<16) diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 16edf30a..9f2784db 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -306,6 +306,13 @@ hidden long __syscall_ret(unsigned long), #define SO_SNDTIMEO_OLD 21 #endif +#ifndef SIOCGSTAMP_OLD +#define SIOCGSTAMP_OLD 0x8906 +#endif +#ifndef SIOCGSTAMPNS_OLD +#define SIOCGSTAMPNS_OLD 0x8907 +#endif + #ifdef SYS_open #define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE) #define __sys_open3(x,pn,fl,mo) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, mo) diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c index 5a41f0e8..6f31d4bc 100644 --- a/src/misc/ioctl.c +++ b/src/misc/ioctl.c @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #include "syscall.h" int ioctl(int fd, int req, ...) @@ -9,5 +12,25 @@ int ioctl(int fd, int req, ...) va_start(ap, req); arg = va_arg(ap, void *); va_end(ap); - return syscall(SYS_ioctl, fd, req, arg); + int r = __syscall(SYS_ioctl, fd, req, arg); + if (r==-ENOTTY) switch (req) { + case SIOCGSTAMP: + case SIOCGSTAMPNS: + if (SIOCGSTAMP==SIOCGSTAMP_OLD) break; + if (req==SIOCGSTAMP) req=SIOCGSTAMP_OLD; + if (req==SIOCGSTAMPNS) req=SIOCGSTAMPNS_OLD; + long t32[2]; + r = __syscall(SYS_ioctl, fd, req, t32); + if (r<0) break; + if (req==SIOCGSTAMP_OLD) { + struct timeval *tv = arg; + tv->tv_sec = t32[0]; + tv->tv_usec = t32[1]; + } else { + struct timespec *ts = arg; + ts->tv_sec = t32[0]; + ts->tv_nsec = t32[1]; + } + } + return __syscall_ret(r); } -- 2.25.1