mailing list of musl libc
 help / color / mirror / code / Atom feed
* [PATCH v2] remaining steps for time64 switchover
@ 2019-11-01 20:25 Rich Felker
  2019-11-02  0:02 ` Rich Felker
  0 siblings, 1 reply; 2+ messages in thread
From: Rich Felker @ 2019-11-01 20:25 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 591 bytes --]

This is the version of the time64 switchover I hope to push soon, with
the sockopt/ioctl fixes integrated. That part isn't as pretty as I'd
like, in terms of how the steps are factored, but at this point it
should be working without breaking anything (I tested builds of the
weird-bits archs mips, powerpc, and x32, as well as i386 and sh, and
confirmed right macro definitions are getting used).

I'll be out for the next few hours, but hoping to push tonight or
tomorrow, so if you want to help looking for embarrassing mistakes I'd
prefer not to have in there, now is the time. :-)

Rich

[-- Attachment #2: 0001-add-time64-symbol-name-redirects-to-public-headers-u.patch --]
[-- Type: text/plain, Size: 12538 bytes --]

From 1febd21d3fb7b78f6fc13e48b3ff2a396a607a15 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Wed, 31 Jul 2019 15:24:58 -0400
Subject: [PATCH 01/15] add time64 symbol name redirects to public headers,
 under arch control

a _REDIR_TIME64 macro is introduced, which the arch's alltypes.h is
expected to define, to control redirection of symbol names for
interfaces that involve time_t and derived types. this ensures that
object files will only be linked to libc interfaces matching the ABI
whose headers they were compiled against.

along with time32 compat shims, which will be introduced separately,
the redirection also makes it possible for a single libc (static or
shared) to be used with object files produced with either the old
(32-bit time_t) headers or the new ones after 64-bit time_t switchover
takes place. mixing of such object files (or shared libraries) in the
same program will also be possible, but must be done with care; ABI
between libc and a consumer of the libc interfaces is guaranteed to
match by the the symbol name redirection, but pairwise ABI between
consumers of libc that define interfaces between each other in terms
of time_t is not guaranteed to match.

this change adds a dependency on an additional "GNU C" feature to the
public headers for existing 32-bit archs, which is generally
undesirable; however, the feature is one which glibc has depended on
for a long time, and thus which any viable alternative compiler is
going to need to provide. 64-bit archs are not affected, nor will
future 32-bit archs be, regardless of whether they are "new" on the
kernel side (e.g. riscv32) or just newly-added (e.g. a new sparc or
xtensa port). the same applies to newly-added ABIs for existing
machine-level archs.
---
 include/aio.h          |  4 ++++
 include/features.h     |  2 ++
 include/mqueue.h       |  5 +++++
 include/poll.h         |  6 ++++++
 include/pthread.h      | 10 ++++++++++
 include/sched.h        |  4 ++++
 include/semaphore.h    |  4 ++++
 include/signal.h       |  8 ++++++++
 include/sys/resource.h |  4 ++++
 include/sys/select.h   |  5 +++++
 include/sys/sem.h      |  6 ++++++
 include/sys/socket.h   |  6 ++++++
 include/sys/stat.h     |  9 +++++++++
 include/sys/time.h     | 14 ++++++++++++++
 include/sys/timeb.h    |  6 ++++++
 include/sys/timerfd.h  |  5 +++++
 include/sys/timex.h    |  5 +++++
 include/sys/wait.h     |  7 +++++++
 include/threads.h      |  6 ++++++
 include/time.h         | 28 ++++++++++++++++++++++++++++
 include/utime.h        |  6 ++++++
 21 files changed, 150 insertions(+)

diff --git a/include/aio.h b/include/aio.h
index 19bc28a9..453c41b7 100644
--- a/include/aio.h
+++ b/include/aio.h
@@ -62,6 +62,10 @@ int lio_listio(int, struct aiocb *__restrict const *__restrict, int, struct sige
 #define off64_t off_t
 #endif
 
+#if _REDIR_TIME64
+__REDIR(aio_suspend, __aio_suspend_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/features.h b/include/features.h
index f4d651ef..85cfb72a 100644
--- a/include/features.h
+++ b/include/features.h
@@ -35,4 +35,6 @@
 #define _Noreturn
 #endif
 
+#define __REDIR(x,y) __typeof__(x) x __asm__(#y)
+
 #endif
diff --git a/include/mqueue.h b/include/mqueue.h
index f5cbe796..0c807ea0 100644
--- a/include/mqueue.h
+++ b/include/mqueue.h
@@ -30,6 +30,11 @@ ssize_t mq_timedreceive(mqd_t, char *__restrict, size_t, unsigned *__restrict, c
 int mq_timedsend(mqd_t, const char *, size_t, unsigned, const struct timespec *);
 int mq_unlink(const char *);
 
+#if _REDIR_TIME64
+__REDIR(mq_timedreceive, __mq_timedreceive_time64);
+__REDIR(mq_timedsend, __mq_timedsend_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/poll.h b/include/poll.h
index daccc760..472e4b84 100644
--- a/include/poll.h
+++ b/include/poll.h
@@ -44,6 +44,12 @@ int poll (struct pollfd *, nfds_t, int);
 int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
 #endif
 
+#if _REDIR_TIME64
+#ifdef _GNU_SOURCE
+__REDIR(ppoll, __ppoll_time64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/pthread.h b/include/pthread.h
index e238321b..984db680 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -224,6 +224,16 @@ int pthread_tryjoin_np(pthread_t, void **);
 int pthread_timedjoin_np(pthread_t, void **, const struct timespec *);
 #endif
 
+#if _REDIR_TIME64
+__REDIR(pthread_mutex_timedlock, __pthread_mutex_timedlock_time64);
+__REDIR(pthread_cond_timedwait, __pthread_cond_timedwait_time64);
+__REDIR(pthread_rwlock_timedrdlock, __pthread_rwlock_timedrdlock_time64);
+__REDIR(pthread_rwlock_timedwrlock, __pthread_rwlock_timedwrlock_time64);
+#ifdef _GNU_SOURCE
+__REDIR(pthread_timedjoin_np, __pthread_timedjoin_np_time64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sched.h b/include/sched.h
index 7e470d3a..c3a8d49a 100644
--- a/include/sched.h
+++ b/include/sched.h
@@ -133,6 +133,10 @@ __CPU_op_func_S(XOR, ^)
 
 #endif
 
+#if _REDIR_TIME64
+__REDIR(sched_rr_get_interval, __sched_rr_get_interval_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/semaphore.h b/include/semaphore.h
index 277c47d6..3690f496 100644
--- a/include/semaphore.h
+++ b/include/semaphore.h
@@ -29,6 +29,10 @@ int    sem_trywait(sem_t *);
 int    sem_unlink(const char *);
 int    sem_wait(sem_t *);
 
+#if _REDIR_TIME64
+__REDIR(sem_timedwait, __sem_timedwait_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/signal.h b/include/signal.h
index 5c48cb83..fbdf667b 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -271,6 +271,14 @@ typedef int sig_atomic_t;
 void (*signal(int, void (*)(int)))(int);
 int raise(int);
 
+#if _REDIR_TIME64
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
+ || defined(_BSD_SOURCE)
+__REDIR(sigtimedwait, __sigtimedwait_time64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/resource.h b/include/sys/resource.h
index 70d793d5..e0c86ae3 100644
--- a/include/sys/resource.h
+++ b/include/sys/resource.h
@@ -104,6 +104,10 @@ int prlimit(pid_t, int, const struct rlimit *, struct rlimit *);
 #define rlim64_t rlim_t
 #endif
 
+#if _REDIR_TIME64
+__REDIR(getrusage, __getrusage_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/select.h b/include/sys/select.h
index d34cbf10..b3bab1d5 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -35,6 +35,11 @@ int pselect (int, fd_set *__restrict, fd_set *__restrict, fd_set *__restrict, co
 #define NFDBITS (8*(int)sizeof(long))
 #endif
 
+#if _REDIR_TIME64
+__REDIR(select, __select_time64);
+__REDIR(pselect, __pselect_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/sem.h b/include/sys/sem.h
index e6161e51..a747784e 100644
--- a/include/sys/sem.h
+++ b/include/sys/sem.h
@@ -60,6 +60,12 @@ int semop(int, struct sembuf *, size_t);
 int semtimedop(int, struct sembuf *, size_t, const struct timespec *);
 #endif
 
+#if _REDIR_TIME64
+#ifdef _GNU_SOURCE
+__REDIR(semtimedop, __semtimedop_time64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/socket.h b/include/sys/socket.h
index 8692efa7..318a98ef 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -350,6 +350,12 @@ int setsockopt (int, int, int, const void *, socklen_t);
 
 int sockatmark (int);
 
+#if _REDIR_TIME64
+#ifdef _GNU_SOURCE
+__REDIR(recvmmsg, __recvmmsg_time64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/stat.h b/include/sys/stat.h
index 9d096624..10d446c4 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -110,6 +110,15 @@ int lchmod(const char *, mode_t);
 #define off64_t off_t
 #endif
 
+#if _REDIR_TIME64
+__REDIR(stat, __stat_time64);
+__REDIR(fstat, __fstat_time64);
+__REDIR(lstat, __lstat_time64);
+__REDIR(fstatat, __fstatat_time64);
+__REDIR(futimens, __futimens_time64);
+__REDIR(utimensat, __utimensat_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/time.h b/include/sys/time.h
index c5cab814..cdc67ef6 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -56,6 +56,20 @@ int adjtime (const struct timeval *, struct timeval *);
 	(void)0 )
 #endif
 
+#if _REDIR_TIME64
+__REDIR(gettimeofday, __gettimeofday_time64);
+__REDIR(getitimer, __getitimer_time64);
+__REDIR(setitimer, __setitimer_time64);
+__REDIR(utimes, __utimes_time64);
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+__REDIR(futimes, __futimes_time64);
+__REDIR(futimesat, __futimesat_time64);
+__REDIR(lutimes, __lutimes_time64);
+__REDIR(settimeofday, __settimeofday_time64);
+__REDIR(adjtime, __adjtime64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/timeb.h b/include/sys/timeb.h
index 108c1f5c..628239b7 100644
--- a/include/sys/timeb.h
+++ b/include/sys/timeb.h
@@ -4,6 +4,8 @@
 extern "C" {
 #endif
 
+#include <features.h>
+
 #define __NEED_time_t
 
 #include <bits/alltypes.h>
@@ -16,6 +18,10 @@ struct timeb {
 
 int ftime(struct timeb *);
 
+#if _REDIR_TIME64
+__REDIR(ftime, __ftime64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/timerfd.h b/include/sys/timerfd.h
index 2794d36a..1b832cdd 100644
--- a/include/sys/timerfd.h
+++ b/include/sys/timerfd.h
@@ -20,6 +20,11 @@ int timerfd_create(int, int);
 int timerfd_settime(int, int, const struct itimerspec *, struct itimerspec *);
 int timerfd_gettime(int, struct itimerspec *);
 
+#if _REDIR_TIME64
+__REDIR(timerfd_settime, __timerfd_settime64);
+__REDIR(timerfd_gettime, __timerfd_gettime64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/timex.h b/include/sys/timex.h
index 2e688880..8b417e1b 100644
--- a/include/sys/timex.h
+++ b/include/sys/timex.h
@@ -91,6 +91,11 @@ struct timex {
 int adjtimex(struct timex *);
 int clock_adjtime(clockid_t, struct timex *);
 
+#if _REDIR_TIME64
+__REDIR(adjtimex, __adjtimex_time64);
+__REDIR(clock_adjtime, __clock_adjtime64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/wait.h b/include/sys/wait.h
index 50c5c709..d9adbdec 100644
--- a/include/sys/wait.h
+++ b/include/sys/wait.h
@@ -53,6 +53,13 @@ pid_t wait4 (pid_t, int *, int, struct rusage *);
 #define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu)
 #define WIFCONTINUED(s) ((s) == 0xffff)
 
+#if _REDIR_TIME64
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+__REDIR(wait3, __wait3_time64);
+__REDIR(wait4, __wait4_time64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/threads.h b/include/threads.h
index 8122b3b1..52ec3100 100644
--- a/include/threads.h
+++ b/include/threads.h
@@ -80,6 +80,12 @@ void tss_delete(tss_t);
 int tss_set(tss_t, void *);
 void *tss_get(tss_t);
 
+#if _REDIR_TIME64
+__REDIR(thrd_sleep, __thrd_sleep_time64);
+__REDIR(mtx_timedlock, __mtx_timedlock_time64);
+__REDIR(cnd_timedwait, __cnd_timedwait_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/time.h b/include/time.h
index 672b3fc3..5494df18 100644
--- a/include/time.h
+++ b/include/time.h
@@ -130,6 +130,34 @@ int stime(const time_t *);
 time_t timegm(struct tm *);
 #endif
 
+#if _REDIR_TIME64
+__REDIR(time, __time64);
+__REDIR(difftime, __difftime64);
+__REDIR(mktime, __mktime64);
+__REDIR(gmtime, __gmtime64);
+__REDIR(localtime, __localtime64);
+__REDIR(ctime, __ctime64);
+__REDIR(timespec_get, __timespec_get_time64);
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
+ || defined(_BSD_SOURCE)
+__REDIR(gmtime_r, __gmtime64_r);
+__REDIR(localtime_r, __localtime64_r);
+__REDIR(ctime_r, __ctime64_r);
+__REDIR(nanosleep, __nanosleep_time64);
+__REDIR(clock_getres, __clock_getres_time64);
+__REDIR(clock_gettime, __clock_gettime64);
+__REDIR(clock_settime, __clock_settime64);
+__REDIR(clock_nanosleep, __clock_nanosleep_time64);
+__REDIR(timer_settime, __timer_settime64);
+__REDIR(timer_gettime, __timer_gettime64);
+#endif
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+__REDIR(stime, __stime64);
+__REDIR(timegm, __timegm_time64);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/utime.h b/include/utime.h
index dd5ff927..5755bd53 100644
--- a/include/utime.h
+++ b/include/utime.h
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+#include <features.h>
+
 #define __NEED_time_t
 
 #include <bits/alltypes.h>
@@ -16,6 +18,10 @@ struct utimbuf {
 
 int utime (const char *, const struct utimbuf *);
 
+#if _REDIR_TIME64
+__REDIR(utime, __utime64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.21.0


[-- Attachment #3: 0002-prepare-struct-sched_param-for-change-in-time_t-defi.patch --]
[-- Type: text/plain, Size: 1004 bytes --]

From 2d69fcf5ef271c1f5fec45ee9337ec7280a5dae7 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Fri, 9 Aug 2019 22:20:55 -0400
Subject: [PATCH 02/15] prepare struct sched_param for change in time_t
 definition

the time_t members in struct sched_param are just reserved space to
preserve size and alignment. when time_t changes to 64-bit on 32-bit
archs, this structure should not change.

make definition conditional on _REDIR_TIME64 to match the size of the
old time_t, which can be assumed to be long if _REDIR_TIME64 is
defined.
---
 include/sched.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/sched.h b/include/sched.h
index c3a8d49a..822f464e 100644
--- a/include/sched.h
+++ b/include/sched.h
@@ -19,10 +19,14 @@ extern "C" {
 struct sched_param {
 	int sched_priority;
 	int __reserved1;
+#if _REDIR_TIME64
+	long __reserved2[4];
+#else
 	struct {
 		time_t __reserved1;
 		long __reserved2;
 	} __reserved2[2];
+#endif
 	int __reserved3;
 };
 
-- 
2.21.0


[-- Attachment #4: 0003-disable-lfs64-aliases-for-remapped-time64-functions.patch --]
[-- Type: text/plain, Size: 2765 bytes --]

From 50018f92f7a1d79bc41a1ad5c5baf99eb7cd40af Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 1 Aug 2019 00:56:48 -0400
Subject: [PATCH 03/15] disable lfs64 aliases for remapped time64 functions

these functions cannot provide the glibc lfs64-ABI-compatible symbols
when time_t differs from what it was in that ABI. instead, the aliases
need to be provided by the time32 compat shims or through some other
mechanism.
---
 src/aio/aio_suspend.c | 2 ++
 src/stat/__xstat.c    | 4 ++++
 src/stat/fstat.c      | 2 ++
 src/stat/fstatat.c    | 2 ++
 src/stat/lstat.c      | 2 ++
 src/stat/stat.c       | 2 ++
 6 files changed, 14 insertions(+)

diff --git a/src/aio/aio_suspend.c b/src/aio/aio_suspend.c
index 9b24b6af..34b66f87 100644
--- a/src/aio/aio_suspend.c
+++ b/src/aio/aio_suspend.c
@@ -73,4 +73,6 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
 	}
 }
 
+#if !_REDIR_TIME64
 weak_alias(aio_suspend, aio_suspend64);
+#endif
diff --git a/src/stat/__xstat.c b/src/stat/__xstat.c
index f6303430..630936a0 100644
--- a/src/stat/__xstat.c
+++ b/src/stat/__xstat.c
@@ -1,5 +1,7 @@
 #include <sys/stat.h>
 
+#if !_REDIR_TIME64
+
 int __fxstat(int ver, int fd, struct stat *buf)
 {
 	return fstat(fd, buf);
@@ -25,6 +27,8 @@ weak_alias(__fxstatat, __fxstatat64);
 weak_alias(__lxstat, __lxstat64);
 weak_alias(__xstat, __xstat64);
 
+#endif
+
 int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev)
 {
 	return mknod(path, mode, *dev);
diff --git a/src/stat/fstat.c b/src/stat/fstat.c
index 07f9a5de..9bbb46de 100644
--- a/src/stat/fstat.c
+++ b/src/stat/fstat.c
@@ -10,4 +10,6 @@ int fstat(int fd, struct stat *st)
 	return fstatat(fd, "", st, AT_EMPTY_PATH);
 }
 
+#if !_REDIR_TIME64
 weak_alias(fstat, fstat64);
+#endif
diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
index d915fa10..bf0a554c 100644
--- a/src/stat/fstatat.c
+++ b/src/stat/fstatat.c
@@ -126,4 +126,6 @@ int fstatat(int fd, const char *restrict path, struct stat *restrict st, int fla
 	return __syscall_ret(ret);
 }
 
+#if !_REDIR_TIME64
 weak_alias(fstatat, fstatat64);
+#endif
diff --git a/src/stat/lstat.c b/src/stat/lstat.c
index 9f95218a..6fe004de 100644
--- a/src/stat/lstat.c
+++ b/src/stat/lstat.c
@@ -6,4 +6,6 @@ int lstat(const char *restrict path, struct stat *restrict buf)
 	return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
 }
 
+#if !_REDIR_TIME64
 weak_alias(lstat, lstat64);
+#endif
diff --git a/src/stat/stat.c b/src/stat/stat.c
index 528870d2..ea70efc4 100644
--- a/src/stat/stat.c
+++ b/src/stat/stat.c
@@ -6,4 +6,6 @@ int stat(const char *restrict path, struct stat *restrict buf)
 	return fstatat(AT_FDCWD, path, buf, 0);
 }
 
+#if !_REDIR_TIME64
 weak_alias(stat, stat64);
+#endif
-- 
2.21.0


[-- Attachment #5: 0004-make-fstatat-fill-in-old-time32-stat-fields-too.patch --]
[-- Type: text/plain, Size: 2015 bytes --]

From 0961bb94162896d358937e4979e5830f39818920 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 1 Aug 2019 21:33:57 -0400
Subject: [PATCH 04/15] make fstatat fill in old time32 stat fields too

here _REDIR_TIME64 is used as an indication that there's an old ABI,
and thereby the old time32 timespec fields of struct stat.

keeping struct stat compatible and providing both versions of the
timespec fields is done so that ftw/nftw does not need painful compat
shims, and (more importantly) so that similar interfaces between pairs
of libc consumers (applications/libraries) will be less likely to
break when one has been rebuilt for time64 but the other has not.
---
 src/stat/fstatat.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
index bf0a554c..de165b5c 100644
--- a/src/stat/fstatat.c
+++ b/src/stat/fstatat.c
@@ -57,6 +57,14 @@ static int fstatat_statx(int fd, const char *restrict path, struct stat *restric
 		.st_mtim.tv_nsec = stx.stx_mtime.tv_nsec,
 		.st_ctim.tv_sec = stx.stx_ctime.tv_sec,
 		.st_ctim.tv_nsec = stx.stx_ctime.tv_nsec,
+#if _REDIR_TIME64
+		.__st_atim32.tv_sec = stx.stx_atime.tv_sec,
+		.__st_atim32.tv_nsec = stx.stx_atime.tv_nsec,
+		.__st_mtim32.tv_sec = stx.stx_mtime.tv_sec,
+		.__st_mtim32.tv_nsec = stx.stx_mtime.tv_nsec,
+		.__st_ctim32.tv_sec = stx.stx_ctime.tv_sec,
+		.__st_ctim32.tv_nsec = stx.stx_ctime.tv_nsec,
+#endif
 	};
 	return 0;
 }
@@ -110,6 +118,14 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric
 		.st_mtim.tv_nsec = kst.st_mtime_nsec,
 		.st_ctim.tv_sec = kst.st_ctime_sec,
 		.st_ctim.tv_nsec = kst.st_ctime_nsec,
+#if _REDIR_TIME64
+		.__st_atim32.tv_sec = kst.st_atime_sec,
+		.__st_atim32.tv_nsec = kst.st_atime_nsec,
+		.__st_mtim32.tv_sec = kst.st_mtime_sec,
+		.__st_mtim32.tv_nsec = kst.st_mtime_nsec,
+		.__st_ctim32.tv_sec = kst.st_ctime_sec,
+		.__st_ctim32.tv_nsec = kst.st_ctime_nsec,
+#endif
 	};
 
 	return 0;
-- 
2.21.0


[-- Attachment #6: 0005-add-time32-ABI-compat-shims-compat-source-tree.patch --]
[-- Type: text/plain, Size: 50333 bytes --]

From 453811ea8595b63e3e3f557b2bfd36c02969ebae Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Fri, 2 Aug 2019 15:52:42 -0400
Subject: [PATCH 05/15] add time32 ABI compat shims, compat source tree

these files provide the symbols for the traditional 32-bit time_t ABI
on existing 32-bit archs by wrapping the real, internal versions of
the corresponding functions, which always work with 64-bit time_t.
they are written to be as agnostic as possible to the implementation
details of the real functions, so that they can be written once and
mostly forgotten, but they are aware of details of the old (and
sometimes new) ABI, which is okay since ABI is fixed and cannot
change.

a new compat tree is added, separate from src, which the Makefile does
not see or use now, but which archs will be able to add to the build
process. we could also consider moving other things that are compat
shims here, like functions which are purely for glibc-ABI-compat, with
the goal of making it optional or just cleaning up the main src tree
to make the distinction between actual implementation/API files and
ABI-compat shims clear.
---
 compat/time32/__xstat.c                       | 22 +++++
 compat/time32/adjtime32.c                     | 21 +++++
 compat/time32/adjtimex_time32.c               | 37 ++++++++
 compat/time32/aio_suspend_time32.c            | 11 +++
 compat/time32/clock_adjtime32.c               | 70 ++++++++++++++
 compat/time32/clock_getres_time32.c           | 13 +++
 compat/time32/clock_gettime32.c               | 18 ++++
 compat/time32/clock_nanosleep_time32.c        | 15 +++
 compat/time32/clock_settime32.c               |  9 ++
 compat/time32/cnd_timedwait_time32.c          |  9 ++
 compat/time32/ctime32.c                       |  7 ++
 compat/time32/ctime32_r.c                     |  7 ++
 compat/time32/difftime32.c                    |  7 ++
 compat/time32/fstat_time32.c                  | 17 ++++
 compat/time32/fstatat_time32.c                | 17 ++++
 compat/time32/ftime32.c                       | 25 +++++
 compat/time32/futimens_time32.c               | 10 ++
 compat/time32/futimes_time32.c                | 12 +++
 compat/time32/futimesat_time32.c              | 12 +++
 compat/time32/getitimer_time32.c              | 15 +++
 compat/time32/getrusage_time32.c              | 39 ++++++++
 compat/time32/gettimeofday_time32.c           | 19 ++++
 compat/time32/gmtime32.c                      |  7 ++
 compat/time32/gmtime32_r.c                    |  7 ++
 compat/time32/localtime32.c                   |  7 ++
 compat/time32/localtime32_r.c                 |  7 ++
 compat/time32/lstat_time32.c                  | 17 ++++
 compat/time32/lutimes_time32.c                | 12 +++
 compat/time32/mktime32.c                      | 16 ++++
 compat/time32/mq_timedreceive_time32.c        |  9 ++
 compat/time32/mq_timedsend_time32.c           |  9 ++
 compat/time32/mtx_timedlock_time32.c          |  9 ++
 compat/time32/nanosleep_time32.c              | 15 +++
 compat/time32/ppoll_time32.c                  | 10 ++
 compat/time32/pselect_time32.c                |  9 ++
 compat/time32/pthread_cond_timedwait_time32.c |  9 ++
 .../time32/pthread_mutex_timedlock_time32.c   |  9 ++
 .../pthread_rwlock_timedrdlock_time32.c       |  9 ++
 .../pthread_rwlock_timedwrlock_time32.c       |  9 ++
 compat/time32/pthread_timedjoin_np_time32.c   | 10 ++
 compat/time32/recvmmsg_time32.c               | 10 ++
 compat/time32/sched_rr_get_interval_time32.c  | 13 +++
 compat/time32/select_time32.c                 | 10 ++
 compat/time32/sem_timedwait_time32.c          |  9 ++
 compat/time32/semtimedop_time32.c             | 10 ++
 compat/time32/setitimer_time32.c              | 23 +++++
 compat/time32/settimeofday_time32.c           | 10 ++
 compat/time32/sigtimedwait_time32.c           |  9 ++
 compat/time32/stat_time32.c                   | 17 ++++
 compat/time32/stime32.c                       |  8 ++
 compat/time32/thrd_sleep_time32.c             | 16 ++++
 compat/time32/time32.c                        | 15 +++
 compat/time32/time32.h                        | 91 +++++++++++++++++++
 compat/time32/time32gm.c                      | 15 +++
 compat/time32/timer_gettime32.c               | 15 +++
 compat/time32/timer_settime32.c               | 25 +++++
 compat/time32/timerfd_gettime32.c             | 16 ++++
 compat/time32/timerfd_settime32.c             | 26 ++++++
 compat/time32/timespec_get_time32.c           | 18 ++++
 compat/time32/utime_time32.c                  | 14 +++
 compat/time32/utimensat_time32.c              | 11 +++
 compat/time32/utimes_time32.c                 | 11 +++
 compat/time32/wait3_time32.c                  | 40 ++++++++
 compat/time32/wait4_time32.c                  | 40 ++++++++
 64 files changed, 1064 insertions(+)
 create mode 100644 compat/time32/__xstat.c
 create mode 100644 compat/time32/adjtime32.c
 create mode 100644 compat/time32/adjtimex_time32.c
 create mode 100644 compat/time32/aio_suspend_time32.c
 create mode 100644 compat/time32/clock_adjtime32.c
 create mode 100644 compat/time32/clock_getres_time32.c
 create mode 100644 compat/time32/clock_gettime32.c
 create mode 100644 compat/time32/clock_nanosleep_time32.c
 create mode 100644 compat/time32/clock_settime32.c
 create mode 100644 compat/time32/cnd_timedwait_time32.c
 create mode 100644 compat/time32/ctime32.c
 create mode 100644 compat/time32/ctime32_r.c
 create mode 100644 compat/time32/difftime32.c
 create mode 100644 compat/time32/fstat_time32.c
 create mode 100644 compat/time32/fstatat_time32.c
 create mode 100644 compat/time32/ftime32.c
 create mode 100644 compat/time32/futimens_time32.c
 create mode 100644 compat/time32/futimes_time32.c
 create mode 100644 compat/time32/futimesat_time32.c
 create mode 100644 compat/time32/getitimer_time32.c
 create mode 100644 compat/time32/getrusage_time32.c
 create mode 100644 compat/time32/gettimeofday_time32.c
 create mode 100644 compat/time32/gmtime32.c
 create mode 100644 compat/time32/gmtime32_r.c
 create mode 100644 compat/time32/localtime32.c
 create mode 100644 compat/time32/localtime32_r.c
 create mode 100644 compat/time32/lstat_time32.c
 create mode 100644 compat/time32/lutimes_time32.c
 create mode 100644 compat/time32/mktime32.c
 create mode 100644 compat/time32/mq_timedreceive_time32.c
 create mode 100644 compat/time32/mq_timedsend_time32.c
 create mode 100644 compat/time32/mtx_timedlock_time32.c
 create mode 100644 compat/time32/nanosleep_time32.c
 create mode 100644 compat/time32/ppoll_time32.c
 create mode 100644 compat/time32/pselect_time32.c
 create mode 100644 compat/time32/pthread_cond_timedwait_time32.c
 create mode 100644 compat/time32/pthread_mutex_timedlock_time32.c
 create mode 100644 compat/time32/pthread_rwlock_timedrdlock_time32.c
 create mode 100644 compat/time32/pthread_rwlock_timedwrlock_time32.c
 create mode 100644 compat/time32/pthread_timedjoin_np_time32.c
 create mode 100644 compat/time32/recvmmsg_time32.c
 create mode 100644 compat/time32/sched_rr_get_interval_time32.c
 create mode 100644 compat/time32/select_time32.c
 create mode 100644 compat/time32/sem_timedwait_time32.c
 create mode 100644 compat/time32/semtimedop_time32.c
 create mode 100644 compat/time32/setitimer_time32.c
 create mode 100644 compat/time32/settimeofday_time32.c
 create mode 100644 compat/time32/sigtimedwait_time32.c
 create mode 100644 compat/time32/stat_time32.c
 create mode 100644 compat/time32/stime32.c
 create mode 100644 compat/time32/thrd_sleep_time32.c
 create mode 100644 compat/time32/time32.c
 create mode 100644 compat/time32/time32.h
 create mode 100644 compat/time32/time32gm.c
 create mode 100644 compat/time32/timer_gettime32.c
 create mode 100644 compat/time32/timer_settime32.c
 create mode 100644 compat/time32/timerfd_gettime32.c
 create mode 100644 compat/time32/timerfd_settime32.c
 create mode 100644 compat/time32/timespec_get_time32.c
 create mode 100644 compat/time32/utime_time32.c
 create mode 100644 compat/time32/utimensat_time32.c
 create mode 100644 compat/time32/utimes_time32.c
 create mode 100644 compat/time32/wait3_time32.c
 create mode 100644 compat/time32/wait4_time32.c

diff --git a/compat/time32/__xstat.c b/compat/time32/__xstat.c
new file mode 100644
index 00000000..d8cd5ef2
--- /dev/null
+++ b/compat/time32/__xstat.c
@@ -0,0 +1,22 @@
+#include "time32.h"
+#include <sys/stat.h>
+
+int __fxstat64(int ver, int fd, struct stat *buf)
+{
+	return __fstat_time32(fd, buf);
+}
+
+int __fxstatat64(int ver, int fd, const char *path, struct stat *buf, int flag)
+{
+	return __fstatat_time32(fd, path, buf, flag);
+}
+
+int __lxstat64(int ver, const char *path, struct stat *buf)
+{
+	return __lstat_time32(path, buf);
+}
+
+int __xstat64(int ver, const char *path, struct stat *buf)
+{
+	return __stat_time32(path, buf);
+}
diff --git a/compat/time32/adjtime32.c b/compat/time32/adjtime32.c
new file mode 100644
index 00000000..b0042c63
--- /dev/null
+++ b/compat/time32/adjtime32.c
@@ -0,0 +1,21 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+
+int __adjtime32(const struct timeval32 *in32, struct timeval32 *out32)
+{
+	struct timeval out;
+	int r = adjtime((&(struct timeval){
+		.tv_sec = in32->tv_sec,
+		.tv_usec = in32->tv_usec}), &out);
+	if (r) return r;
+	/* We can't range-check the result because success was already
+	 * committed by the above call. */
+	if (out32) {
+		out32->tv_sec = out.tv_sec;
+		out32->tv_usec = out.tv_usec;
+	}
+	return r;
+}
diff --git a/compat/time32/adjtimex_time32.c b/compat/time32/adjtimex_time32.c
new file mode 100644
index 00000000..d7541da8
--- /dev/null
+++ b/compat/time32/adjtimex_time32.c
@@ -0,0 +1,37 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <stddef.h>
+
+struct oldtimex {
+	unsigned modes;
+	long offset, freq, maxerror, esterror;
+	int status;
+	long constant, precision, tolerance;
+	long time_sec, time_usec;
+	long tick, ppsfreq, jitter;
+	int shift;
+	long stabil, jitcnt, calcnt, errcnt, stbcnt;
+	int tai;
+	int __padding[11];
+};
+
+int __adjtimex_time32(struct timex *tx32)
+{
+	struct timex utx;
+	memcpy(&utx, tx32, sizeof(struct oldtimex));
+	utx.time.tv_sec =
+		*(long *)((char *)tx32 + offsetof(struct oldtimex,time_sec));
+	utx.time.tv_usec =
+		*(long *)((char *)tx32 + offsetof(struct oldtimex,time_usec));
+	int r = adjtimex(&utx);
+	if (r<0) return r;
+	memcpy(tx32, &utx, sizeof(struct oldtimex));
+	*(long *)((char *)tx32 + offsetof(struct oldtimex,time_sec)) =
+		utx.time.tv_sec;
+	*(long *)((char *)tx32 + offsetof(struct oldtimex,time_usec)) =
+		utx.time.tv_usec;
+	return r;
+}
diff --git a/compat/time32/aio_suspend_time32.c b/compat/time32/aio_suspend_time32.c
new file mode 100644
index 00000000..ed5119bd
--- /dev/null
+++ b/compat/time32/aio_suspend_time32.c
@@ -0,0 +1,11 @@
+#include "time32.h"
+#include <time.h>
+#include <aio.h>
+
+int __aio_suspend_time32(const struct aiocb *const cbs[], int cnt, const struct timespec32 *ts32)
+{
+	return aio_suspend(cbs, cnt, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
+
+weak_alias(aio_suspend, aio_suspend64);
diff --git a/compat/time32/clock_adjtime32.c b/compat/time32/clock_adjtime32.c
new file mode 100644
index 00000000..5a25b8ac
--- /dev/null
+++ b/compat/time32/clock_adjtime32.c
@@ -0,0 +1,70 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <stddef.h>
+
+struct timex32 {
+	unsigned modes;
+	long offset, freq, maxerror, esterror;
+	int status;
+	long constant, precision, tolerance;
+	struct timeval32 time;
+	long tick, ppsfreq, jitter;
+	int shift;
+	long stabil, jitcnt, calcnt, errcnt, stbcnt;
+	int tai;
+	int __padding[11];
+};
+
+int __clock_adjtime32(clockid_t clock_id, struct timex32 *tx32)
+{
+	struct timex utx = {
+		.modes = tx32->modes,
+		.offset = tx32->offset,
+		.freq = tx32->freq,
+		.maxerror = tx32->maxerror,
+		.esterror = tx32->esterror,
+		.status = tx32->status,
+		.constant = tx32->constant,
+		.precision = tx32->precision,
+		.tolerance = tx32->tolerance,
+		.time.tv_sec = tx32->time.tv_sec,
+		.time.tv_usec = tx32->time.tv_usec,
+		.tick = tx32->tick,
+		.ppsfreq = tx32->ppsfreq,
+		.jitter = tx32->jitter,
+		.shift = tx32->shift,
+		.stabil = tx32->stabil,
+		.jitcnt = tx32->jitcnt,
+		.calcnt = tx32->calcnt,
+		.errcnt = tx32->errcnt,
+		.stbcnt = tx32->stbcnt,
+		.tai = tx32->tai,
+	};
+	int r = clock_adjtime(clock_id, &utx);
+	if (r<0) return r;
+	tx32->modes = utx.modes;
+	tx32->offset = utx.offset;
+	tx32->freq = utx.freq;
+	tx32->maxerror = utx.maxerror;
+	tx32->esterror = utx.esterror;
+	tx32->status = utx.status;
+	tx32->constant = utx.constant;
+	tx32->precision = utx.precision;
+	tx32->tolerance = utx.tolerance;
+	tx32->time.tv_sec = utx.time.tv_sec;
+	tx32->time.tv_usec = utx.time.tv_usec;
+	tx32->tick = utx.tick;
+	tx32->ppsfreq = utx.ppsfreq;
+	tx32->jitter = utx.jitter;
+	tx32->shift = utx.shift;
+	tx32->stabil = utx.stabil;
+	tx32->jitcnt = utx.jitcnt;
+	tx32->calcnt = utx.calcnt;
+	tx32->errcnt = utx.errcnt;
+	tx32->stbcnt = utx.stbcnt;
+	tx32->tai = utx.tai;
+	return r;
+}
diff --git a/compat/time32/clock_getres_time32.c b/compat/time32/clock_getres_time32.c
new file mode 100644
index 00000000..47a24c13
--- /dev/null
+++ b/compat/time32/clock_getres_time32.c
@@ -0,0 +1,13 @@
+#include "time32.h"
+#include <time.h>
+
+int __clock_getres_time32(clockid_t clk, struct timespec32 *ts32)
+{
+	struct timespec ts;
+	int r = clock_getres(clk, &ts);
+	if (!r && ts32) {
+		ts32->tv_sec = ts.tv_sec;
+		ts32->tv_nsec = ts.tv_nsec;
+	}
+	return r;
+}
diff --git a/compat/time32/clock_gettime32.c b/compat/time32/clock_gettime32.c
new file mode 100644
index 00000000..0cac7bbd
--- /dev/null
+++ b/compat/time32/clock_gettime32.c
@@ -0,0 +1,18 @@
+#include "time32.h"
+#include <time.h>
+#include <errno.h>
+#include <stdint.h>
+
+int __clock_gettime32(clockid_t clk, struct timespec32 *ts32)
+{
+	struct timespec ts;
+	int r = clock_gettime(clk, &ts);
+	if (r) return r;
+	if (ts.tv_sec < INT32_MIN || ts.tv_sec > INT32_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+	ts32->tv_sec = ts.tv_sec;
+	ts32->tv_nsec = ts.tv_nsec;
+	return 0;
+}
diff --git a/compat/time32/clock_nanosleep_time32.c b/compat/time32/clock_nanosleep_time32.c
new file mode 100644
index 00000000..91ef067d
--- /dev/null
+++ b/compat/time32/clock_nanosleep_time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include <time.h>
+#include <errno.h>
+
+int __clock_nanosleep_time32(clockid_t clk, int flags, const struct timespec32 *req32, struct timespec32 *rem32)
+{
+	struct timespec rem;
+	int ret = clock_nanosleep(clk, flags, (&(struct timespec){
+		.tv_sec = req32->tv_sec, .tv_nsec = req32->tv_nsec}), &rem);
+	if (ret==EINTR && rem32 && !(flags & TIMER_ABSTIME)) {
+		rem32->tv_sec = rem.tv_sec;
+		rem32->tv_nsec = rem.tv_nsec;
+	}
+	return ret;
+}
diff --git a/compat/time32/clock_settime32.c b/compat/time32/clock_settime32.c
new file mode 100644
index 00000000..7ca4f0e9
--- /dev/null
+++ b/compat/time32/clock_settime32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+
+int __clock_settime32(clockid_t clk, const struct timespec32 *ts32)
+{
+	return clock_settime(clk, (&(struct timespec){
+		.tv_sec = ts32->tv_sec,
+		.tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/cnd_timedwait_time32.c b/compat/time32/cnd_timedwait_time32.c
new file mode 100644
index 00000000..314251d1
--- /dev/null
+++ b/compat/time32/cnd_timedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <threads.h>
+
+int __cnd_timedwait_time32(cnd_t *restrict c, mtx_t *restrict m, const struct timespec32 *restrict ts32)
+{
+	return cnd_timedwait(c, m, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/compat/time32/ctime32.c b/compat/time32/ctime32.c
new file mode 100644
index 00000000..a057274e
--- /dev/null
+++ b/compat/time32/ctime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include <time.h>
+
+char *__ctime32(time32_t *t)
+{
+	return ctime(&(time_t){*t});
+}
diff --git a/compat/time32/ctime32_r.c b/compat/time32/ctime32_r.c
new file mode 100644
index 00000000..e1ad2e28
--- /dev/null
+++ b/compat/time32/ctime32_r.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include <time.h>
+
+char *__ctime32_r(time32_t *t, char *buf)
+{
+	return ctime_r(&(time_t){*t}, buf);
+}
diff --git a/compat/time32/difftime32.c b/compat/time32/difftime32.c
new file mode 100644
index 00000000..15c65709
--- /dev/null
+++ b/compat/time32/difftime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include <time.h>
+
+double __difftime32(time32_t t1, time_t t2)
+{
+	return difftime(t1, t2);
+}
diff --git a/compat/time32/fstat_time32.c b/compat/time32/fstat_time32.c
new file mode 100644
index 00000000..3e084398
--- /dev/null
+++ b/compat/time32/fstat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include <time.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+struct stat32;
+
+int __fstat_time32(int fd, struct stat32 *restrict st32)
+{
+	struct stat st;
+	int r = fstat(fd, &st);
+	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+	return r;
+}
+
+weak_alias(fstat, fstat64);
diff --git a/compat/time32/fstatat_time32.c b/compat/time32/fstatat_time32.c
new file mode 100644
index 00000000..85dcb008
--- /dev/null
+++ b/compat/time32/fstatat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include <time.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+struct stat32;
+
+int __fstatat_time32(int fd, const char *restrict path, struct stat32 *restrict st32, int flag)
+{
+	struct stat st;
+	int r = fstatat(fd, path, &st, flag);
+	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+	return r;
+}
+
+weak_alias(fstatat, fstatat64);
diff --git a/compat/time32/ftime32.c b/compat/time32/ftime32.c
new file mode 100644
index 00000000..166a6dae
--- /dev/null
+++ b/compat/time32/ftime32.c
@@ -0,0 +1,25 @@
+#include "time32.h"
+#include <sys/timeb.h>
+#include <errno.h>
+#include <stdint.h>
+
+struct timeb32 {
+	int32_t time;
+	unsigned short millitm;
+	short timezone, dstflag;
+};
+
+int __ftime32(struct timeb32 *tp)
+{
+	struct timeb tb;
+	if (ftime(&tb) < 0) return -1;
+	if (tb.time < INT32_MIN || tb.time > INT32_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+	tp->time = tb.time;
+	tp->millitm = tb.millitm;
+	tp->timezone = tb.timezone;
+	tp->dstflag = tb.dstflag;
+	return 0;
+}
diff --git a/compat/time32/futimens_time32.c b/compat/time32/futimens_time32.c
new file mode 100644
index 00000000..7856f176
--- /dev/null
+++ b/compat/time32/futimens_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/stat.h>
+
+int __futimens_time32(int fd, const struct timespec32 *times32)
+{
+	return futimens(fd, !times32 ? 0 : ((struct timespec[2]){
+		{.tv_sec = times32[0].tv_sec,.tv_nsec = times32[0].tv_nsec},
+		{.tv_sec = times32[1].tv_sec,.tv_nsec = times32[1].tv_nsec}}));
+}
diff --git a/compat/time32/futimes_time32.c b/compat/time32/futimes_time32.c
new file mode 100644
index 00000000..f29533f1
--- /dev/null
+++ b/compat/time32/futimes_time32.c
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+int __futimes_time32(int fd, const struct timeval32 times32[2])
+{
+	return futimes(fd, !times32 ? 0 : ((struct timeval[2]){
+		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/compat/time32/futimesat_time32.c b/compat/time32/futimesat_time32.c
new file mode 100644
index 00000000..5a1295bd
--- /dev/null
+++ b/compat/time32/futimesat_time32.c
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+int __futimesat_time32(int dirfd, const char *pathname, const struct timeval32 times32[2])
+{
+	return futimesat(dirfd, pathname, !times32 ? 0 : ((struct timeval[2]){
+		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/compat/time32/getitimer_time32.c b/compat/time32/getitimer_time32.c
new file mode 100644
index 00000000..4bac4bf5
--- /dev/null
+++ b/compat/time32/getitimer_time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+
+int __getitimer_time32(int which, struct itimerval32 *old32)
+{
+	struct itimerval old;
+	int r = getitimer(which, &old);
+	if (r) return r;
+	old32->it_interval.tv_sec = old.it_interval.tv_sec;
+	old32->it_interval.tv_usec = old.it_interval.tv_usec;
+	old32->it_value.tv_sec = old.it_value.tv_sec;
+	old32->it_value.tv_usec = old.it_value.tv_usec;
+	return 0;
+}
diff --git a/compat/time32/getrusage_time32.c b/compat/time32/getrusage_time32.c
new file mode 100644
index 00000000..d7487dee
--- /dev/null
+++ b/compat/time32/getrusage_time32.c
@@ -0,0 +1,39 @@
+#include "time32.h"
+#include <string.h>
+#include <stddef.h>
+#include <sys/resource.h>
+
+struct compat_rusage {
+	struct timeval32 ru_utime;
+	struct timeval32 ru_stime;
+	long	ru_maxrss;
+	long	ru_ixrss;
+	long	ru_idrss;
+	long	ru_isrss;
+	long	ru_minflt;
+	long	ru_majflt;
+	long	ru_nswap;
+	long	ru_inblock;
+	long	ru_oublock;
+	long	ru_msgsnd;
+	long	ru_msgrcv;
+	long	ru_nsignals;
+	long	ru_nvcsw;
+	long	ru_nivcsw;
+};
+
+int __getrusage_time32(int who, struct compat_rusage *usage)
+{
+	struct rusage ru;
+	int r = getrusage(who, &ru);
+	if (!r) {
+		usage->ru_utime.tv_sec = ru.ru_utime.tv_sec;
+		usage->ru_utime.tv_usec = ru.ru_utime.tv_usec;
+		usage->ru_stime.tv_sec = ru.ru_stime.tv_sec;
+		usage->ru_stime.tv_usec = ru.ru_stime.tv_usec;
+		memcpy(&usage->ru_maxrss, &ru.ru_maxrss,
+			sizeof(struct compat_rusage) -
+			offsetof(struct compat_rusage, ru_maxrss));
+	}
+	return r;
+}
diff --git a/compat/time32/gettimeofday_time32.c b/compat/time32/gettimeofday_time32.c
new file mode 100644
index 00000000..1f3ce68e
--- /dev/null
+++ b/compat/time32/gettimeofday_time32.c
@@ -0,0 +1,19 @@
+#include "time32.h"
+#include <sys/time.h>
+#include <errno.h>
+#include <stdint.h>
+
+int __gettimeofday_time32(struct timeval32 *tv32, void *tz)
+{
+	struct timeval tv;
+	if (!tv32) return 0;
+	int r = gettimeofday(&tv, 0);
+	if (r) return r;
+	if (tv.tv_sec < INT32_MIN || tv.tv_sec > INT32_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+	tv32->tv_sec = tv.tv_sec;
+	tv32->tv_usec = tv.tv_usec;
+	return 0;
+}
diff --git a/compat/time32/gmtime32.c b/compat/time32/gmtime32.c
new file mode 100644
index 00000000..963f0e05
--- /dev/null
+++ b/compat/time32/gmtime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include <time.h>
+
+struct tm *__gmtime32(time32_t *t)
+{
+	return gmtime(&(time_t){*t});
+}
diff --git a/compat/time32/gmtime32_r.c b/compat/time32/gmtime32_r.c
new file mode 100644
index 00000000..7d72bfb3
--- /dev/null
+++ b/compat/time32/gmtime32_r.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include <time.h>
+
+struct tm *__gmtime32_r(time32_t *t, struct tm *tm)
+{
+	return gmtime_r(&(time_t){*t}, tm);
+}
diff --git a/compat/time32/localtime32.c b/compat/time32/localtime32.c
new file mode 100644
index 00000000..96bc3034
--- /dev/null
+++ b/compat/time32/localtime32.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include <time.h>
+
+struct tm *__localtime32(time32_t *t)
+{
+	return localtime(&(time_t){*t});
+}
diff --git a/compat/time32/localtime32_r.c b/compat/time32/localtime32_r.c
new file mode 100644
index 00000000..633ec829
--- /dev/null
+++ b/compat/time32/localtime32_r.c
@@ -0,0 +1,7 @@
+#include "time32.h"
+#include <time.h>
+
+struct tm *__localtime32_r(time32_t *t, struct tm *tm)
+{
+	return localtime_r(&(time_t){*t}, tm);
+}
diff --git a/compat/time32/lstat_time32.c b/compat/time32/lstat_time32.c
new file mode 100644
index 00000000..c1257a14
--- /dev/null
+++ b/compat/time32/lstat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include <time.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+struct stat32;
+
+int __lstat_time32(const char *restrict path, struct stat32 *restrict st32)
+{
+	struct stat st;
+	int r = lstat(path, &st);
+	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+	return r;
+}
+
+weak_alias(lstat, lstat64);
diff --git a/compat/time32/lutimes_time32.c b/compat/time32/lutimes_time32.c
new file mode 100644
index 00000000..7f75cd4a
--- /dev/null
+++ b/compat/time32/lutimes_time32.c
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+int __lutimes_time32(const char *path, const struct timeval32 times32[2])
+{
+	return lutimes(path, !times32 ? 0 : ((struct timeval[2]){
+		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/compat/time32/mktime32.c b/compat/time32/mktime32.c
new file mode 100644
index 00000000..e6f15d51
--- /dev/null
+++ b/compat/time32/mktime32.c
@@ -0,0 +1,16 @@
+#include "time32.h"
+#include <time.h>
+#include <errno.h>
+#include <stdint.h>
+
+time32_t __mktime32(struct tm *tm)
+{
+	struct tm tmp = *tm;
+	time_t t = mktime(&tmp);
+	if (t < INT32_MIN || t > INT32_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+	*tm = tmp;
+	return t;
+}
diff --git a/compat/time32/mq_timedreceive_time32.c b/compat/time32/mq_timedreceive_time32.c
new file mode 100644
index 00000000..211cea4b
--- /dev/null
+++ b/compat/time32/mq_timedreceive_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <mqueue.h>
+#include <time.h>
+
+ssize_t __mq_timedreceive_time32(mqd_t mqd, char *restrict msg, size_t len, unsigned *restrict prio, const struct timespec32 *restrict ts32)
+{
+	return mq_timedreceive(mqd, msg, len, prio, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/compat/time32/mq_timedsend_time32.c b/compat/time32/mq_timedsend_time32.c
new file mode 100644
index 00000000..93b697a7
--- /dev/null
+++ b/compat/time32/mq_timedsend_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <mqueue.h>
+#include <time.h>
+
+int __mq_timedsend_time32(mqd_t mqd, const char *msg, size_t len, unsigned prio, const struct timespec32 *ts32)
+{
+	return mq_timedsend(mqd, msg, len, prio, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/compat/time32/mtx_timedlock_time32.c b/compat/time32/mtx_timedlock_time32.c
new file mode 100644
index 00000000..a01f09b8
--- /dev/null
+++ b/compat/time32/mtx_timedlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <threads.h>
+
+int __mtx_timedlock_time32(mtx_t *restrict m, const struct timespec32 *restrict ts32)
+{
+	return mtx_timedlock(m, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/nanosleep_time32.c b/compat/time32/nanosleep_time32.c
new file mode 100644
index 00000000..ea6bdd81
--- /dev/null
+++ b/compat/time32/nanosleep_time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include <time.h>
+#include <errno.h>
+
+int __nanosleep_time32(const struct timespec32 *req32, struct timespec32 *rem32)
+{
+	struct timespec rem;
+	int ret = nanosleep((&(struct timespec){
+		.tv_sec = req32->tv_sec, .tv_nsec = req32->tv_nsec}), &rem);
+	if (ret<0 && errno==EINTR && rem32) {
+		rem32->tv_sec = rem.tv_sec;
+		rem32->tv_nsec = rem.tv_nsec;
+	}
+	return ret;
+}
diff --git a/compat/time32/ppoll_time32.c b/compat/time32/ppoll_time32.c
new file mode 100644
index 00000000..43b4b0df
--- /dev/null
+++ b/compat/time32/ppoll_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#define _GNU_SOURCE
+#include <time.h>
+#include <poll.h>
+
+int __ppoll_time32(struct pollfd *fds, nfds_t n, const struct timespec32 *ts32, const sigset_t *mask)
+{
+	return ppoll(fds, n, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
+}
diff --git a/compat/time32/pselect_time32.c b/compat/time32/pselect_time32.c
new file mode 100644
index 00000000..ecaa8f86
--- /dev/null
+++ b/compat/time32/pselect_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/select.h>
+
+int __pselect_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, const struct timespec32 *restrict ts32, const sigset_t *restrict mask)
+{
+	return pselect(n, rfds, wfds, efds, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}), mask);
+}
diff --git a/compat/time32/pthread_cond_timedwait_time32.c b/compat/time32/pthread_cond_timedwait_time32.c
new file mode 100644
index 00000000..fba1f2a9
--- /dev/null
+++ b/compat/time32/pthread_cond_timedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <pthread.h>
+
+int __pthread_cond_timedwait_time32(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec32 *restrict ts32)
+{
+	return pthread_cond_timedwait(c, m, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/pthread_mutex_timedlock_time32.c b/compat/time32/pthread_mutex_timedlock_time32.c
new file mode 100644
index 00000000..2d29602c
--- /dev/null
+++ b/compat/time32/pthread_mutex_timedlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <pthread.h>
+
+int __pthread_mutex_timedlock_time32(pthread_mutex_t *restrict m, const struct timespec32 *restrict ts32)
+{
+	return pthread_mutex_timedlock(m, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/pthread_rwlock_timedrdlock_time32.c b/compat/time32/pthread_rwlock_timedrdlock_time32.c
new file mode 100644
index 00000000..33df27a4
--- /dev/null
+++ b/compat/time32/pthread_rwlock_timedrdlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <pthread.h>
+
+int __pthread_rwlock_timedrdlock_time32(pthread_rwlock_t *restrict rw, const struct timespec32 *restrict ts32)
+{
+	return pthread_rwlock_timedrdlock(rw, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/pthread_rwlock_timedwrlock_time32.c b/compat/time32/pthread_rwlock_timedwrlock_time32.c
new file mode 100644
index 00000000..99f24f73
--- /dev/null
+++ b/compat/time32/pthread_rwlock_timedwrlock_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <pthread.h>
+
+int __pthread_rwlock_timedwrlock_time32(pthread_rwlock_t *restrict rw, const struct timespec32 *restrict ts32)
+{
+	return pthread_rwlock_timedwrlock(rw, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/pthread_timedjoin_np_time32.c b/compat/time32/pthread_timedjoin_np_time32.c
new file mode 100644
index 00000000..99a26bc6
--- /dev/null
+++ b/compat/time32/pthread_timedjoin_np_time32.c
@@ -0,0 +1,10 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include <time.h>
+#include <pthread.h>
+
+int __pthread_timedjoin_np_time32(pthread_t t, void **res, const struct timespec *at32)
+{
+	return pthread_timedjoin_np(t, res, !at32 ? 0 : (&(struct timespec){
+		.tv_sec = at32->tv_sec, .tv_nsec = at32->tv_nsec}));
+}
diff --git a/compat/time32/recvmmsg_time32.c b/compat/time32/recvmmsg_time32.c
new file mode 100644
index 00000000..acf1cfb8
--- /dev/null
+++ b/compat/time32/recvmmsg_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#define _GNU_SOURCE
+#include <time.h>
+#include <sys/socket.h>
+
+int __recvmmsg_time32(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags, struct timespec32 *ts32)
+{
+	return recvmmsg(fd, msgvec, vlen, flags, ts32 ? (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
+}
diff --git a/compat/time32/sched_rr_get_interval_time32.c b/compat/time32/sched_rr_get_interval_time32.c
new file mode 100644
index 00000000..36cbbaca
--- /dev/null
+++ b/compat/time32/sched_rr_get_interval_time32.c
@@ -0,0 +1,13 @@
+#include "time32.h"
+#include <time.h>
+#include <sched.h>
+
+int __sched_rr_get_interval_time32(pid_t pid, struct timespec32 *ts32)
+{
+	struct timespec ts;
+	int r = sched_rr_get_interval(pid, &ts);
+	if (r) return r;
+	ts32->tv_sec = ts.tv_sec;
+	ts32->tv_nsec = ts.tv_nsec;
+	return r;
+}
diff --git a/compat/time32/select_time32.c b/compat/time32/select_time32.c
new file mode 100644
index 00000000..2d8df9ac
--- /dev/null
+++ b/compat/time32/select_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+int __select_time32(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval32 *restrict tv32)
+{
+	return select(n, rfds, wfds, efds, !tv32 ? 0 : (&(struct timeval){
+		.tv_sec = tv32->tv_sec, .tv_usec = tv32->tv_usec}));
+}
diff --git a/compat/time32/sem_timedwait_time32.c b/compat/time32/sem_timedwait_time32.c
new file mode 100644
index 00000000..c3469f9b
--- /dev/null
+++ b/compat/time32/sem_timedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <semaphore.h>
+
+int __sem_timedwait_time32(sem_t *sem, const struct timespec32 *restrict ts32)
+{
+	return sem_timedwait(sem, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/semtimedop_time32.c b/compat/time32/semtimedop_time32.c
new file mode 100644
index 00000000..34ec5281
--- /dev/null
+++ b/compat/time32/semtimedop_time32.c
@@ -0,0 +1,10 @@
+#include "time32.h"
+#define _GNU_SOURCE
+#include <sys/sem.h>
+#include <time.h>
+
+int __semtimedop_time32(int id, struct sembuf *buf, size_t n, const struct timespec32 *ts32)
+{
+	return semtimedop(id, buf, n, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/setitimer_time32.c b/compat/time32/setitimer_time32.c
new file mode 100644
index 00000000..4651dacb
--- /dev/null
+++ b/compat/time32/setitimer_time32.c
@@ -0,0 +1,23 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+
+int __setitimer_time32(int which, const struct itimerval32 *restrict new32, struct itimerval32 *restrict old32)
+{
+	struct itimerval old;
+	int r = setitimer(which, (&(struct itimerval){
+		.it_interval.tv_sec = new32->it_interval.tv_sec,
+		.it_interval.tv_usec = new32->it_interval.tv_usec,
+		.it_value.tv_sec = new32->it_value.tv_sec,
+		.it_value.tv_usec = new32->it_value.tv_usec}), &old);
+	if (r) return r;
+	/* The above call has already committed to success by changing the
+	 * timer setting, so we can't fail on out-of-range old value.
+	 * Since these are relative times, values large enough to overflow
+	 * don't make sense anyway. */
+	old32->it_interval.tv_sec = old.it_interval.tv_sec;
+	old32->it_interval.tv_usec = old.it_interval.tv_usec;
+	old32->it_value.tv_sec = old.it_value.tv_sec;
+	old32->it_value.tv_usec = old.it_value.tv_usec;
+	return 0;
+}
diff --git a/compat/time32/settimeofday_time32.c b/compat/time32/settimeofday_time32.c
new file mode 100644
index 00000000..09e625cb
--- /dev/null
+++ b/compat/time32/settimeofday_time32.c
@@ -0,0 +1,10 @@
+#define _BSD_SOURCE
+#include "time32.h"
+#include <sys/time.h>
+
+int __settimeofday_time32(const struct timeval32 *tv32, const void *tz)
+{
+	return settimeofday(!tv32 ? 0 : (&(struct timeval){
+		.tv_sec = tv32->tv_sec,
+		.tv_usec = tv32->tv_usec}), 0);
+}
diff --git a/compat/time32/sigtimedwait_time32.c b/compat/time32/sigtimedwait_time32.c
new file mode 100644
index 00000000..6b3aa39c
--- /dev/null
+++ b/compat/time32/sigtimedwait_time32.c
@@ -0,0 +1,9 @@
+#include "time32.h"
+#include <time.h>
+#include <signal.h>
+
+int __sigtimedwait_time32(const sigset_t *restrict set, siginfo_t *restrict si, const struct timespec32 *restrict ts32)
+{
+	return sigtimedwait(set, si, !ts32 ? 0 : (&(struct timespec){
+		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}));
+}
diff --git a/compat/time32/stat_time32.c b/compat/time32/stat_time32.c
new file mode 100644
index 00000000..8c6121da
--- /dev/null
+++ b/compat/time32/stat_time32.c
@@ -0,0 +1,17 @@
+#include "time32.h"
+#include <time.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+struct stat32;
+
+int __stat_time32(const char *restrict path, struct stat32 *restrict st32)
+{
+	struct stat st;
+	int r = stat(path, &st);
+	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
+	return r;
+}
+
+weak_alias(stat, stat64);
diff --git a/compat/time32/stime32.c b/compat/time32/stime32.c
new file mode 100644
index 00000000..cc76364d
--- /dev/null
+++ b/compat/time32/stime32.c
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include <time.h>
+
+int __stime32(const time32_t *t)
+{
+	return stime(&(time_t){*t});
+}
diff --git a/compat/time32/thrd_sleep_time32.c b/compat/time32/thrd_sleep_time32.c
new file mode 100644
index 00000000..59088001
--- /dev/null
+++ b/compat/time32/thrd_sleep_time32.c
@@ -0,0 +1,16 @@
+#include "time32.h"
+#include <time.h>
+#include <threads.h>
+#include <errno.h>
+
+int __thrd_sleep_time32(const struct timespec32 *req32, struct timespec32 *rem32)
+{
+	struct timespec rem;
+	int ret = thrd_sleep((&(struct timespec){
+		.tv_sec = req32->tv_sec, .tv_nsec = req32->tv_nsec}), &rem);
+	if (ret<0 && errno==EINTR && rem32) {
+		rem32->tv_sec = rem.tv_sec;
+		rem32->tv_nsec = rem.tv_nsec;
+	}
+	return ret;
+}
diff --git a/compat/time32/time32.c b/compat/time32/time32.c
new file mode 100644
index 00000000..4b8fac1c
--- /dev/null
+++ b/compat/time32/time32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include <time.h>
+#include <errno.h>
+#include <stdint.h>
+
+time32_t __time32(time32_t *p)
+{
+	time_t t = time(0);
+	if (t < INT32_MIN || t > INT32_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+	if (p) *p = t;
+	return t;
+}
diff --git a/compat/time32/time32.h b/compat/time32/time32.h
new file mode 100644
index 00000000..fdec17c3
--- /dev/null
+++ b/compat/time32/time32.h
@@ -0,0 +1,91 @@
+#ifndef TIME32_H
+#define TIME32_H
+
+#include <sys/types.h>
+
+typedef long time32_t;
+
+struct timeval32 {
+	long tv_sec;
+	long tv_usec;
+};
+
+struct itimerval32 {
+	struct timeval32 it_interval;
+	struct timeval32 it_value;
+};
+
+struct timespec32 {
+	long tv_sec;
+	long tv_nsec;
+};
+
+struct itimerspec32 {
+	struct timespec32 it_interval;
+	struct timespec32 it_value;
+};
+
+int __adjtime32() __asm__("adjtime");
+int __adjtimex_time32() __asm__("adjtimex");
+int __aio_suspend_time32() __asm__("aio_suspend");
+int __clock_adjtime32() __asm__("clock_adjtime");
+int __clock_getres_time32() __asm__("clock_getres");
+int __clock_gettime32() __asm__("clock_gettime");
+int __clock_nanosleep_time32() __asm__("clock_nanosleep");
+int __clock_settime32() __asm__("clock_settime");
+int __cnd_timedwait_time32() __asm__("cnd_timedwait");
+char *__ctime32() __asm__("ctime");
+char *__ctime32_r() __asm__("ctime_r");
+double __difftime32() __asm__("difftime");
+int __fstat_time32() __asm__("fstat");
+int __fstatat_time32() __asm__("fstatat");
+int __ftime32() __asm__("ftime");
+int __futimens_time32() __asm__("futimens");
+int __futimes_time32() __asm__("futimes");
+int __futimesat_time32() __asm__("futimesat");
+int __getitimer_time32() __asm__("getitimer");
+int __getrusage_time32() __asm__("getrusage");
+int __gettimeofday_time32() __asm__("gettimeofday");
+struct tm *__gmtime32() __asm__("gmtime");
+struct tm *__gmtime32_r() __asm__("gmtime_r");
+struct tm *__localtime32() __asm__("localtime");
+struct tm *__localtime32_r() __asm__("localtime_r");
+int __lstat_time32() __asm__("lstat");
+int __lutimes_time32() __asm__("lutimes");
+time32_t __mktime32() __asm__("mktime");
+ssize_t __mq_timedreceive_time32() __asm__("mq_timedreceive");
+int __mq_timedsend_time32() __asm__("mq_timedsend");
+int __mtx_timedlock_time32() __asm__("mtx_timedlock");
+int __nanosleep_time32() __asm__("nanosleep");
+int __ppoll_time32() __asm__("ppoll");
+int __pselect_time32() __asm__("pselect");
+int __pthread_cond_timedwait_time32() __asm__("pthread_cond_timedwait");
+int __pthread_mutex_timedlock_time32() __asm__("pthread_mutex_timedlock");
+int __pthread_rwlock_timedrdlock_time32() __asm__("pthread_rwlock_timedrdlock");
+int __pthread_rwlock_timedwrlock_time32() __asm__("pthread_rwlock_timedwrlock");
+int __pthread_timedjoin_np_time32() __asm__("pthread_timedjoin_np");
+int __recvmmsg_time32() __asm__("recvmmsg");
+int __sched_rr_get_interval_time32() __asm__("sched_rr_get_interval");
+int __select_time32() __asm__("select");
+int __sem_timedwait_time32() __asm__("sem_timedwait");
+int __semtimedop_time32() __asm__("semtimedop");
+int __setitimer_time32() __asm__("setitimer");
+int __settimeofday_time32() __asm__("settimeofday");
+int __sigtimedwait_time32() __asm__("sigtimedwait");
+int __stat_time32() __asm__("stat");
+int __stime32() __asm__("stime");
+int __thrd_sleep_time32() __asm__("thrd_sleep");
+time32_t __time32() __asm__("time");
+time32_t __time32gm() __asm__("timegm");
+int __timer_gettime32() __asm__("timer_gettime");
+int __timer_settime32() __asm__("timer_settime");
+int __timerfd_gettime32() __asm__("timerfd_gettime");
+int __timerfd_settime32() __asm__("timerfd_settime");
+int __timespec_get_time32() __asm__("timespec_get");
+int __utime_time32() __asm__("utime");
+int __utimensat_time32() __asm__("utimensat");
+int __utimes_time32() __asm__("utimes");
+pid_t __wait3_time32() __asm__("wait3");
+pid_t __wait4_time32() __asm__("wait4");
+
+#endif
diff --git a/compat/time32/time32gm.c b/compat/time32/time32gm.c
new file mode 100644
index 00000000..60d68fbf
--- /dev/null
+++ b/compat/time32/time32gm.c
@@ -0,0 +1,15 @@
+#define _GNU_SOURCE
+#include "time32.h"
+#include <time.h>
+#include <errno.h>
+#include <stdint.h>
+
+time32_t __time32gm(struct tm *tm)
+{
+	time_t t = timegm(tm);
+	if (t < INT32_MIN || t > INT32_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+	return t;
+}
diff --git a/compat/time32/timer_gettime32.c b/compat/time32/timer_gettime32.c
new file mode 100644
index 00000000..b4184cc2
--- /dev/null
+++ b/compat/time32/timer_gettime32.c
@@ -0,0 +1,15 @@
+#include "time32.h"
+#include <time.h>
+
+int __timer_gettime32(timer_t t, struct itimerspec32 *val32)
+{
+	struct itimerspec old;
+	int r = timer_gettime(t, &old);
+	if (r) return r;
+	/* No range checking for consistency with settime */
+	val32->it_interval.tv_sec = old.it_interval.tv_sec;
+	val32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+	val32->it_value.tv_sec = old.it_value.tv_sec;
+	val32->it_value.tv_nsec = old.it_value.tv_nsec;
+	return 0;
+}
diff --git a/compat/time32/timer_settime32.c b/compat/time32/timer_settime32.c
new file mode 100644
index 00000000..a447e7d4
--- /dev/null
+++ b/compat/time32/timer_settime32.c
@@ -0,0 +1,25 @@
+#include "time32.h"
+#include <time.h>
+
+int __timer_settime32(timer_t t, int flags, const struct itimerspec32 *restrict val32, struct itimerspec32 *restrict old32)
+{
+	struct itimerspec old;
+	int r = timer_settime(t, flags, (&(struct itimerspec){
+		.it_interval.tv_sec = val32->it_interval.tv_sec,
+		.it_interval.tv_nsec = val32->it_interval.tv_nsec,
+		.it_value.tv_sec = val32->it_value.tv_sec,
+		.it_value.tv_nsec = val32->it_value.tv_nsec}),
+		old32 ? &old : 0);
+	if (r) return r;
+	/* The above call has already committed to success by changing the
+	 * timer setting, so we can't fail on out-of-range old value.
+	 * Since these are relative times, values large enough to overflow
+	 * don't make sense anyway. */
+	if (old32) {
+		old32->it_interval.tv_sec = old.it_interval.tv_sec;
+		old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+		old32->it_value.tv_sec = old.it_value.tv_sec;
+		old32->it_value.tv_nsec = old.it_value.tv_nsec;
+	}
+	return 0;
+}
diff --git a/compat/time32/timerfd_gettime32.c b/compat/time32/timerfd_gettime32.c
new file mode 100644
index 00000000..75e5435f
--- /dev/null
+++ b/compat/time32/timerfd_gettime32.c
@@ -0,0 +1,16 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/timerfd.h>
+
+int __timerfd_gettime32(int t, struct itimerspec32 *val32)
+{
+	struct itimerspec old;
+	int r = timerfd_gettime(t, &old);
+	if (r) return r;
+	/* No range checking for consistency with settime */
+	val32->it_interval.tv_sec = old.it_interval.tv_sec;
+	val32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+	val32->it_value.tv_sec = old.it_value.tv_sec;
+	val32->it_value.tv_nsec = old.it_value.tv_nsec;
+	return 0;
+}
diff --git a/compat/time32/timerfd_settime32.c b/compat/time32/timerfd_settime32.c
new file mode 100644
index 00000000..67830d34
--- /dev/null
+++ b/compat/time32/timerfd_settime32.c
@@ -0,0 +1,26 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/timerfd.h>
+
+int __timerfd_settime32(int t, int flags, const struct itimerspec32 *restrict val32, struct itimerspec32 *restrict old32)
+{
+	struct itimerspec old;
+	int r = timerfd_settime(t, flags, (&(struct itimerspec){
+		.it_interval.tv_sec = val32->it_interval.tv_sec,
+		.it_interval.tv_nsec = val32->it_interval.tv_nsec,
+		.it_value.tv_sec = val32->it_value.tv_sec,
+		.it_value.tv_nsec = val32->it_value.tv_nsec}),
+		old32 ? &old : 0);
+	if (r) return r;
+	/* The above call has already committed to success by changing the
+	 * timer setting, so we can't fail on out-of-range old value.
+	 * Since these are relative times, values large enough to overflow
+	 * don't make sense anyway. */
+	if (old32) {
+		old32->it_interval.tv_sec = old.it_interval.tv_sec;
+		old32->it_interval.tv_nsec = old.it_interval.tv_nsec;
+		old32->it_value.tv_sec = old.it_value.tv_sec;
+		old32->it_value.tv_nsec = old.it_value.tv_nsec;
+	}
+	return 0;
+}
diff --git a/compat/time32/timespec_get_time32.c b/compat/time32/timespec_get_time32.c
new file mode 100644
index 00000000..e9ca94cb
--- /dev/null
+++ b/compat/time32/timespec_get_time32.c
@@ -0,0 +1,18 @@
+#include "time32.h"
+#include <time.h>
+#include <errno.h>
+#include <stdint.h>
+
+int __timespec_get_time32(struct timespec32 *ts32, int base)
+{
+	struct timespec ts;
+	int r = timespec_get(&ts, base);
+	if (!r) return r;
+	if (ts.tv_sec < INT32_MIN || ts.tv_sec > INT32_MAX) {
+		errno = EOVERFLOW;
+		return 0;
+	}
+	ts32->tv_sec = ts.tv_sec;
+	ts32->tv_nsec = ts.tv_nsec;
+	return r;
+}
diff --git a/compat/time32/utime_time32.c b/compat/time32/utime_time32.c
new file mode 100644
index 00000000..65f11d46
--- /dev/null
+++ b/compat/time32/utime_time32.c
@@ -0,0 +1,14 @@
+#include "time32.h"
+#include <time.h>
+#include <utime.h>
+
+struct utimbuf32 {
+	time32_t actime;
+	time32_t modtime;
+};
+
+int __utime_time32(const char *path, const struct utimbuf32 *times32)
+{
+	return utime(path, !times32 ? 0 : (&(struct utimbuf){
+		.actime = times32->actime, .modtime = times32->modtime}));
+}
diff --git a/compat/time32/utimensat_time32.c b/compat/time32/utimensat_time32.c
new file mode 100644
index 00000000..c687b8d1
--- /dev/null
+++ b/compat/time32/utimensat_time32.c
@@ -0,0 +1,11 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/stat.h>
+
+int __utimensat_time32(int fd, const char *path, const struct timespec32 times32[2], int flags)
+{
+	return utimensat(fd, path, !times32 ? 0 : ((struct timespec[2]){
+		{.tv_sec = times32[0].tv_sec,.tv_nsec = times32[0].tv_nsec},
+		{.tv_sec = times32[1].tv_sec,.tv_nsec = times32[1].tv_nsec}}),
+		flags);
+}
diff --git a/compat/time32/utimes_time32.c b/compat/time32/utimes_time32.c
new file mode 100644
index 00000000..59248f62
--- /dev/null
+++ b/compat/time32/utimes_time32.c
@@ -0,0 +1,11 @@
+#include "time32.h"
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+int __utimes_time32(const char *path, const struct timeval32 times32[2])
+{
+	return utimes(path, !times32 ? 0 : ((struct timeval[2]){
+		{.tv_sec = times32[0].tv_sec,.tv_usec = times32[0].tv_usec},
+		{.tv_sec = times32[1].tv_sec,.tv_usec = times32[1].tv_usec}}));
+}
diff --git a/compat/time32/wait3_time32.c b/compat/time32/wait3_time32.c
new file mode 100644
index 00000000..8fe128ed
--- /dev/null
+++ b/compat/time32/wait3_time32.c
@@ -0,0 +1,40 @@
+#define _BSD_SOURCE
+#include "time32.h"
+#include <string.h>
+#include <stddef.h>
+#include <sys/wait.h>
+
+struct compat_rusage {
+	struct timeval32 ru_utime;
+	struct timeval32 ru_stime;
+	long	ru_maxrss;
+	long	ru_ixrss;
+	long	ru_idrss;
+	long	ru_isrss;
+	long	ru_minflt;
+	long	ru_majflt;
+	long	ru_nswap;
+	long	ru_inblock;
+	long	ru_oublock;
+	long	ru_msgsnd;
+	long	ru_msgrcv;
+	long	ru_nsignals;
+	long	ru_nvcsw;
+	long	ru_nivcsw;
+};
+
+pid_t __wait3_time32(int *status, int options, struct compat_rusage *usage)
+{
+	struct rusage ru;
+	int r = wait3(status, options, usage ? &ru : 0);
+	if (!r && usage) {
+		usage->ru_utime.tv_sec = ru.ru_utime.tv_sec;
+		usage->ru_utime.tv_usec = ru.ru_utime.tv_usec;
+		usage->ru_stime.tv_sec = ru.ru_stime.tv_sec;
+		usage->ru_stime.tv_usec = ru.ru_stime.tv_usec;
+		memcpy(&usage->ru_maxrss, &ru.ru_maxrss,
+			sizeof(struct compat_rusage) -
+			offsetof(struct compat_rusage, ru_maxrss));
+	}
+	return r;
+}
diff --git a/compat/time32/wait4_time32.c b/compat/time32/wait4_time32.c
new file mode 100644
index 00000000..918548e7
--- /dev/null
+++ b/compat/time32/wait4_time32.c
@@ -0,0 +1,40 @@
+#define _BSD_SOURCE
+#include "time32.h"
+#include <string.h>
+#include <stddef.h>
+#include <sys/wait.h>
+
+struct compat_rusage {
+	struct timeval32 ru_utime;
+	struct timeval32 ru_stime;
+	long	ru_maxrss;
+	long	ru_ixrss;
+	long	ru_idrss;
+	long	ru_isrss;
+	long	ru_minflt;
+	long	ru_majflt;
+	long	ru_nswap;
+	long	ru_inblock;
+	long	ru_oublock;
+	long	ru_msgsnd;
+	long	ru_msgrcv;
+	long	ru_nsignals;
+	long	ru_nvcsw;
+	long	ru_nivcsw;
+};
+
+pid_t __wait4_time32(pid_t pid, int *status, int options, struct compat_rusage *usage)
+{
+	struct rusage ru;
+	int r = wait4(pid, status, options, usage ? &ru : 0);
+	if (!r && usage) {
+		usage->ru_utime.tv_sec = ru.ru_utime.tv_sec;
+		usage->ru_utime.tv_usec = ru.ru_utime.tv_usec;
+		usage->ru_stime.tv_sec = ru.ru_stime.tv_sec;
+		usage->ru_stime.tv_usec = ru.ru_stime.tv_usec;
+		memcpy(&usage->ru_maxrss, &ru.ru_maxrss,
+			sizeof(struct compat_rusage) -
+			offsetof(struct compat_rusage, ru_maxrss));
+	}
+	return r;
+}
-- 
2.21.0


[-- Attachment #7: 0006-add-time64-redirect-for-and-redirecting-implementati.patch --]
[-- Type: text/plain, Size: 2360 bytes --]

From ca6ef98295c1d3476b3adbdc2c4887c812104130 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Fri, 9 Aug 2019 15:26:23 -0400
Subject: [PATCH 06/15] add time64 redirect for, and redirecting implementation
 of, dlsym

if symbols are being redirected to provide the new time64 ABI, dlsym
must perform matching redirections; otherwise, it would poke a hole in
the magic and return pointers to functions that are not safe to call
from a caller using time64 types.

rather than duplicating a table of redirections, use the time64
symbols present in libc's symbol table to derive the decision for
whether a particular symbol needs to be redirected.
---
 include/dlfcn.h |  4 ++++
 ldso/dynlink.c  | 27 +++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/include/dlfcn.h b/include/dlfcn.h
index 78fb0733..13ab71dd 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -35,6 +35,10 @@ int dladdr(const void *, Dl_info *);
 int dlinfo(void *, int, void *);
 #endif
 
+#if _REDIR_TIME64
+__REDIR(dlsym, __dlsym_time64);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 7ac0bf75..7810356b 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -2237,6 +2237,33 @@ hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra
 	return res;
 }
 
+hidden void *__dlsym_redir_time64(void *restrict p, const char *restrict s, void *restrict ra)
+{
+#if _REDIR_TIME64
+	const char *suffix, *suffix2 = "";
+	char redir[36];
+
+	/* Map the symbol name to a time64 version of itself according to the
+	 * pattern used for naming the redirected time64 symbols. */
+	size_t l = strnlen(s, sizeof redir);
+	if (l<4 || l==sizeof redir) goto no_redir;
+	if (s[l-2]=='_' && s[l-1]=='r') {
+		l -= 2;
+		suffix2 = s+l;
+	}
+	if (l<4) goto no_redir;
+	if (!strcmp(s+l-4, "time")) suffix = "64";
+	else suffix = "_time64";
+
+	/* Use the presence of the remapped symbol name in libc to determine
+	 * whether it's one that requires time64 redirection; replace if so. */
+	snprintf(redir, sizeof redir, "__%.*s%s%s", (int)l, s, suffix, suffix2);
+	if (find_sym(&ldso, redir, 1).sym) s = redir;
+no_redir:
+#endif
+	return __dlsym(p, s, ra);
+}
+
 int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data)
 {
 	struct dso *current;
-- 
2.21.0


[-- Attachment #8: 0007-add-__dlsym_time64-asm-entry-point-for-all-legacy-32.patch --]
[-- Type: text/plain, Size: 3614 bytes --]

From 35686a6573c0bfd5930248424cc6fb73bfd6df25 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Sun, 20 Oct 2019 14:32:20 -0400
Subject: [PATCH 07/15] add __dlsym_time64 asm entry point for all
 legacy-32bit-time_t archs

---
 src/ldso/arm/dlsym_time64.S        | 3 +++
 src/ldso/i386/dlsym_time64.S       | 3 +++
 src/ldso/m68k/dlsym_time64.S       | 3 +++
 src/ldso/microblaze/dlsym_time64.S | 3 +++
 src/ldso/mips/dlsym_time64.S       | 3 +++
 src/ldso/mipsn32/dlsym_time64.S    | 3 +++
 src/ldso/or1k/dlsym_time64.S       | 3 +++
 src/ldso/powerpc/dlsym_time64.S    | 3 +++
 src/ldso/sh/dlsym_time64.S         | 3 +++
 9 files changed, 27 insertions(+)
 create mode 100644 src/ldso/arm/dlsym_time64.S
 create mode 100644 src/ldso/i386/dlsym_time64.S
 create mode 100644 src/ldso/m68k/dlsym_time64.S
 create mode 100644 src/ldso/microblaze/dlsym_time64.S
 create mode 100644 src/ldso/mips/dlsym_time64.S
 create mode 100644 src/ldso/mipsn32/dlsym_time64.S
 create mode 100644 src/ldso/or1k/dlsym_time64.S
 create mode 100644 src/ldso/powerpc/dlsym_time64.S
 create mode 100644 src/ldso/sh/dlsym_time64.S

diff --git a/src/ldso/arm/dlsym_time64.S b/src/ldso/arm/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/arm/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/i386/dlsym_time64.S b/src/ldso/i386/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/i386/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/m68k/dlsym_time64.S b/src/ldso/m68k/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/m68k/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/microblaze/dlsym_time64.S b/src/ldso/microblaze/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/microblaze/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/mips/dlsym_time64.S b/src/ldso/mips/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/mips/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/mipsn32/dlsym_time64.S b/src/ldso/mipsn32/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/mipsn32/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/or1k/dlsym_time64.S b/src/ldso/or1k/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/or1k/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/powerpc/dlsym_time64.S b/src/ldso/powerpc/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/powerpc/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/sh/dlsym_time64.S b/src/ldso/sh/dlsym_time64.S
new file mode 100644
index 00000000..bb2e7040
--- /dev/null
+++ b/src/ldso/sh/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
-- 
2.21.0


[-- Attachment #9: 0008-add-framework-for-arch-provided-makefile-fragments-c.patch --]
[-- Type: text/plain, Size: 1705 bytes --]

From eba248101003888803d626439ac877dbc21e9e80 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Sun, 20 Oct 2019 20:03:20 -0400
Subject: [PATCH 08/15] add framework for arch-provided makefile fragments,
 compat source dirs

the immediate usage case for this is to let 32-bit archs moving to
64-bit time_t via symbol redirection pull in wrapper shims that
provide the old symbol names. in the future it may be used for other
types of compatibility-only source files that are not relevant to all
archs.
---
 Makefile | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index b46f8ca4..d636f5a9 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ includedir = $(prefix)/include
 libdir = $(prefix)/lib
 syslibdir = /lib
 
-SRC_DIRS = $(addprefix $(srcdir)/,src/* crt ldso)
+SRC_DIRS = $(addprefix $(srcdir)/,src/* crt ldso $(COMPAT_SRC_DIRS))
 BASE_GLOBS = $(addsuffix /*.c,$(SRC_DIRS))
 ARCH_GLOBS = $(addsuffix /$(ARCH)/*.[csS],$(SRC_DIRS))
 BASE_SRCS = $(sort $(wildcard $(BASE_GLOBS)))
@@ -27,7 +27,7 @@ ARCH_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(ARCH_SRCS)))
 REPLACED_OBJS = $(sort $(subst /$(ARCH)/,/,$(ARCH_OBJS)))
 ALL_OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(ARCH_OBJS))))
 
-LIBC_OBJS = $(filter obj/src/%,$(ALL_OBJS))
+LIBC_OBJS = $(filter obj/src/%,$(ALL_OBJS)) $(filter obj/compat/%,$(ALL_OBJS))
 LDSO_OBJS = $(filter obj/ldso/%,$(ALL_OBJS:%.o=%.lo))
 CRT_OBJS = $(filter obj/crt/%,$(ALL_OBJS))
 
@@ -75,6 +75,7 @@ WRAPCC_CLANG = clang
 LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
 
 -include config.mak
+-include arch/$(ARCH)/arch.mak
 
 ifeq ($(ARCH),)
 
-- 
2.21.0


[-- Attachment #10: 0009-make-time-related-socket-options-overridable-by-arch.patch --]
[-- Type: text/plain, Size: 2085 bytes --]

From 8023f3c19ea939a5b6e60e71734d489dcbfac2f9 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 31 Oct 2019 16:48:30 -0400
Subject: [PATCH 09/15] make time-related socket options overridable by arch
 bits files

SO_RCVTIMEO and SO_SNDTIMEO already were, but only in aggregate with
SO_DEBUG and all of the other low/traditional options that varied per
arch. SO_TIMESTAMP* are newly overridable. the two groups have to be
done separately since mips64 and powerpc64 will override the former
but not the latter.

at some point this should be cleaned up to use bits headers more
idiomatically.
---
 include/sys/socket.h | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/include/sys/socket.h b/include/sys/socket.h
index 318a98ef..6be699d9 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -182,8 +182,6 @@ struct linger {
 #define SO_PEERCRED     17
 #define SO_RCVLOWAT     18
 #define SO_SNDLOWAT     19
-#define SO_RCVTIMEO     20
-#define SO_SNDTIMEO     21
 #define SO_ACCEPTCONN   30
 #define SO_PEERSEC      31
 #define SO_SNDBUFFORCE  32
@@ -192,6 +190,17 @@ struct linger {
 #define SO_DOMAIN       39
 #endif
 
+#ifndef SO_RCVTIMEO
+#define SO_RCVTIMEO     20
+#define SO_SNDTIMEO     21
+#endif
+
+#ifndef SO_TIMESTAMP
+#define SO_TIMESTAMP    29
+#define SO_TIMESTAMPNS  35
+#define SO_TIMESTAMPING 37
+#endif
+
 #define SO_SECURITY_AUTHENTICATION              22
 #define SO_SECURITY_ENCRYPTION_TRANSPORT        23
 #define SO_SECURITY_ENCRYPTION_NETWORK          24
@@ -203,14 +212,10 @@ struct linger {
 #define SO_GET_FILTER           SO_ATTACH_FILTER
 
 #define SO_PEERNAME             28
-#define SO_TIMESTAMP            29
 #define SCM_TIMESTAMP           SO_TIMESTAMP
-
 #define SO_PASSSEC              34
-#define SO_TIMESTAMPNS          35
 #define SCM_TIMESTAMPNS         SO_TIMESTAMPNS
 #define SO_MARK                 36
-#define SO_TIMESTAMPING         37
 #define SCM_TIMESTAMPING        SO_TIMESTAMPING
 #define SO_RXQ_OVFL             40
 #define SO_WIFI_STATUS          41
-- 
2.21.0


[-- Attachment #11: 0010-fix-x32-msghdr-struct-by-removing-x32-bits-socket.h.patch --]
[-- Type: text/plain, Size: 1354 bytes --]

From 476209dcaa9c5f40fd18b8484b0fbc6d3c979eb9 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 31 Oct 2019 22:55:39 -0400
Subject: [PATCH 10/15] fix x32 msghdr struct by removing x32 bits/socket.h

being that it contains pointers and (from the kernel perspective,
which is wrong) size_t members, x32 uses the 32-bit version of the
structure, not a half-32-bit, half-64-bit layout like we had here. the
x86_64 definition was inadvertently copied when x32 was first added.

unlike errors in the opposite direction (missing padding), this error
was not easily detected breakage, because the layout of the commonly
used initial subset of members still matched. breakage could only be
observed in the presence of control messages or flags.
---
 arch/x32/bits/socket.h | 16 ----------------
 1 file changed, 16 deletions(-)
 delete mode 100644 arch/x32/bits/socket.h

diff --git a/arch/x32/bits/socket.h b/arch/x32/bits/socket.h
deleted file mode 100644
index a4c89f3d..00000000
--- a/arch/x32/bits/socket.h
+++ /dev/null
@@ -1,16 +0,0 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int msg_iovlen, __pad1;
-	void *msg_control;
-	socklen_t msg_controllen, __pad2;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	socklen_t cmsg_len;
-	int __pad1;
-	int cmsg_level;
-	int cmsg_type;
-};
-- 
2.21.0


[-- Attachment #12: 0011-move-msghdr-and-cmsghdr-out-of-bits-socket.h.patch --]
[-- Type: text/plain, Size: 8463 bytes --]

From 83121201c289b9ee325268c1cb354b2eb3fe114a Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 31 Oct 2019 23:09:48 -0400
Subject: [PATCH 11/15] move msghdr and cmsghdr out of bits/socket.h

these structures can now be defined generically in terms of endianness
and long size. previously, the 32-bit archs all shared a common
definition from the generic bits header, and each 64-bit arch had to
repeat the 64-bit version, with endian conditionals if the arch had
variants of each endianness.

I would prefer getting rid of the preprocessor conditionals for
padding and instead using unnamed bitfield members, like commit
9b2921bea1d5017832e1b45d1fd64220047a9802 did for struct timespec.
however, at present sendmsg, recvmsg, and recvmmsg need access to the
padding members by name to zero them. this could perhaps be cleaned up
in the future.
---
 arch/aarch64/bits/socket.h   | 31 -------------------------------
 arch/generic/bits/socket.h   | 15 ---------------
 arch/mips/bits/socket.h      | 16 ----------------
 arch/mips64/bits/socket.h    | 32 --------------------------------
 arch/mipsn32/bits/socket.h   | 16 ----------------
 arch/powerpc/bits/socket.h   | 16 ----------------
 arch/powerpc64/bits/socket.h | 32 --------------------------------
 arch/riscv64/bits/socket.h   | 17 -----------------
 arch/s390x/bits/socket.h     | 17 -----------------
 arch/x86_64/bits/socket.h    | 16 ----------------
 include/sys/socket.h         | 34 ++++++++++++++++++++++++++++++++++
 11 files changed, 34 insertions(+), 208 deletions(-)
 delete mode 100644 arch/aarch64/bits/socket.h
 delete mode 100644 arch/riscv64/bits/socket.h
 delete mode 100644 arch/s390x/bits/socket.h
 delete mode 100644 arch/x86_64/bits/socket.h

diff --git a/arch/aarch64/bits/socket.h b/arch/aarch64/bits/socket.h
deleted file mode 100644
index 55337c8b..00000000
--- a/arch/aarch64/bits/socket.h
+++ /dev/null
@@ -1,31 +0,0 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad1, msg_iovlen;
-#else
-	int msg_iovlen, __pad1;
-#endif
-	void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad2;
-	socklen_t msg_controllen;
-#else
-	socklen_t msg_controllen;
-	int __pad2;
-#endif
-	int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad1;
-	socklen_t cmsg_len;
-#else
-	socklen_t cmsg_len;
-	int __pad1;
-#endif
-	int cmsg_level;
-	int cmsg_type;
-};
diff --git a/arch/generic/bits/socket.h b/arch/generic/bits/socket.h
index 1f73b995..e69de29b 100644
--- a/arch/generic/bits/socket.h
+++ b/arch/generic/bits/socket.h
@@ -1,15 +0,0 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int msg_iovlen;
-	void *msg_control;
-	socklen_t msg_controllen;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	socklen_t cmsg_len;
-	int cmsg_level;
-	int cmsg_type;
-};
diff --git a/arch/mips/bits/socket.h b/arch/mips/bits/socket.h
index b82c7d34..92551b9f 100644
--- a/arch/mips/bits/socket.h
+++ b/arch/mips/bits/socket.h
@@ -1,19 +1,3 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int msg_iovlen;
-	void *msg_control;
-	socklen_t msg_controllen;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	socklen_t cmsg_len;
-	int cmsg_level;
-	int cmsg_type;
-};
-
 #define SOCK_STREAM    2
 #define SOCK_DGRAM     1
 
diff --git a/arch/mips64/bits/socket.h b/arch/mips64/bits/socket.h
index aafb209c..519b9c8e 100644
--- a/arch/mips64/bits/socket.h
+++ b/arch/mips64/bits/socket.h
@@ -1,35 +1,3 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad1, msg_iovlen;
-#else
-	int msg_iovlen, __pad1;
-#endif
-	void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad2;
-	socklen_t msg_controllen;
-#else
-	socklen_t msg_controllen;
-	int __pad2;
-#endif
-	int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad1;
-	socklen_t cmsg_len;
-#else
-	socklen_t cmsg_len;
-	int __pad1;
-#endif
-	int cmsg_level;
-	int cmsg_type;
-};
-
 #define SOCK_STREAM    2
 #define SOCK_DGRAM     1
 #define SOL_SOCKET     65535
diff --git a/arch/mipsn32/bits/socket.h b/arch/mipsn32/bits/socket.h
index b82c7d34..92551b9f 100644
--- a/arch/mipsn32/bits/socket.h
+++ b/arch/mipsn32/bits/socket.h
@@ -1,19 +1,3 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int msg_iovlen;
-	void *msg_control;
-	socklen_t msg_controllen;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	socklen_t cmsg_len;
-	int cmsg_level;
-	int cmsg_type;
-};
-
 #define SOCK_STREAM    2
 #define SOCK_DGRAM     1
 
diff --git a/arch/powerpc/bits/socket.h b/arch/powerpc/bits/socket.h
index a94b8bdb..557e324f 100644
--- a/arch/powerpc/bits/socket.h
+++ b/arch/powerpc/bits/socket.h
@@ -1,19 +1,3 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int msg_iovlen;
-	void *msg_control;
-	socklen_t msg_controllen;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	socklen_t cmsg_len;
-	int cmsg_level;
-	int cmsg_type;
-};
-
 #define SO_DEBUG        1
 #define SO_REUSEADDR    2
 #define SO_TYPE         3
diff --git a/arch/powerpc64/bits/socket.h b/arch/powerpc64/bits/socket.h
index dae47302..557e324f 100644
--- a/arch/powerpc64/bits/socket.h
+++ b/arch/powerpc64/bits/socket.h
@@ -1,35 +1,3 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad1, msg_iovlen;
-#else
-	int msg_iovlen, __pad1;
-#endif
-	void *msg_control;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad2;
-	socklen_t msg_controllen;
-#else
-	socklen_t msg_controllen;
-	int __pad2;
-#endif
-	int msg_flags;
-};
-
-struct cmsghdr {
-#if __BYTE_ORDER == __BIG_ENDIAN
-	int __pad1;
-	socklen_t cmsg_len;
-#else
-	socklen_t cmsg_len;
-	int __pad1;
-#endif
-	int cmsg_level;
-	int cmsg_type;
-};
-
 #define SO_DEBUG        1
 #define SO_REUSEADDR    2
 #define SO_TYPE         3
diff --git a/arch/riscv64/bits/socket.h b/arch/riscv64/bits/socket.h
deleted file mode 100644
index e2fd64cf..00000000
--- a/arch/riscv64/bits/socket.h
+++ /dev/null
@@ -1,17 +0,0 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int msg_iovlen, __pad1;
-	void *msg_control;
-	socklen_t msg_controllen;
-	int __pad2;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	socklen_t cmsg_len;
-	int __pad1;
-	int cmsg_level;
-	int cmsg_type;
-};
diff --git a/arch/s390x/bits/socket.h b/arch/s390x/bits/socket.h
deleted file mode 100644
index bd4b20c4..00000000
--- a/arch/s390x/bits/socket.h
+++ /dev/null
@@ -1,17 +0,0 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int __pad1, msg_iovlen;
-	void *msg_control;
-	int __pad2;
-	socklen_t msg_controllen;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	int __pad1;
-	socklen_t cmsg_len;
-	int cmsg_level;
-	int cmsg_type;
-};
diff --git a/arch/x86_64/bits/socket.h b/arch/x86_64/bits/socket.h
deleted file mode 100644
index a4c89f3d..00000000
--- a/arch/x86_64/bits/socket.h
+++ /dev/null
@@ -1,16 +0,0 @@
-struct msghdr {
-	void *msg_name;
-	socklen_t msg_namelen;
-	struct iovec *msg_iov;
-	int msg_iovlen, __pad1;
-	void *msg_control;
-	socklen_t msg_controllen, __pad2;
-	int msg_flags;
-};
-
-struct cmsghdr {
-	socklen_t cmsg_len;
-	int __pad1;
-	int cmsg_level;
-	int cmsg_type;
-};
diff --git a/include/sys/socket.h b/include/sys/socket.h
index 6be699d9..4ea7be1e 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -19,6 +19,40 @@ extern "C" {
 
 #include <bits/socket.h>
 
+struct msghdr {
+	void *msg_name;
+	socklen_t msg_namelen;
+	struct iovec *msg_iov;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN
+	int __pad1;
+#endif
+	int msg_iovlen;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN
+	int __pad1;
+#endif
+	void *msg_control;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN
+	int __pad2;
+#endif
+	socklen_t msg_controllen;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN
+	int __pad2;
+#endif
+	int msg_flags;
+};
+
+struct cmsghdr {
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN
+	int __pad1;
+#endif
+	socklen_t cmsg_len;
+#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN
+	int __pad1;
+#endif
+	int cmsg_level;
+	int cmsg_type;
+};
+
 #ifdef _GNU_SOURCE
 struct ucred {
 	pid_t pid;
-- 
2.21.0


[-- Attachment #13: 0012-add-back-x32-bits-socket.h-defining-time-related-soc.patch --]
[-- Type: text/plain, Size: 981 bytes --]

From a2b608ed2c39a816146210fe8992ebefbd168a7e Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 31 Oct 2019 23:21:35 -0400
Subject: [PATCH 12/15] add back x32 bits/socket.h defining time-related socket
 options

these definitions are merely copied from the top-level sys/socket.h,
so there is no functional change at this time. however, the top-level
definitions will change to use the time64 "_NEW" versions on 32-bit
archs when time_t is switched over to 64-bit. this commit ensures that
change will be suppressed on x32.
---
 arch/x32/bits/socket.h | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 arch/x32/bits/socket.h

diff --git a/arch/x32/bits/socket.h b/arch/x32/bits/socket.h
new file mode 100644
index 00000000..8d830010
--- /dev/null
+++ b/arch/x32/bits/socket.h
@@ -0,0 +1,5 @@
+#define SO_RCVTIMEO     20
+#define SO_SNDTIMEO     21
+#define SO_TIMESTAMP    29
+#define SO_TIMESTAMPNS  35
+#define SO_TIMESTAMPING 37
-- 
2.21.0


[-- Attachment #14: 0013-add-x32-bits-ioctl_fix.h-defining-time-related-socki.patch --]
[-- Type: text/plain, Size: 816 bytes --]

From 8c26edfd82bc65ccbd11be1f1e3d5b44378261c9 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 31 Oct 2019 23:40:10 -0400
Subject: [PATCH 13/15] add x32 bits/ioctl_fix.h defining time-related sockios
 macros

these definitions are copied from generic bits/ioctl.h, so that x32
keeps the "_OLD" versions (which are already time64 on x32) when
32-bit archs switch to 64-bit time_t.
---
 arch/x32/bits/ioctl_fix.h | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 arch/x32/bits/ioctl_fix.h

diff --git a/arch/x32/bits/ioctl_fix.h b/arch/x32/bits/ioctl_fix.h
new file mode 100644
index 00000000..83b957bd
--- /dev/null
+++ b/arch/x32/bits/ioctl_fix.h
@@ -0,0 +1,4 @@
+#undef SIOCGSTAMP
+#undef SIOCGSTAMPNS
+#define SIOCGSTAMP      0x8906
+#define SIOCGSTAMPNS    0x8907
-- 
2.21.0


[-- Attachment #15: 0014-switch-all-existing-32-bit-archs-to-64-bit-time_t.patch --]
[-- Type: text/plain, Size: 46026 bytes --]

From deb2de2705266adf039d6834396000a9a34f3212 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Fri, 2 Aug 2019 15:41:27 -0400
Subject: [PATCH 14/15] switch all existing 32-bit archs to 64-bit time_t

this commit preserves ABI fully for existing interface boundaries
between libc and libc consumers (applications or libraries), by
retaining existing symbol names for the legacy 32-bit interfaces and
redirecting sources compiled against the new headers to alternate
symbol names. this does not necessarily, however, preserve the
pairwise ABI of libc consumers with one another; where they use
time_t-derived types in their interfaces with one another, it may be
necessary to synchronize updates with each other.

the intent is that ABI resulting from this commit already be stable
and permanent, but it will not be officially so until a release is
made. changes to some header-defined types that do not play any role
in the ABI between libc and its consumers may still be subject to
change.

mechanically, the changes made by this commit for each 32-bit arch are
as follows:

- _REDIR_TIME64 is defined to activate the symbol redirections in
  public headers

- COMPAT_SRC_DIRS is defined in arch.mak to activate build of ABI
  compat shims to serve as definitions for the original symbol names

- time_t and suseconds_t definitions are changed to long long (64-bit)

- IPC_STAT definition is changed to add the IPC_TIME64 bit (0x100),
  triggering conversion of semid_ds, shmid_ds, and msqid_ds split
  low/high time bits into new time_t members

- structs semid_ds, shmid_ds, msqid_ds, and stat are modified to add
  new 64-bit time_t/timespec members at the end, maintaining existing
  layout of other members.

for socket option (SO_*) and ioctl (sockios) command macros that need
new definitions, the top-level/generic ones are changed to use the
kernel's "_NEW" values on 32-bit archs, and bits files for archs with
their own versions are modified likewise. x32, which already had
64-bit time_t with the old ones, has already been exempted via its own
arch-speciifc bits.

in addition, on archs where vdso clock_gettime is used, the
VDSO_CGT_SYM macro definition in syscall_arch.h is changed to use a
new time64 vdso function if available, and a new VDSO_CGT32_SYM macro
is added for use as fallback on kernels lacking time64.
---
 arch/arm/arch.mak                  |  1 +
 arch/arm/bits/alltypes.h.in        |  5 +++--
 arch/arm/bits/ipcstat.h            |  2 +-
 arch/arm/bits/msg.h                | 15 +++++++++------
 arch/arm/bits/sem.h                | 10 ++++++----
 arch/arm/bits/shm.h                | 16 ++++++++++------
 arch/arm/bits/stat.h               |  6 +++++-
 arch/arm/syscall_arch.h            |  4 +++-
 arch/generic/bits/ioctl.h          |  5 +++++
 arch/i386/arch.mak                 |  1 +
 arch/i386/bits/alltypes.h.in       |  5 +++--
 arch/i386/bits/ipcstat.h           |  2 +-
 arch/i386/bits/msg.h               | 15 +++++++++------
 arch/i386/bits/sem.h               | 10 ++++++----
 arch/i386/bits/shm.h               | 16 ++++++++++------
 arch/i386/bits/stat.h              |  6 +++++-
 arch/i386/syscall_arch.h           |  4 +++-
 arch/m68k/arch.mak                 |  1 +
 arch/m68k/bits/alltypes.h.in       |  5 +++--
 arch/m68k/bits/ipcstat.h           |  2 +-
 arch/m68k/bits/msg.h               | 15 +++++++++------
 arch/m68k/bits/sem.h               | 10 ++++++----
 arch/m68k/bits/shm.h               | 16 ++++++++++------
 arch/m68k/bits/stat.h              |  6 +++++-
 arch/microblaze/arch.mak           |  1 +
 arch/microblaze/bits/alltypes.h.in |  5 +++--
 arch/microblaze/bits/ipcstat.h     |  2 +-
 arch/microblaze/bits/msg.h         | 15 +++++++++------
 arch/microblaze/bits/sem.h         | 10 ++++++----
 arch/microblaze/bits/shm.h         | 16 ++++++++++------
 arch/microblaze/bits/stat.h        |  6 +++++-
 arch/mips/arch.mak                 |  1 +
 arch/mips/bits/alltypes.h.in       |  5 +++--
 arch/mips/bits/ioctl.h             |  4 ++--
 arch/mips/bits/ipcstat.h           |  2 +-
 arch/mips/bits/msg.h               | 27 +++++++++++++++------------
 arch/mips/bits/sem.h               | 10 ++++++----
 arch/mips/bits/shm.h               | 15 ++++++++++-----
 arch/mips/bits/socket.h            |  7 +++++--
 arch/mips/bits/stat.h              | 12 ++++++++----
 arch/mips/syscall_arch.h           |  4 +++-
 arch/mipsn32/arch.mak              |  1 +
 arch/mipsn32/bits/alltypes.h.in    |  5 +++--
 arch/mipsn32/bits/ioctl.h          |  2 ++
 arch/mipsn32/bits/ipcstat.h        |  2 +-
 arch/mipsn32/bits/msg.h            | 27 +++++++++++++++------------
 arch/mipsn32/bits/sem.h            | 10 ++++++----
 arch/mipsn32/bits/shm.h            | 15 ++++++++++-----
 arch/mipsn32/bits/socket.h         |  7 +++++--
 arch/mipsn32/bits/stat.h           | 12 ++++++++----
 arch/mipsn32/syscall_arch.h        |  4 +++-
 arch/or1k/arch.mak                 |  1 +
 arch/or1k/bits/alltypes.h.in       |  5 +++--
 arch/or1k/bits/ipcstat.h           |  2 +-
 arch/or1k/bits/msg.h               | 15 +++++++++------
 arch/or1k/bits/sem.h               | 10 ++++++----
 arch/or1k/bits/shm.h               | 16 ++++++++++------
 arch/or1k/bits/stat.h              | 10 +++++++---
 arch/powerpc/arch.mak              |  1 +
 arch/powerpc/bits/alltypes.h.in    |  5 +++--
 arch/powerpc/bits/ioctl.h          |  4 ++--
 arch/powerpc/bits/ipcstat.h        |  2 +-
 arch/powerpc/bits/msg.h            | 15 +++++++++------
 arch/powerpc/bits/sem.h            | 10 ++++++----
 arch/powerpc/bits/shm.h            | 16 +++++++++-------
 arch/powerpc/bits/socket.h         |  7 +++++--
 arch/powerpc/bits/stat.h           |  6 +++++-
 arch/sh/arch.mak                   |  1 +
 arch/sh/bits/alltypes.h.in         |  5 +++--
 arch/sh/bits/ioctl.h               |  4 ++--
 arch/sh/bits/ipcstat.h             |  2 +-
 arch/sh/bits/msg.h                 | 15 +++++++++------
 arch/sh/bits/sem.h                 | 10 ++++++----
 arch/sh/bits/shm.h                 | 16 ++++++++++------
 arch/sh/bits/stat.h                |  6 +++++-
 include/sys/socket.h               |  8 ++++++++
 76 files changed, 382 insertions(+), 215 deletions(-)
 create mode 100644 arch/arm/arch.mak
 create mode 100644 arch/i386/arch.mak
 create mode 100644 arch/m68k/arch.mak
 create mode 100644 arch/microblaze/arch.mak
 create mode 100644 arch/mips/arch.mak
 create mode 100644 arch/mipsn32/arch.mak
 create mode 100644 arch/or1k/arch.mak
 create mode 100644 arch/powerpc/arch.mak
 create mode 100644 arch/sh/arch.mak

diff --git a/arch/arm/arch.mak b/arch/arm/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/arm/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/arm/bits/alltypes.h.in b/arch/arm/bits/alltypes.h.in
index d2700bd9..40bd30ea 100644
--- a/arch/arm/bits/alltypes.h.in
+++ b/arch/arm/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -19,5 +20,5 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/arm/bits/ipcstat.h b/arch/arm/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/arm/bits/ipcstat.h
+++ b/arch/arm/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/arm/bits/msg.h b/arch/arm/bits/msg.h
index bc8436c4..7bbbb2bf 100644
--- a/arch/arm/bits/msg.h
+++ b/arch/arm/bits/msg.h
@@ -1,15 +1,18 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
 	msglen_t msg_qbytes;
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/arm/bits/sem.h b/arch/arm/bits/sem.h
index d383d4ea..544e3d2a 100644
--- a/arch/arm/bits/sem.h
+++ b/arch/arm/bits/sem.h
@@ -1,9 +1,9 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	long __unused1;
-	time_t sem_ctime;
-	long __unused2;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_lo;
+	unsigned long __sem_ctime_hi;
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 	unsigned short sem_nsems;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -13,4 +13,6 @@ struct semid_ds {
 #endif
 	long __unused3;
 	long __unused4;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/arm/bits/shm.h b/arch/arm/bits/shm.h
index 81b2a29a..725fb469 100644
--- a/arch/arm/bits/shm.h
+++ b/arch/arm/bits/shm.h
@@ -3,17 +3,21 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	int __unused1;
-	time_t shm_dtime;
-	int __unused2;
-	time_t shm_ctime;
-	int __unused3;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_atime_hi;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_dtime_hi;
+	unsigned long __shm_ctime_lo;
+	unsigned long __shm_ctime_hi;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
 	unsigned long __pad1;
 	unsigned long __pad2;
+	unsigned long __pad3;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/arm/bits/stat.h b/arch/arm/bits/stat.h
index 22b19bbf..5d7828cf 100644
--- a/arch/arm/bits/stat.h
+++ b/arch/arm/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
 	off_t st_size;
 	blksize_t st_blksize;
 	blkcnt_t st_blocks;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
+	ino_t st_ino;
 	struct timespec st_atim;
 	struct timespec st_mtim;
 	struct timespec st_ctim;
-	ino_t st_ino;
 };
diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h
index 53fb155c..4b08762d 100644
--- a/arch/arm/syscall_arch.h
+++ b/arch/arm/syscall_arch.h
@@ -99,7 +99,9 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 }
 
 #define VDSO_USEFUL
-#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
 #define VDSO_CGT_VER "LINUX_2.6"
 
 #define SYSCALL_FADVISE_6_ARG
diff --git a/arch/generic/bits/ioctl.h b/arch/generic/bits/ioctl.h
index d1a6c035..60ae8b85 100644
--- a/arch/generic/bits/ioctl.h
+++ b/arch/generic/bits/ioctl.h
@@ -104,7 +104,12 @@
 #define FIOGETOWN       0x8903
 #define SIOCGPGRP       0x8904
 #define SIOCATMARK      0x8905
+#if __LONG_MAX == 0x7fffffff
+#define SIOCGSTAMP      _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS    _IOR(0x89, 7, char[16])
+#else
 #define SIOCGSTAMP      0x8906
 #define SIOCGSTAMPNS    0x8907
+#endif
 
 #include <bits/ioctl_fix.h>
diff --git a/arch/i386/arch.mak b/arch/i386/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/i386/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/i386/bits/alltypes.h.in b/arch/i386/bits/alltypes.h.in
index f033f376..74e599a2 100644
--- a/arch/i386/bits/alltypes.h.in
+++ b/arch/i386/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -29,5 +30,5 @@ TYPEDEF struct { __attribute__((__aligned__(8))) long long __ll; long double __l
 TYPEDEF struct { alignas(8) long long __ll; long double __ld; } max_align_t;
 #endif
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/i386/bits/ipcstat.h b/arch/i386/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/i386/bits/ipcstat.h
+++ b/arch/i386/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/i386/bits/msg.h b/arch/i386/bits/msg.h
index bc8436c4..7bbbb2bf 100644
--- a/arch/i386/bits/msg.h
+++ b/arch/i386/bits/msg.h
@@ -1,15 +1,18 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
 	msglen_t msg_qbytes;
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/i386/bits/sem.h b/arch/i386/bits/sem.h
index e61571c1..65661542 100644
--- a/arch/i386/bits/sem.h
+++ b/arch/i386/bits/sem.h
@@ -1,11 +1,13 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	long __unused1;
-	time_t sem_ctime;
-	long __unused2;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_lo;
+	unsigned long __sem_ctime_hi;
 	unsigned short sem_nsems;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
 	long __unused3;
 	long __unused4;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/i386/bits/shm.h b/arch/i386/bits/shm.h
index 81b2a29a..725fb469 100644
--- a/arch/i386/bits/shm.h
+++ b/arch/i386/bits/shm.h
@@ -3,17 +3,21 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	int __unused1;
-	time_t shm_dtime;
-	int __unused2;
-	time_t shm_ctime;
-	int __unused3;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_atime_hi;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_dtime_hi;
+	unsigned long __shm_ctime_lo;
+	unsigned long __shm_ctime_hi;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
 	unsigned long __pad1;
 	unsigned long __pad2;
+	unsigned long __pad3;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/i386/bits/stat.h b/arch/i386/bits/stat.h
index 22b19bbf..5d7828cf 100644
--- a/arch/i386/bits/stat.h
+++ b/arch/i386/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
 	off_t st_size;
 	blksize_t st_blksize;
 	blkcnt_t st_blocks;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
+	ino_t st_ino;
 	struct timespec st_atim;
 	struct timespec st_mtim;
 	struct timespec st_ctim;
-	ino_t st_ino;
 };
diff --git a/arch/i386/syscall_arch.h b/arch/i386/syscall_arch.h
index 22b0b28b..69642e57 100644
--- a/arch/i386/syscall_arch.h
+++ b/arch/i386/syscall_arch.h
@@ -83,7 +83,9 @@ static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a
 }
 
 #define VDSO_USEFUL
-#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
 #define VDSO_CGT_VER "LINUX_2.6"
 
 #define SYSCALL_USE_SOCKETCALL
diff --git a/arch/m68k/arch.mak b/arch/m68k/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/m68k/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/m68k/bits/alltypes.h.in b/arch/m68k/bits/alltypes.h.in
index 922c2ce5..a92d1f07 100644
--- a/arch/m68k/bits/alltypes.h.in
+++ b/arch/m68k/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -23,5 +24,5 @@ TYPEDEF long double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/m68k/bits/ipcstat.h b/arch/m68k/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/m68k/bits/ipcstat.h
+++ b/arch/m68k/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/m68k/bits/msg.h b/arch/m68k/bits/msg.h
index bc8436c4..7bbbb2bf 100644
--- a/arch/m68k/bits/msg.h
+++ b/arch/m68k/bits/msg.h
@@ -1,15 +1,18 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
 	msglen_t msg_qbytes;
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/m68k/bits/sem.h b/arch/m68k/bits/sem.h
index 08faafea..d88338e6 100644
--- a/arch/m68k/bits/sem.h
+++ b/arch/m68k/bits/sem.h
@@ -1,11 +1,13 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	long __unused1;
-	time_t sem_ctime;
-	long __unused2;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_lo;
+	unsigned long __sem_ctime_hi;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
 	unsigned short sem_nsems;
 	long __unused3;
 	long __unused4;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/m68k/bits/shm.h b/arch/m68k/bits/shm.h
index 81b2a29a..725fb469 100644
--- a/arch/m68k/bits/shm.h
+++ b/arch/m68k/bits/shm.h
@@ -3,17 +3,21 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	int __unused1;
-	time_t shm_dtime;
-	int __unused2;
-	time_t shm_ctime;
-	int __unused3;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_atime_hi;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_dtime_hi;
+	unsigned long __shm_ctime_lo;
+	unsigned long __shm_ctime_hi;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
 	unsigned long __pad1;
 	unsigned long __pad2;
+	unsigned long __pad3;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/m68k/bits/stat.h b/arch/m68k/bits/stat.h
index 0f7b66a1..f8768147 100644
--- a/arch/m68k/bits/stat.h
+++ b/arch/m68k/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
 	off_t st_size;
 	blksize_t st_blksize;
 	blkcnt_t st_blocks;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
+	ino_t st_ino;
 	struct timespec st_atim;
 	struct timespec st_mtim;
 	struct timespec st_ctim;
-	ino_t st_ino;
 };
diff --git a/arch/microblaze/arch.mak b/arch/microblaze/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/microblaze/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/microblaze/bits/alltypes.h.in b/arch/microblaze/bits/alltypes.h.in
index b958604e..6f69b4f9 100644
--- a/arch/microblaze/bits/alltypes.h.in
+++ b/arch/microblaze/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -19,5 +20,5 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/microblaze/bits/ipcstat.h b/arch/microblaze/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/microblaze/bits/ipcstat.h
+++ b/arch/microblaze/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/microblaze/bits/msg.h b/arch/microblaze/bits/msg.h
index bc8436c4..7bbbb2bf 100644
--- a/arch/microblaze/bits/msg.h
+++ b/arch/microblaze/bits/msg.h
@@ -1,15 +1,18 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
 	msglen_t msg_qbytes;
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/microblaze/bits/sem.h b/arch/microblaze/bits/sem.h
index d383d4ea..544e3d2a 100644
--- a/arch/microblaze/bits/sem.h
+++ b/arch/microblaze/bits/sem.h
@@ -1,9 +1,9 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	long __unused1;
-	time_t sem_ctime;
-	long __unused2;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_lo;
+	unsigned long __sem_ctime_hi;
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 	unsigned short sem_nsems;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -13,4 +13,6 @@ struct semid_ds {
 #endif
 	long __unused3;
 	long __unused4;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/microblaze/bits/shm.h b/arch/microblaze/bits/shm.h
index 81b2a29a..725fb469 100644
--- a/arch/microblaze/bits/shm.h
+++ b/arch/microblaze/bits/shm.h
@@ -3,17 +3,21 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	int __unused1;
-	time_t shm_dtime;
-	int __unused2;
-	time_t shm_ctime;
-	int __unused3;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_atime_hi;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_dtime_hi;
+	unsigned long __shm_ctime_lo;
+	unsigned long __shm_ctime_hi;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
 	unsigned long __pad1;
 	unsigned long __pad2;
+	unsigned long __pad3;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/microblaze/bits/stat.h b/arch/microblaze/bits/stat.h
index ce6a6bd0..8a4d509a 100644
--- a/arch/microblaze/bits/stat.h
+++ b/arch/microblaze/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
 	blksize_t st_blksize;
 	int __st_blksize_padding;
 	blkcnt_t st_blocks;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
+	unsigned __unused[2];
 	struct timespec st_atim;
 	struct timespec st_mtim;
 	struct timespec st_ctim;
-	unsigned __unused[2];
 };
diff --git a/arch/mips/arch.mak b/arch/mips/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/mips/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/mips/bits/alltypes.h.in b/arch/mips/bits/alltypes.h.in
index 9544b496..32544cfe 100644
--- a/arch/mips/bits/alltypes.h.in
+++ b/arch/mips/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -19,5 +20,5 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/mips/bits/ioctl.h b/arch/mips/bits/ioctl.h
index e277c3f0..e20bf19e 100644
--- a/arch/mips/bits/ioctl.h
+++ b/arch/mips/bits/ioctl.h
@@ -110,5 +110,5 @@
 #define SIOCATMARK      _IOR('s', 7, int)
 #define SIOCSPGRP       _IOW('s', 8, pid_t)
 #define SIOCGPGRP       _IOR('s', 9, pid_t)
-#define SIOCGSTAMP      0x8906
-#define SIOCGSTAMPNS    0x8907
+#define SIOCGSTAMP      _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS    _IOR(0x89, 7, char[16])
diff --git a/arch/mips/bits/ipcstat.h b/arch/mips/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/mips/bits/ipcstat.h
+++ b/arch/mips/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/mips/bits/msg.h b/arch/mips/bits/msg.h
index f28aece8..c734dbb5 100644
--- a/arch/mips/bits/msg.h
+++ b/arch/mips/bits/msg.h
@@ -1,19 +1,19 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
 #if _MIPSEL || __MIPSEL || __MIPSEL__
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 #else
-	int __unused1;
-	time_t msg_stime;
-	int __unused2;
-	time_t msg_rtime;
-	int __unused3;
-	time_t msg_ctime;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_ctime_hi;
+	unsigned long __msg_ctime_lo;
 #endif
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
@@ -21,4 +21,7 @@ struct msqid_ds {
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/mips/bits/sem.h b/arch/mips/bits/sem.h
index 5184eb59..fe6f0948 100644
--- a/arch/mips/bits/sem.h
+++ b/arch/mips/bits/sem.h
@@ -1,7 +1,7 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	time_t sem_ctime;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_ctime_lo;
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 	unsigned short sem_nsems;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -9,6 +9,8 @@ struct semid_ds {
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
 	unsigned short sem_nsems;
 #endif
-	long __unused3;
-	long __unused4;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_hi;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/mips/bits/shm.h b/arch/mips/bits/shm.h
index 8d193781..ab8c642d 100644
--- a/arch/mips/bits/shm.h
+++ b/arch/mips/bits/shm.h
@@ -3,14 +3,19 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	time_t shm_dtime;
-	time_t shm_ctime;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_ctime_lo;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
-	unsigned long __pad1;
-	unsigned long __pad2;
+	unsigned short __shm_atime_hi;
+	unsigned short __shm_dtime_hi;
+	unsigned short __shm_ctime_hi;
+	unsigned short __pad1;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/mips/bits/socket.h b/arch/mips/bits/socket.h
index 92551b9f..4ffc4d4a 100644
--- a/arch/mips/bits/socket.h
+++ b/arch/mips/bits/socket.h
@@ -16,13 +16,16 @@
 #define SO_RCVBUF       0x1002
 #define SO_SNDLOWAT     0x1003
 #define SO_RCVLOWAT     0x1004
-#define SO_RCVTIMEO     0x1006
-#define SO_SNDTIMEO     0x1005
 #define SO_ERROR        0x1007
 #define SO_TYPE         0x1008
 #define SO_ACCEPTCONN   0x1009
 #define SO_PROTOCOL     0x1028
 #define SO_DOMAIN       0x1029
+#define SO_TIMESTAMP    63
+#define SO_TIMESTAMPNS  64
+#define SO_TIMESTAMPING 65
+#define SO_RCVTIMEO     66
+#define SO_SNDTIMEO     67
 
 #define SO_NO_CHECK     11
 #define SO_PRIORITY     12
diff --git a/arch/mips/bits/stat.h b/arch/mips/bits/stat.h
index 3291a636..48d4ac80 100644
--- a/arch/mips/bits/stat.h
+++ b/arch/mips/bits/stat.h
@@ -12,11 +12,15 @@ struct stat {
 	dev_t st_rdev;
 	long __st_padding2[2];
 	off_t st_size;
-	struct timespec st_atim;
-	struct timespec st_mtim;
-	struct timespec st_ctim;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
 	blksize_t st_blksize;
 	long __st_padding3;
 	blkcnt_t st_blocks;
-        long __st_padding4[14];
+	struct timespec st_atim;
+	struct timespec st_mtim;
+	struct timespec st_ctim;
+	long __st_padding4[2];
 };
diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
index 6ea73437..f821e73f 100644
--- a/arch/mips/syscall_arch.h
+++ b/arch/mips/syscall_arch.h
@@ -142,7 +142,9 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
 }
 
 #define VDSO_USEFUL
-#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
 #define VDSO_CGT_VER "LINUX_2.6"
 
 #define SO_SNDTIMEO_OLD 0x1005
diff --git a/arch/mipsn32/arch.mak b/arch/mipsn32/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/mipsn32/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/mipsn32/bits/alltypes.h.in b/arch/mipsn32/bits/alltypes.h.in
index 9544b496..32544cfe 100644
--- a/arch/mipsn32/bits/alltypes.h.in
+++ b/arch/mipsn32/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -19,5 +20,5 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/mipsn32/bits/ioctl.h b/arch/mipsn32/bits/ioctl.h
index e277c3f0..f0e39563 100644
--- a/arch/mipsn32/bits/ioctl.h
+++ b/arch/mipsn32/bits/ioctl.h
@@ -112,3 +112,5 @@
 #define SIOCGPGRP       _IOR('s', 9, pid_t)
 #define SIOCGSTAMP      0x8906
 #define SIOCGSTAMPNS    0x8907
+#define SIOCGSTAMP      _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS    _IOR(0x89, 7, char[16])
diff --git a/arch/mipsn32/bits/ipcstat.h b/arch/mipsn32/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/mipsn32/bits/ipcstat.h
+++ b/arch/mipsn32/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/mipsn32/bits/msg.h b/arch/mipsn32/bits/msg.h
index f28aece8..c734dbb5 100644
--- a/arch/mipsn32/bits/msg.h
+++ b/arch/mipsn32/bits/msg.h
@@ -1,19 +1,19 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
 #if _MIPSEL || __MIPSEL || __MIPSEL__
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 #else
-	int __unused1;
-	time_t msg_stime;
-	int __unused2;
-	time_t msg_rtime;
-	int __unused3;
-	time_t msg_ctime;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_ctime_hi;
+	unsigned long __msg_ctime_lo;
 #endif
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
@@ -21,4 +21,7 @@ struct msqid_ds {
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/mipsn32/bits/sem.h b/arch/mipsn32/bits/sem.h
index 5184eb59..fe6f0948 100644
--- a/arch/mipsn32/bits/sem.h
+++ b/arch/mipsn32/bits/sem.h
@@ -1,7 +1,7 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	time_t sem_ctime;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_ctime_lo;
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 	unsigned short sem_nsems;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -9,6 +9,8 @@ struct semid_ds {
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
 	unsigned short sem_nsems;
 #endif
-	long __unused3;
-	long __unused4;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_hi;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/mipsn32/bits/shm.h b/arch/mipsn32/bits/shm.h
index 8d193781..ab8c642d 100644
--- a/arch/mipsn32/bits/shm.h
+++ b/arch/mipsn32/bits/shm.h
@@ -3,14 +3,19 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	time_t shm_dtime;
-	time_t shm_ctime;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_ctime_lo;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
-	unsigned long __pad1;
-	unsigned long __pad2;
+	unsigned short __shm_atime_hi;
+	unsigned short __shm_dtime_hi;
+	unsigned short __shm_ctime_hi;
+	unsigned short __pad1;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/mipsn32/bits/socket.h b/arch/mipsn32/bits/socket.h
index 92551b9f..4ffc4d4a 100644
--- a/arch/mipsn32/bits/socket.h
+++ b/arch/mipsn32/bits/socket.h
@@ -16,13 +16,16 @@
 #define SO_RCVBUF       0x1002
 #define SO_SNDLOWAT     0x1003
 #define SO_RCVLOWAT     0x1004
-#define SO_RCVTIMEO     0x1006
-#define SO_SNDTIMEO     0x1005
 #define SO_ERROR        0x1007
 #define SO_TYPE         0x1008
 #define SO_ACCEPTCONN   0x1009
 #define SO_PROTOCOL     0x1028
 #define SO_DOMAIN       0x1029
+#define SO_TIMESTAMP    63
+#define SO_TIMESTAMPNS  64
+#define SO_TIMESTAMPING 65
+#define SO_RCVTIMEO     66
+#define SO_SNDTIMEO     67
 
 #define SO_NO_CHECK     11
 #define SO_PRIORITY     12
diff --git a/arch/mipsn32/bits/stat.h b/arch/mipsn32/bits/stat.h
index 27d36b51..6e2f2808 100644
--- a/arch/mipsn32/bits/stat.h
+++ b/arch/mipsn32/bits/stat.h
@@ -9,11 +9,15 @@ struct stat {
 	dev_t st_rdev;
 	long __pad2[2];
 	off_t st_size;
-	struct timespec st_atim;
-	struct timespec st_mtim;
-	struct timespec st_ctim;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
 	blksize_t st_blksize;
 	long __pad3;
 	blkcnt_t st_blocks;
-	long __pad4[14];
+	struct timespec st_atim;
+	struct timespec st_mtim;
+	struct timespec st_ctim;
+	long __pad4[2];
 };
diff --git a/arch/mipsn32/syscall_arch.h b/arch/mipsn32/syscall_arch.h
index 5ff43bba..c1a4b7da 100644
--- a/arch/mipsn32/syscall_arch.h
+++ b/arch/mipsn32/syscall_arch.h
@@ -116,7 +116,9 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 }
 
 #define VDSO_USEFUL
-#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
 #define VDSO_CGT_VER "LINUX_2.6"
 
 #define SO_SNDTIMEO_OLD 0x1005
diff --git a/arch/or1k/arch.mak b/arch/or1k/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/or1k/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/or1k/bits/alltypes.h.in b/arch/or1k/bits/alltypes.h.in
index 5faa1578..aeb73ab5 100644
--- a/arch/or1k/bits/alltypes.h.in
+++ b/arch/or1k/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -14,5 +15,5 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/or1k/bits/ipcstat.h b/arch/or1k/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/or1k/bits/ipcstat.h
+++ b/arch/or1k/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/or1k/bits/msg.h b/arch/or1k/bits/msg.h
index bc8436c4..7bbbb2bf 100644
--- a/arch/or1k/bits/msg.h
+++ b/arch/or1k/bits/msg.h
@@ -1,15 +1,18 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
 	msglen_t msg_qbytes;
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/or1k/bits/sem.h b/arch/or1k/bits/sem.h
index 08faafea..d88338e6 100644
--- a/arch/or1k/bits/sem.h
+++ b/arch/or1k/bits/sem.h
@@ -1,11 +1,13 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	long __unused1;
-	time_t sem_ctime;
-	long __unused2;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_lo;
+	unsigned long __sem_ctime_hi;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
 	unsigned short sem_nsems;
 	long __unused3;
 	long __unused4;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/or1k/bits/shm.h b/arch/or1k/bits/shm.h
index 81b2a29a..725fb469 100644
--- a/arch/or1k/bits/shm.h
+++ b/arch/or1k/bits/shm.h
@@ -3,17 +3,21 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	int __unused1;
-	time_t shm_dtime;
-	int __unused2;
-	time_t shm_ctime;
-	int __unused3;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_atime_hi;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_dtime_hi;
+	unsigned long __shm_ctime_lo;
+	unsigned long __shm_ctime_hi;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
 	unsigned long __pad1;
 	unsigned long __pad2;
+	unsigned long __pad3;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/or1k/bits/stat.h b/arch/or1k/bits/stat.h
index ce6a6bd0..cde3fd02 100644
--- a/arch/or1k/bits/stat.h
+++ b/arch/or1k/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
 	blksize_t st_blksize;
 	int __st_blksize_padding;
 	blkcnt_t st_blocks;
-	struct timespec st_atim;
-	struct timespec st_mtim;
-	struct timespec st_ctim;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
 	unsigned __unused[2];
+ 	struct timespec st_atim;
+ 	struct timespec st_mtim;
+ 	struct timespec st_ctim;
 };
diff --git a/arch/powerpc/arch.mak b/arch/powerpc/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/powerpc/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/powerpc/bits/alltypes.h.in b/arch/powerpc/bits/alltypes.h.in
index fd0c816c..8e003545 100644
--- a/arch/powerpc/bits/alltypes.h.in
+++ b/arch/powerpc/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -18,5 +19,5 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/powerpc/bits/ioctl.h b/arch/powerpc/bits/ioctl.h
index b6cbb18f..ac9bfd20 100644
--- a/arch/powerpc/bits/ioctl.h
+++ b/arch/powerpc/bits/ioctl.h
@@ -116,5 +116,5 @@
 #define FIOGETOWN       0x8903
 #define SIOCGPGRP       0x8904
 #define SIOCATMARK      0x8905
-#define SIOCGSTAMP      0x8906
-#define SIOCGSTAMPNS    0x8907
+#define SIOCGSTAMP      _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS    _IOR(0x89, 7, char[16])
diff --git a/arch/powerpc/bits/ipcstat.h b/arch/powerpc/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/powerpc/bits/ipcstat.h
+++ b/arch/powerpc/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/powerpc/bits/msg.h b/arch/powerpc/bits/msg.h
index 171c11a3..9fb15dcc 100644
--- a/arch/powerpc/bits/msg.h
+++ b/arch/powerpc/bits/msg.h
@@ -1,15 +1,18 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
-	int __unused1;
-	time_t msg_stime;
-	int __unused2;
-	time_t msg_rtime;
-	int __unused3;
-	time_t msg_ctime;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_ctime_hi;
+	unsigned long __msg_ctime_lo;
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
 	msglen_t msg_qbytes;
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/powerpc/bits/sem.h b/arch/powerpc/bits/sem.h
index bc2d6d1f..28be4845 100644
--- a/arch/powerpc/bits/sem.h
+++ b/arch/powerpc/bits/sem.h
@@ -1,10 +1,12 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	int __unused1;
-	time_t sem_otime;
-	int  __unused2;
-	time_t sem_ctime;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_ctime_hi;
+	unsigned long __sem_ctime_lo;
 	unsigned short __sem_nsems_pad, sem_nsems;
 	long __unused3;
 	long __unused4;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/powerpc/bits/shm.h b/arch/powerpc/bits/shm.h
index b19801d5..fb1d4020 100644
--- a/arch/powerpc/bits/shm.h
+++ b/arch/powerpc/bits/shm.h
@@ -2,19 +2,21 @@
 
 struct shmid_ds {
 	struct ipc_perm shm_perm;
-	int __unused1;
-	time_t shm_atime;
-	int __unused2;
-	time_t shm_dtime;
-	int __unused3;
-	time_t shm_ctime;
-	int __unused4;
+	unsigned long __shm_atime_hi;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_dtime_hi;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_ctime_hi;
+	unsigned long __shm_ctime_lo;
 	size_t shm_segsz;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
 	unsigned long __pad1;
 	unsigned long __pad2;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/powerpc/bits/socket.h b/arch/powerpc/bits/socket.h
index 557e324f..e5fa0f7a 100644
--- a/arch/powerpc/bits/socket.h
+++ b/arch/powerpc/bits/socket.h
@@ -15,8 +15,6 @@
 #define SO_REUSEPORT    15
 #define SO_RCVLOWAT     16
 #define SO_SNDLOWAT     17
-#define SO_RCVTIMEO     18
-#define SO_SNDTIMEO     19
 #define SO_PASSCRED     20
 #define SO_PEERCRED     21
 #define SO_ACCEPTCONN   30
@@ -25,3 +23,8 @@
 #define SO_RCVBUFFORCE  33
 #define SO_PROTOCOL     38
 #define SO_DOMAIN       39
+#define SO_TIMESTAMP    63
+#define SO_TIMESTAMPNS  64
+#define SO_TIMESTAMPING 65
+#define SO_RCVTIMEO     66
+#define SO_SNDTIMEO     67
diff --git a/arch/powerpc/bits/stat.h b/arch/powerpc/bits/stat.h
index dcb896fd..585d98e9 100644
--- a/arch/powerpc/bits/stat.h
+++ b/arch/powerpc/bits/stat.h
@@ -13,8 +13,12 @@ struct stat {
 	off_t st_size;
 	blksize_t st_blksize;
 	blkcnt_t st_blocks;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
+	unsigned __unused[2];
 	struct timespec st_atim;
 	struct timespec st_mtim;
 	struct timespec st_ctim;
-	unsigned __unused[2];
 };
diff --git a/arch/sh/arch.mak b/arch/sh/arch.mak
new file mode 100644
index 00000000..aa4d05ce
--- /dev/null
+++ b/arch/sh/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/sh/bits/alltypes.h.in b/arch/sh/bits/alltypes.h.in
index b32f913c..04e0fcca 100644
--- a/arch/sh/bits/alltypes.h.in
+++ b/arch/sh/bits/alltypes.h.in
@@ -1,3 +1,4 @@
+#define _REDIR_TIME64 1
 #define _Addr int
 #define _Int64 long long
 #define _Reg int
@@ -23,5 +24,5 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
+TYPEDEF long long time_t;
+TYPEDEF long long suseconds_t;
diff --git a/arch/sh/bits/ioctl.h b/arch/sh/bits/ioctl.h
index c4305655..370b6901 100644
--- a/arch/sh/bits/ioctl.h
+++ b/arch/sh/bits/ioctl.h
@@ -108,5 +108,5 @@
 #define SIOCATMARK      _IOR('s', 7, int)
 #define SIOCSPGRP       _IOW('s', 8, int)
 #define SIOCGPGRP       _IOW('s', 9, int)
-#define SIOCGSTAMP      _IOR('s', 100, char[8])
-#define SIOCGSTAMPNS    _IOR('s', 101, char[8])
+#define SIOCGSTAMP      _IOR(0x89, 6, char[16])
+#define SIOCGSTAMPNS    _IOR(0x89, 7, char[16])
diff --git a/arch/sh/bits/ipcstat.h b/arch/sh/bits/ipcstat.h
index 0018ad1e..4f4fcb0c 100644
--- a/arch/sh/bits/ipcstat.h
+++ b/arch/sh/bits/ipcstat.h
@@ -1 +1 @@
-#define IPC_STAT 2
+#define IPC_STAT 0x102
diff --git a/arch/sh/bits/msg.h b/arch/sh/bits/msg.h
index bc8436c4..7bbbb2bf 100644
--- a/arch/sh/bits/msg.h
+++ b/arch/sh/bits/msg.h
@@ -1,15 +1,18 @@
 struct msqid_ds {
 	struct ipc_perm msg_perm;
-	time_t msg_stime;
-	int __unused1;
-	time_t msg_rtime;
-	int __unused2;
-	time_t msg_ctime;
-	int __unused3;
+	unsigned long __msg_stime_lo;
+	unsigned long __msg_stime_hi;
+	unsigned long __msg_rtime_lo;
+	unsigned long __msg_rtime_hi;
+	unsigned long __msg_ctime_lo;
+	unsigned long __msg_ctime_hi;
 	unsigned long msg_cbytes;
 	msgqnum_t msg_qnum;
 	msglen_t msg_qbytes;
 	pid_t msg_lspid;
 	pid_t msg_lrpid;
 	unsigned long __unused[2];
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
 };
diff --git a/arch/sh/bits/sem.h b/arch/sh/bits/sem.h
index d383d4ea..544e3d2a 100644
--- a/arch/sh/bits/sem.h
+++ b/arch/sh/bits/sem.h
@@ -1,9 +1,9 @@
 struct semid_ds {
 	struct ipc_perm sem_perm;
-	time_t sem_otime;
-	long __unused1;
-	time_t sem_ctime;
-	long __unused2;
+	unsigned long __sem_otime_lo;
+	unsigned long __sem_otime_hi;
+	unsigned long __sem_ctime_lo;
+	unsigned long __sem_ctime_hi;
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 	unsigned short sem_nsems;
 	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
@@ -13,4 +13,6 @@ struct semid_ds {
 #endif
 	long __unused3;
 	long __unused4;
+	time_t sem_otime;
+	time_t sem_ctime;
 };
diff --git a/arch/sh/bits/shm.h b/arch/sh/bits/shm.h
index 6cdac131..adc01e34 100644
--- a/arch/sh/bits/shm.h
+++ b/arch/sh/bits/shm.h
@@ -3,17 +3,21 @@
 struct shmid_ds {
 	struct ipc_perm shm_perm;
 	size_t shm_segsz;
-	time_t shm_atime;
-	int __unused1;
-	time_t shm_dtime;
-	int __unused2;
-	time_t shm_ctime;
-	int __unused3;
+	unsigned long __shm_atime_lo;
+	unsigned long __shm_atime_hi;
+	unsigned long __shm_dtime_lo;
+	unsigned long __shm_dtime_hi;
+	unsigned long __shm_ctime_lo;
+	unsigned long __shm_ctime_hi;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
 	unsigned long __pad1;
 	unsigned long __pad2;
+	unsigned long __pad3;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
 };
 
 struct shminfo {
diff --git a/arch/sh/bits/stat.h b/arch/sh/bits/stat.h
index 22b19bbf..5d7828cf 100644
--- a/arch/sh/bits/stat.h
+++ b/arch/sh/bits/stat.h
@@ -14,8 +14,12 @@ struct stat {
 	off_t st_size;
 	blksize_t st_blksize;
 	blkcnt_t st_blocks;
+	struct {
+		long tv_sec;
+		long tv_nsec;
+	} __st_atim32, __st_mtim32, __st_ctim32;
+	ino_t st_ino;
 	struct timespec st_atim;
 	struct timespec st_mtim;
 	struct timespec st_ctim;
-	ino_t st_ino;
 };
diff --git a/include/sys/socket.h b/include/sys/socket.h
index 4ea7be1e..3db3cca3 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -225,6 +225,13 @@ struct linger {
 #endif
 
 #ifndef SO_RCVTIMEO
+#if __LONG_MAX == 0x7fffffff
+#define SO_TIMESTAMP    63
+#define SO_TIMESTAMPNS  64
+#define SO_TIMESTAMPING 65
+#define SO_RCVTIMEO     66
+#define SO_SNDTIMEO     67
+#else
 #define SO_RCVTIMEO     20
 #define SO_SNDTIMEO     21
 #endif
@@ -234,6 +241,7 @@ struct linger {
 #define SO_TIMESTAMPNS  35
 #define SO_TIMESTAMPING 37
 #endif
+#endif
 
 #define SO_SECURITY_AUTHENTICATION              22
 #define SO_SECURITY_ENCRYPTION_TRANSPORT        23
-- 
2.21.0


[-- Attachment #16: 0015-move-time_t-and-suseconds_t-definitions-to-common-al.patch --]
[-- Type: text/plain, Size: 7654 bytes --]

From c119d3d73cc92e4a0d223348a420731c05036ce1 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Tue, 22 Oct 2019 17:08:56 -0400
Subject: [PATCH 15/15] move time_t and suseconds_t definitions to common
 alltypes.h.in

now that all 32-bit archs have 64-bit time_t (and suseconds_t), the
arch-provided _Int64 macro (long or long long, as appropriate) can be
used to define them, and arch-specific definitions are no longer
needed.
---
 arch/aarch64/bits/alltypes.h.in    | 3 ---
 arch/arm/bits/alltypes.h.in        | 3 ---
 arch/i386/bits/alltypes.h.in       | 3 ---
 arch/m68k/bits/alltypes.h.in       | 3 ---
 arch/microblaze/bits/alltypes.h.in | 3 ---
 arch/mips/bits/alltypes.h.in       | 3 ---
 arch/mips64/bits/alltypes.h.in     | 3 ---
 arch/mipsn32/bits/alltypes.h.in    | 3 ---
 arch/or1k/bits/alltypes.h.in       | 3 ---
 arch/powerpc/bits/alltypes.h.in    | 3 ---
 arch/powerpc64/bits/alltypes.h.in  | 3 ---
 arch/riscv64/bits/alltypes.h.in    | 3 ---
 arch/s390x/bits/alltypes.h.in      | 3 ---
 arch/sh/bits/alltypes.h.in         | 3 ---
 arch/x32/bits/alltypes.h.in        | 3 ---
 arch/x86_64/bits/alltypes.h.in     | 3 ---
 include/alltypes.h.in              | 2 ++
 17 files changed, 2 insertions(+), 48 deletions(-)

diff --git a/arch/aarch64/bits/alltypes.h.in b/arch/aarch64/bits/alltypes.h.in
index 8c171051..c547ca0b 100644
--- a/arch/aarch64/bits/alltypes.h.in
+++ b/arch/aarch64/bits/alltypes.h.in
@@ -22,6 +22,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
diff --git a/arch/arm/bits/alltypes.h.in b/arch/arm/bits/alltypes.h.in
index 40bd30ea..d62bd7bd 100644
--- a/arch/arm/bits/alltypes.h.in
+++ b/arch/arm/bits/alltypes.h.in
@@ -19,6 +19,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/i386/bits/alltypes.h.in b/arch/i386/bits/alltypes.h.in
index 74e599a2..6feb03a6 100644
--- a/arch/i386/bits/alltypes.h.in
+++ b/arch/i386/bits/alltypes.h.in
@@ -29,6 +29,3 @@ TYPEDEF struct { __attribute__((__aligned__(8))) long long __ll; long double __l
 #else
 TYPEDEF struct { alignas(8) long long __ll; long double __ld; } max_align_t;
 #endif
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/m68k/bits/alltypes.h.in b/arch/m68k/bits/alltypes.h.in
index a92d1f07..f5646909 100644
--- a/arch/m68k/bits/alltypes.h.in
+++ b/arch/m68k/bits/alltypes.h.in
@@ -23,6 +23,3 @@ TYPEDEF long double double_t;
 #endif
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/microblaze/bits/alltypes.h.in b/arch/microblaze/bits/alltypes.h.in
index 6f69b4f9..9a4ce29d 100644
--- a/arch/microblaze/bits/alltypes.h.in
+++ b/arch/microblaze/bits/alltypes.h.in
@@ -19,6 +19,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/mips/bits/alltypes.h.in b/arch/mips/bits/alltypes.h.in
index 32544cfe..ff934a4c 100644
--- a/arch/mips/bits/alltypes.h.in
+++ b/arch/mips/bits/alltypes.h.in
@@ -19,6 +19,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/mips64/bits/alltypes.h.in b/arch/mips64/bits/alltypes.h.in
index ed8384a1..fcd61ee8 100644
--- a/arch/mips64/bits/alltypes.h.in
+++ b/arch/mips64/bits/alltypes.h.in
@@ -19,7 +19,4 @@ TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
 
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
-
 TYPEDEF unsigned nlink_t;
diff --git a/arch/mipsn32/bits/alltypes.h.in b/arch/mipsn32/bits/alltypes.h.in
index 32544cfe..ff934a4c 100644
--- a/arch/mipsn32/bits/alltypes.h.in
+++ b/arch/mipsn32/bits/alltypes.h.in
@@ -19,6 +19,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/or1k/bits/alltypes.h.in b/arch/or1k/bits/alltypes.h.in
index aeb73ab5..7d3e291a 100644
--- a/arch/or1k/bits/alltypes.h.in
+++ b/arch/or1k/bits/alltypes.h.in
@@ -14,6 +14,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/powerpc/bits/alltypes.h.in b/arch/powerpc/bits/alltypes.h.in
index 8e003545..b48df6a6 100644
--- a/arch/powerpc/bits/alltypes.h.in
+++ b/arch/powerpc/bits/alltypes.h.in
@@ -18,6 +18,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/powerpc64/bits/alltypes.h.in b/arch/powerpc64/bits/alltypes.h.in
index 03ad18fc..143ffa8d 100644
--- a/arch/powerpc64/bits/alltypes.h.in
+++ b/arch/powerpc64/bits/alltypes.h.in
@@ -18,6 +18,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
diff --git a/arch/riscv64/bits/alltypes.h.in b/arch/riscv64/bits/alltypes.h.in
index 77e9798a..4579d174 100644
--- a/arch/riscv64/bits/alltypes.h.in
+++ b/arch/riscv64/bits/alltypes.h.in
@@ -16,6 +16,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
diff --git a/arch/s390x/bits/alltypes.h.in b/arch/s390x/bits/alltypes.h.in
index 20d9c630..15d18c8f 100644
--- a/arch/s390x/bits/alltypes.h.in
+++ b/arch/s390x/bits/alltypes.h.in
@@ -13,6 +13,3 @@ TYPEDEF double float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
diff --git a/arch/sh/bits/alltypes.h.in b/arch/sh/bits/alltypes.h.in
index 04e0fcca..6a538352 100644
--- a/arch/sh/bits/alltypes.h.in
+++ b/arch/sh/bits/alltypes.h.in
@@ -23,6 +23,3 @@ TYPEDEF float float_t;
 TYPEDEF double double_t;
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/x32/bits/alltypes.h.in b/arch/x32/bits/alltypes.h.in
index 655d189b..9f9d2410 100644
--- a/arch/x32/bits/alltypes.h.in
+++ b/arch/x32/bits/alltypes.h.in
@@ -22,6 +22,3 @@ TYPEDEF double double_t;
 #endif
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long long time_t;
-TYPEDEF long long suseconds_t;
diff --git a/arch/x86_64/bits/alltypes.h.in b/arch/x86_64/bits/alltypes.h.in
index fd42cb05..5cd8a299 100644
--- a/arch/x86_64/bits/alltypes.h.in
+++ b/arch/x86_64/bits/alltypes.h.in
@@ -18,6 +18,3 @@ TYPEDEF double double_t;
 #endif
 
 TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
-
-TYPEDEF long time_t;
-TYPEDEF long suseconds_t;
diff --git a/include/alltypes.h.in b/include/alltypes.h.in
index e9b29afc..94aa2089 100644
--- a/include/alltypes.h.in
+++ b/include/alltypes.h.in
@@ -8,6 +8,8 @@ TYPEDEF _Addr ssize_t;
 TYPEDEF _Addr intptr_t;
 TYPEDEF _Addr regoff_t;
 TYPEDEF _Reg register_t;
+TYPEDEF _Int64 time_t;
+TYPEDEF _Int64 suseconds_t;
 
 TYPEDEF signed char     int8_t;
 TYPEDEF signed short    int16_t;
-- 
2.21.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] remaining steps for time64 switchover
  2019-11-01 20:25 [PATCH v2] remaining steps for time64 switchover Rich Felker
@ 2019-11-02  0:02 ` Rich Felker
  0 siblings, 0 replies; 2+ messages in thread
From: Rich Felker @ 2019-11-02  0:02 UTC (permalink / raw)
  To: musl

On Fri, Nov 01, 2019 at 04:25:40PM -0400, Rich Felker wrote:
> From: Rich Felker <dalias@aerifal.cx>
> Date: Fri, 2 Aug 2019 15:41:27 -0400
> Subject: [PATCH 14/15] switch all existing 32-bit archs to 64-bit time_t
> 
> [...]
> 
> diff --git a/include/sys/socket.h b/include/sys/socket.h
> index 4ea7be1e..3db3cca3 100644
> --- a/include/sys/socket.h
> +++ b/include/sys/socket.h
> @@ -225,6 +225,13 @@ struct linger {
>  #endif
>  
>  #ifndef SO_RCVTIMEO
> +#if __LONG_MAX == 0x7fffffff
> +#define SO_TIMESTAMP    63
> +#define SO_TIMESTAMPNS  64
> +#define SO_TIMESTAMPING 65
> +#define SO_RCVTIMEO     66
> +#define SO_SNDTIMEO     67
> +#else
>  #define SO_RCVTIMEO     20
>  #define SO_SNDTIMEO     21
>  #endif
> @@ -234,6 +241,7 @@ struct linger {
>  #define SO_TIMESTAMPNS  35
>  #define SO_TIMESTAMPING 37
>  #endif
> +#endif
>  
>  #define SO_SECURITY_AUTHENTICATION              22
>  #define SO_SECURITY_ENCRYPTION_TRANSPORT        23
> -- 
> 2.21.0
> 

Somehow this got badly botched in rebasing. There's supposed to be
versions of this conditional for both #ifndef's.

I'm in the process of trying to factor this to two commits to avoid
touching non-arch-specific bits in the switchover commit. If that
works out ok I'll post a v3. Probably spending more effort on this
than I should but I'd like a nice audit trail of how the change was
logically made.

Rich


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-11-02  0:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-01 20:25 [PATCH v2] remaining steps for time64 switchover Rich Felker
2019-11-02  0:02 ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).