Discussion:
[RFC PATCH 00/52] Make GLIBC Y2038-proof
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:27 UTC
Permalink
This series implements Y2038-proof types, implementation, internal
functions, and APIs. For more information, see documentation at
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign

Each patch in this series except the last add one type or function,
with a few exception where several functions are implemented as a whole.

The last patch enables the _TIME_BITS mechanism. Once this patch is
applied, API header files will will use 64-bit time if _TIME_BITS is
defined and equal to 64 prior to their inclusion, and conversively,
will use 32-bit time if _TIME_BITS is different from 64 or does not
exist.

Albert ARIBAUD (3ADEV) (52):
Y2038: add type __time64_t
Y2038: add function __difftime64
Y2038: add functions using struct tm
Y2038: add function __mktime64 (and timelocal)
Y2038: add function __timegm64
Y2038: add struct __timespec64
Y2038: add function __clock_gettime64
Y2038: add function __clock_settime64
Y2038: add function __clock_getres64
Y2038: add function __clock_nanosleep64
Y2038: add function __timespec_get64
Y2038: add function __futimens64
Y2038: add function __utimensat64
Y2038: add function __sigtimedwait64
Y2038: add struct __timeval64
Y2038: add function __futimes64
Y2038: add function __lutimes64
Y2038: add struct __itimerspec64
Y2038: add function __timer_gettime64
Y2038: add function __timer_settime64
Y2038: add function __timerfd_gettime64
Y2038: add function __timerfd_settime64
Y2038: add struct __stat64_t64
Y2038: add function __fstat64_t64 (and __fxstat64_t64)
Y2038: add function __stat64_t64 (and __xstat64_t64)
Y2038: add function __lstat64_t64 (and __lxstat64_t64)
Y2038: add function __fstatat64_t64 (and __fxstatat_t64)
Y2038: add function __time_t64
Y2038: add function __stime_t64
Y2038: add function __utimes_t64
Y2038: add function __gettimeofday_t64
Y2038: add function __settimeofday_t64
Y2038: add function __mq_timedsend_t64
Y2038: add function __mq_timedreceive_t64
Y2038: add function __msgctl_t64
Y2038: add function __sched_rr_get_interval_t64
Y2038: add function __nanosleep64_t64
Y2038: add function __adjtime_t64
Y2038: add function __utime_t64
Y2038: add struct __itimerval_t64
Y2038: add function __getitimer_t64
Y2038: add function __setitimer_t64
Y2038: add functions using futexes
Y2038: add function __getrusage_t64
Y2038: add struct __ntp_timeval_t64
Y2038: add function __ntp_gettime_t64
Y2038: add function __ntp_gettimex_t64
Y2038: add function __adjtimex_t64 (and __ntp_adjtime_t64)
Y2038: add function pselect
Y2038: add function select
Y2038: add RPC functions
Y2038: add _TIME_BITS==64 support

bits/typesizes.h | 1 +
include/features.h | 4 +
include/sys/select.h | 15 +
include/sys/stat.h | 35 ++
include/sys/time.h | 6 +
include/time.h | 130 +++++-
include/utime.h | 7 +
io/Versions | 11 +
io/fstat64.c | 7 +
io/fstatat64.c | 7 +
io/futimens.c | 9 +
io/lstat64.c | 7 +
io/stat64.c | 7 +
io/sys/stat.h | 75 +++-
io/utime.c | 16 +
io/utime.h | 15 +-
io/utimensat.c | 9 +
misc/futimes.c | 9 +
misc/lutimes.c | 8 +
misc/sys/select.h | 25 ++
misc/utimes.c | 15 +
nptl/Versions | 11 +
nptl/lll_timedlock_wait.c | 37 ++
nptl/pthread_cond_wait.c | 285 +++++++++++++
nptl/pthread_mutex_timedlock.c | 616 +++++++++++++++++++++++++++
nptl/pthread_rwlock_common.c | 591 +++++++++++++++++++++++++
nptl/pthread_rwlock_timedrdlock.c | 19 +
nptl/pthread_rwlock_timedwrlock.c | 19 +
nptl/sem_timedwait.c | 18 +
nptl/sem_wait.c | 24 ++
nptl/sem_waitcommon.c | 172 ++++++++
posix/Makefile | 3 +-
posix/Versions | 7 +
posix/bits/types.h | 3 +-
posix/sched.h | 9 +
posix/sched_rr_gi64.c | 51 +++
resource/Makefile | 2 +-
resource/Versions | 7 +
resource/getrusage64.c | 185 ++++++++
resource/sys/resource.h | 9 +
rt/Makefile | 6 +-
rt/Versions | 13 +
rt/mq_timedreceive_t64.c | 45 ++
rt/mq_timedsend_t64.c | 44 ++
rt/mqueue.h | 22 +
rt/timerfd_gettime64.c | 28 ++
rt/timerfd_settime64.c | 29 ++
signal/signal.h | 10 +
signal/sigtimedwait.c | 10 +
sunrpc/clnt_udp.c | 27 ++
sunrpc/pmap_rmt.c | 23 +
sunrpc/rpc/clnt.h | 24 ++
sunrpc/rpc/pmap_clnt.h | 15 +
sysdeps/nptl/aio_misc.h | 39 ++
sysdeps/nptl/lowlevellock.h | 17 +
sysdeps/nptl/pthread.h | 41 ++
sysdeps/posix/clock_getres.c | 87 +++-
sysdeps/posix/time.c | 26 ++
sysdeps/posix/utime.c | 22 +
sysdeps/pthread/aio_suspend.c | 164 +++++++
sysdeps/pthread/semaphore.h | 10 +
sysdeps/unix/clock_gettime.c | 46 ++
sysdeps/unix/clock_settime.c | 56 ++-
sysdeps/unix/sysv/linux/Versions | 9 +
sysdeps/unix/sysv/linux/adjtime.c | 124 ++++++
sysdeps/unix/sysv/linux/arm/Versions | 24 ++
sysdeps/unix/sysv/linux/arm/init-first.c | 15 +
sysdeps/unix/sysv/linux/arm/libc-vdso.h | 1 +
sysdeps/unix/sysv/linux/bits/msq.h | 20 +
sysdeps/unix/sysv/linux/bits/stat.h | 6 +-
sysdeps/unix/sysv/linux/clock_getres.c | 40 ++
sysdeps/unix/sysv/linux/clock_gettime.c | 44 ++
sysdeps/unix/sysv/linux/clock_nanosleep.c | 87 +++-
sysdeps/unix/sysv/linux/clock_settime.c | 23 +
sysdeps/unix/sysv/linux/futex-internal.h | 123 ++++++
sysdeps/unix/sysv/linux/futimens.c | 38 ++
sysdeps/unix/sysv/linux/futimes.c | 52 +++
sysdeps/unix/sysv/linux/fxstat64.c | 50 +++
sysdeps/unix/sysv/linux/fxstatat64.c | 54 +++
sysdeps/unix/sysv/linux/gettimeofday.c | 26 ++
sysdeps/unix/sysv/linux/lowlevellock-futex.h | 22 +
sysdeps/unix/sysv/linux/lutimes.c | 53 +++
sysdeps/unix/sysv/linux/lxstat64.c | 50 +++
sysdeps/unix/sysv/linux/msgctl.c | 72 ++++
sysdeps/unix/sysv/linux/ntp_gettime.c | 25 ++
sysdeps/unix/sysv/linux/ntp_gettimex.c | 31 ++
sysdeps/unix/sysv/linux/pselect.c | 61 +++
sysdeps/unix/sysv/linux/select.c | 66 +++
sysdeps/unix/sysv/linux/settimeofday64.c | 44 ++
sysdeps/unix/sysv/linux/sigtimedwait.c | 75 ++++
sysdeps/unix/sysv/linux/stime.c | 70 +++
sysdeps/unix/sysv/linux/sys/timerfd.h | 19 +
sysdeps/unix/sysv/linux/sys/timex.h | 32 +-
sysdeps/unix/sysv/linux/time.c | 22 +
sysdeps/unix/sysv/linux/timer_gettime.c | 24 ++
sysdeps/unix/sysv/linux/timer_settime.c | 49 +++
sysdeps/unix/sysv/linux/timerfd_gettime64.c | 44 ++
sysdeps/unix/sysv/linux/timerfd_settime64.c | 71 +++
sysdeps/unix/sysv/linux/timespec_get.c | 35 ++
sysdeps/unix/sysv/linux/utimensat.c | 36 ++
sysdeps/unix/sysv/linux/utimes.c | 31 ++
sysdeps/unix/sysv/linux/xstat64.c | 50 +++
sysvipc/sys/msg.h | 9 +
time/Makefile | 4 +-
time/Versions | 16 +
time/adjtime.c | 10 +
time/bits/types/struct_timespec.h | 17 +
time/bits/types/struct_timeval.h | 9 +
time/bits/types/time_t.h | 4 +
time/ctime.c | 10 +
time/ctime_r.c | 9 +
time/difftime.c | 9 +
time/getitimer64.c | 51 +++
time/gettimeofday.c | 10 +
time/gmtime.c | 15 +
time/localtime.c | 17 +
time/mktime.c | 403 ++++++++++++++++++
time/nanosleep64.c | 61 +++
time/offtime.c | 64 +++
time/setitimer64.c | 69 +++
time/settimeofday.c | 8 +
time/stime.c | 17 +
time/sys/time.h | 74 ++++
time/time.c | 13 +
time/time.h | 161 ++++++-
time/timegm.c | 11 +
time/tzfile.c | 4 +-
time/tzset.c | 64 ++-
128 files changed, 6112 insertions(+), 35 deletions(-)
create mode 100644 posix/sched_rr_gi64.c
create mode 100644 resource/getrusage64.c
create mode 100644 rt/mq_timedreceive_t64.c
create mode 100644 rt/mq_timedsend_t64.c
create mode 100644 rt/timerfd_gettime64.c
create mode 100644 rt/timerfd_settime64.c
create mode 100644 sysdeps/unix/sysv/linux/settimeofday64.c
create mode 100644 sysdeps/unix/sysv/linux/stime.c
create mode 100644 sysdeps/unix/sysv/linux/timerfd_gettime64.c
create mode 100644 sysdeps/unix/sysv/linux/timerfd_settime64.c
create mode 100644 time/getitimer64.c
create mode 100644 time/nanosleep64.c
create mode 100644 time/setitimer64.c
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:28 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
bits/typesizes.h | 1 +
posix/bits/types.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/bits/typesizes.h b/bits/typesizes.h
index d407bf4067..a916cc1d0d 100644
--- a/bits/typesizes.h
+++ b/bits/typesizes.h
@@ -48,6 +48,7 @@
#define __ID_T_TYPE __U32_TYPE
#define __CLOCK_T_TYPE __SLONGWORD_TYPE
#define __TIME_T_TYPE __SLONGWORD_TYPE
+#define __TIME64_T_TYPE __SQUAD_TYPE
#define __USECONDS_T_TYPE __U32_TYPE
#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE
#define __DADDR_T_TYPE __S32_TYPE
diff --git a/posix/bits/types.h b/posix/bits/types.h
index e2f73a89e4..26f1e4542f 100644
--- a/posix/bits/types.h
+++ b/posix/bits/types.h
@@ -145,7 +145,8 @@ __STD_TYPE __CLOCK_T_TYPE __clock_t; /* Type of CPU usage counts. */
__STD_TYPE __RLIM_T_TYPE __rlim_t; /* Type for resource measurement. */
__STD_TYPE __RLIM64_T_TYPE __rlim64_t; /* Type for resource measurement (LFS). */
__STD_TYPE __ID_T_TYPE __id_t; /* General type for IDs. */
-__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch. */
+__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch, Y2038-unsafe. */
+__STD_TYPE __TIME64_T_TYPE __time64_t; /* Seconds since the Epoch, Y2038-safe. */
__STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds. */
__STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds. */
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:29 UTC
Permalink
Note: the implementation expects __time64_t arguments but returns
a double like its 32-bit-time counterpart, in order to remain as
source-code-compatible as possible, even though the precision of a
double is only about 55 bits.

The implementation is simpler than its 32-bit counterpart, as it
assumes that all __time64_t implementations are just 64-bit integers.

Also, the implementation does not require a Y2038-proof kernel.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/arm/Versions | 7 +++++++
time/difftime.c | 9 +++++++++
2 files changed, 16 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 7e5ba53455..d3655768c8 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -16,4 +16,11 @@ libc {
# nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
__vdso_clock_gettime;
}
+
+ # Y2038 symbols are given their own version until they can be put in
+ # the right place
+
+ GLIBC_Y2038 {
+ __difftime64;
+ }
}
diff --git a/time/difftime.c b/time/difftime.c
index e5e3311744..1b2494c727 100644
--- a/time/difftime.c
+++ b/time/difftime.c
@@ -119,3 +119,12 @@ __difftime (time_t time1, time_t time0)
return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
}
strong_alias (__difftime, difftime)
+
+/* Return the difference between 64-bit TIME1 and TIME0. */
+double
+__difftime64 (__time64_t time1, __time64_t time0)
+{
+ /* Subtract the smaller integer from the larger, convert the difference to
+ double, and then negate if needed. */
+ return time1 < time0 ? - (time0 - time1) : (time1 - time0);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:30 UTC
Permalink
This consists in the following implementation additions:

([file] 32-bit implementation -> [file] 64-bit addition)

time/ctime.c ctime() -> __ctime64()
time/ctime_r.c ctime_r() -> __ctime64_r()
time/gmtime.c gmtime() -> __gmtime64()
time/gmtime.c gmtime_r() -> __gmtime64_r()
time/localtime.c localtime() -> __localtime64()
time/localtime.c localtime_r() -> __localtime64_r()

which require the following internal function additions

time/offtime.c __offtime() -> __offtime64()
time/tzset.c __tz_convert() -> __tz64_convert()

and internal function (32-bit-time-compatible) changes

time/tzfile.c __tzfile_compute()
time/tzset.c tzset_internal()
time/tzset.c compute_change()

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 26 ++++++++++++---
sysdeps/unix/sysv/linux/arm/Versions | 3 ++
time/ctime.c | 10 ++++++
time/ctime_r.c | 9 +++++
time/gmtime.c | 15 +++++++++
time/localtime.c | 17 ++++++++++
time/offtime.c | 64 ++++++++++++++++++++++++++++++++++++
time/tzfile.c | 4 +--
time/tzset.c | 64 +++++++++++++++++++++++++++++++++---
9 files changed, 201 insertions(+), 11 deletions(-)

diff --git a/include/time.h b/include/time.h
index 9956b82eb8..d2b1080fd6 100644
--- a/include/time.h
+++ b/include/time.h
@@ -8,6 +8,8 @@ extern __typeof (strftime_l) __strftime_l;
libc_hidden_proto (__strftime_l)
extern __typeof (strptime_l) __strptime_l;

+extern struct tm *__localtime64 (const __time64_t *__timer);
+
libc_hidden_proto (time)
libc_hidden_proto (asctime)
libc_hidden_proto (mktime)
@@ -39,13 +41,13 @@ extern int __use_tzfile attribute_hidden;

extern void __tzfile_read (const char *file, size_t extra,
char **extrap);
-extern void __tzfile_compute (time_t timer, int use_localtime,
+extern void __tzfile_compute (__time64_t timer, int use_localtime,
long int *leap_correct, int *leap_hit,
struct tm *tp);
extern void __tzfile_default (const char *std, const char *dst,
long int stdoff, long int dstoff);
extern void __tzset_parse_tz (const char *tz);
-extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
+extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
__THROW internal_function;

/* Subroutine of `mktime'. Return the `time_t' representation of TP and
@@ -58,23 +60,37 @@ extern time_t __mktime_internal (struct tm *__tp,
extern struct tm *__localtime_r (const time_t *__timer,
struct tm *__tp) attribute_hidden;

-extern struct tm *__gmtime_r (const time_t *__restrict __timer,
+extern struct tm *__localtime64_r (const __time64_t *__timer,
+ struct tm *__tp) attribute_hidden;
+
+extern struct tm *__gmtime_r (const __time_t *__restrict __timer,
struct tm *__restrict __tp);
libc_hidden_proto (__gmtime_r)

+extern struct tm *__gmtime64_r (const __time64_t *__restrict __timer,
+ struct tm *__restrict __tp);
+
/* Compute the `struct tm' representation of *T,
offset OFFSET seconds east of UTC,
and store year, yday, mon, mday, wday, hour, min, sec into *TP.
Return nonzero if successful. */
-extern int __offtime (const time_t *__timer,
+extern int __offtime (const __time_t *__timer,
long int __offset,
struct tm *__tp);

+extern int __offtime64 (const __time64_t *__timer,
+ long int __offset,
+ struct tm *__tp);
+
extern char *__asctime_r (const struct tm *__tp, char *__buf);
extern void __tzset (void);

/* Prototype for the internal function to get information based on TZ. */
-extern struct tm *__tz_convert (const time_t *timer, int use_localtime, struct tm *tp);
+extern struct tm *__tz_convert (const __time_t *timer, int use_localtime,
+ struct tm *tp);
+
+extern struct tm *__tz_convert64 (const __time64_t *timer,
+ int use_localtime, struct tm *tp);

extern int __nanosleep (const struct timespec *__requested_time,
struct timespec *__remaining);
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index d3655768c8..dd6a160c75 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -22,5 +22,8 @@ libc {

GLIBC_Y2038 {
__difftime64;
+ __ctime64; __ctime64_r;
+ __gmtime64; __gmtime64_r;
+ __localtime64; __localtime64_r;
}
}
diff --git a/time/ctime.c b/time/ctime.c
index 7baca1bb57..a5150c1845 100644
--- a/time/ctime.c
+++ b/time/ctime.c
@@ -26,3 +26,13 @@ ctime (const time_t *t)
In particular, ctime and asctime must yield the same pointer. */
return asctime (localtime (t));
}
+
+/* Return a string as returned by asctime which
+ is the representation of *T in that form. */
+char *
+__ctime64 (const __time64_t *t)
+{
+ /* Apply the same rule as ctime:
+ make ctime64 (t) is equivalent to asctime (localtime64 (t)). */
+ return asctime (__localtime64 (t));
+}
diff --git a/time/ctime_r.c b/time/ctime_r.c
index ecd7731038..74d856f17e 100644
--- a/time/ctime_r.c
+++ b/time/ctime_r.c
@@ -27,3 +27,12 @@ ctime_r (const time_t *t, char *buf)
struct tm tm;
return __asctime_r (__localtime_r (t, &tm), buf);
}
+
+/* Return a string as returned by asctime which is the representation
+ of *T in that form. Reentrant Y2038-proof version. */
+char *
+__ctime64_r (const __time64_t *t, char *buf)
+{
+ struct tm tm;
+ return __asctime_r (__localtime64_r (t, &tm), buf);
+}
diff --git a/time/gmtime.c b/time/gmtime.c
index 049d551cdf..7662c1d1f7 100644
--- a/time/gmtime.c
+++ b/time/gmtime.c
@@ -35,3 +35,18 @@ gmtime (const time_t *t)
{
return __tz_convert (t, 0, &_tmbuf);
}
+
+/* Return the `struct tm' representation of 64-bit-time *T
+ in UTC, using *TP to store the result. */
+struct tm *
+__gmtime64_r (const __time64_t *t, struct tm *tp)
+{
+ return __tz_convert64 (t, 0, tp);
+}
+
+/* Return the `struct tm' representation of 64-bit-time *T in UTC. */
+struct tm *
+__gmtime64 (const __time64_t *t)
+{
+ return __tz_convert64 (t, 0, &_tmbuf);
+}
diff --git a/time/localtime.c b/time/localtime.c
index 07dd67ca71..fd2d997e60 100644
--- a/time/localtime.c
+++ b/time/localtime.c
@@ -39,3 +39,20 @@ localtime (const time_t *t)
return __tz_convert (t, 1, &_tmbuf);
}
libc_hidden_def (localtime)
+
+/* 64-bit-time versions */
+
+/* Return the `struct tm' representation of *T in local time,
+ using *TP to store the result. */
+struct tm *
+__localtime64_r (const __time64_t *t, struct tm *tp)
+{
+ return __tz_convert64 (t, 1, tp);
+}
+
+/* Return the `struct tm' representation of *T in local time. */
+struct tm *
+__localtime64 (const __time64_t *t)
+{
+ return __tz_convert64 (t, 1, &_tmbuf);
+}
diff --git a/time/offtime.c b/time/offtime.c
index 75a28fed84..84237db440 100644
--- a/time/offtime.c
+++ b/time/offtime.c
@@ -84,3 +84,67 @@ __offtime (const time_t *t, long int offset, struct tm *tp)
tp->tm_mday = days + 1;
return 1;
}
+
+/* Compute the `struct tm' representation of 64-bit-time *T,
+ offset OFFSET seconds east of UTC,
+ and store year, yday, mon, mday, wday, hour, min, sec into *TP.
+ Return nonzero if successful. */
+int
+__offtime64 (const __time64_t *t, long int offset, struct tm *tp)
+{
+ __time64_t days, rem, y;
+ const unsigned short int *ip;
+
+ days = *t / SECS_PER_DAY;
+ rem = *t % SECS_PER_DAY;
+ rem += offset;
+ while (rem < 0)
+ {
+ rem += SECS_PER_DAY;
+ --days;
+ }
+ while (rem >= SECS_PER_DAY)
+ {
+ rem -= SECS_PER_DAY;
+ ++days;
+ }
+ tp->tm_hour = rem / SECS_PER_HOUR;
+ rem %= SECS_PER_HOUR;
+ tp->tm_min = rem / 60;
+ tp->tm_sec = rem % 60;
+ /* January 1, 1970 was a Thursday. */
+ tp->tm_wday = (4 + days) % 7;
+ if (tp->tm_wday < 0)
+ tp->tm_wday += 7;
+ y = 1970;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+
+ while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+ {
+ /* Guess a corrected year, assuming 365 days per year. */
+ __time64_t yg = y + days / 365 - (days % 365 < 0);
+
+ /* Adjust DAYS and Y to match the guessed year. */
+ days -= ((yg - y) * 365
+ + LEAPS_THRU_END_OF (yg - 1)
+ - LEAPS_THRU_END_OF (y - 1));
+ y = yg;
+ }
+ tp->tm_year = y - 1900;
+ if (tp->tm_year != y - 1900)
+ {
+ /* The year cannot be represented due to overflow. */
+ __set_errno (EOVERFLOW);
+ return 0;
+ }
+ tp->tm_yday = days;
+ ip = __mon_yday[__isleap(y)];
+ for (y = 11; days < (long int) ip[y]; --y)
+ continue;
+ days -= ip[y];
+ tp->tm_mon = y;
+ tp->tm_mday = days + 1;
+ return 1;
+}
diff --git a/time/tzfile.c b/time/tzfile.c
index d41246980b..9da9d0b38b 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -630,7 +630,7 @@ __tzfile_default (const char *std, const char *dst,
}

void
-__tzfile_compute (time_t timer, int use_localtime,
+__tzfile_compute (__time64_t timer, int use_localtime,
long int *leap_correct, int *leap_hit,
struct tm *tp)
{
@@ -685,7 +685,7 @@ __tzfile_compute (time_t timer, int use_localtime,

/* Convert to broken down structure. If this fails do not
use the string. */
- if (__glibc_unlikely (! __offtime (&timer, 0, tp)))
+ if (__glibc_unlikely (! __offtime64 (&timer, 0, tp)))
goto use_last;

/* Use the rules from the TZ string to compute the change. */
diff --git a/time/tzset.c b/time/tzset.c
index cf5fe969b6..ee462107e1 100644
--- a/time/tzset.c
+++ b/time/tzset.c
@@ -55,7 +55,7 @@ typedef struct

/* We cache the computed time of change for a
given year so we don't have to recompute it. */
- time_t change; /* When to change to this zone. */
+ __time64_t change; /* When to change to this zone. */
int computed_for; /* Year above is computed for. */
} tz_rule;

@@ -417,7 +417,7 @@ tzset_internal (int always)
tz_rules[0].name = tz_rules[1].name = "UTC";
if (J0 != 0)
tz_rules[0].type = tz_rules[1].type = J0;
- tz_rules[0].change = tz_rules[1].change = (time_t) -1;
+ tz_rules[0].change = tz_rules[1].change = (__time64_t) -1;
update_vars ();
return;
}
@@ -516,10 +516,11 @@ compute_change (tz_rule *rule, int year)


/* Figure out the correct timezone for TM and set `__tzname',
- `__timezone', and `__daylight' accordingly. */
+ `__timezone', and `__daylight' accordingly.
+ NOTE: this takes a __time64_t value, so passing a __time_t value is OK. */
void
internal_function
-__tz_compute (time_t timer, struct tm *tm, int use_localtime)
+__tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
{
compute_change (&tz_rules[0], 1900 + tm->tm_year);
compute_change (&tz_rules[1], 1900 + tm->tm_year);
@@ -620,6 +621,61 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
}


+/* Return the `struct tm' representation of *TIMER in the local timezone.
+ Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */
+struct tm *
+__tz_convert64 (const __time64_t *timer, int use_localtime, struct tm *tp)
+{
+ long int leap_correction;
+ int leap_extra_secs;
+
+ if (timer == NULL)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ __libc_lock_lock (tzset_lock);
+
+ /* Update internal database according to current TZ setting.
+ POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
+ This is a good idea since this allows at least a bit more parallelism. */
+ tzset_internal (tp == &_tmbuf && use_localtime);
+
+ if (__use_tzfile)
+ __tzfile_compute (*timer, use_localtime, &leap_correction,
+ &leap_extra_secs, tp);
+ else
+ {
+ if (! __offtime64 (timer, 0, tp))
+ tp = NULL;
+ else
+ __tz_compute (*timer, tp, use_localtime);
+ leap_correction = 0L;
+ leap_extra_secs = 0;
+ }
+
+ __libc_lock_unlock (tzset_lock);
+
+ if (tp)
+ {
+ if (! use_localtime)
+ {
+ tp->tm_isdst = 0;
+ tp->tm_zone = "GMT";
+ tp->tm_gmtoff = 0L;
+ }
+
+ if (__offtime64 (timer, tp->tm_gmtoff - leap_correction, tp))
+ tp->tm_sec += leap_extra_secs;
+ else
+ tp = NULL;
+ }
+
+ return tp;
+}
+
+
libc_freeres_fn (free_mem)
{
while (tzstring_list != NULL)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:31 UTC
Permalink
__mktime64 is designed similar to mktime, including checks on (64-bit)
integer limits, and respects the same Posix requirements as __mktime does,
i.e. calls tzset().

timelocal is a macro which evaluates to mktime, so when APIs are enabled,
both mktime and timelocal will become Y2038-proof

Also, the implementation does not require a Y2038-proof kernel.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 9 +
sysdeps/unix/sysv/linux/arm/Versions | 1 +
time/mktime.c | 403 +++++++++++++++++++++++++++++++++++
3 files changed, 413 insertions(+)

diff --git a/include/time.h b/include/time.h
index d2b1080fd6..79ab6ab6a1 100644
--- a/include/time.h
+++ b/include/time.h
@@ -57,6 +57,15 @@ extern time_t __mktime_internal (struct tm *__tp,
struct tm *(*__func) (const time_t *,
struct tm *),
time_t *__offset);
+
+/* Subroutine of `__mktime64'. Return the `__time64_t' representation of TP and
+ normalize TP, given that a `struct tm *' maps to a `__time64_t' as performed
+ by FUNC. Keep track of next guess for __time64_t offset in *OFFSET. */
+extern __time64_t __mktime64_internal (struct tm *__tp,
+ struct tm *(*__func) (const __time64_t *,
+ struct tm *),
+ __time64_t *__offset);
+
extern struct tm *__localtime_r (const time_t *__timer,
struct tm *__tp) attribute_hidden;

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index dd6a160c75..546d7c60ee 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -25,5 +25,6 @@ libc {
__ctime64; __ctime64_r;
__gmtime64; __gmtime64_r;
__localtime64; __localtime64_r;
+ __mktime64; __timelocal64_r;
}
}
diff --git a/time/mktime.c b/time/mktime.c
index 4c48d358a1..c0ba4e5761 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -599,6 +599,409 @@ weak_alias (mktime, timelocal)
libc_hidden_def (mktime)
libc_hidden_weak (timelocal)
#endif
+
+/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
+ (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
+ were not adjusted between the time stamps.
+
+ The YEAR values uses the same numbering as TP->tm_year. Values
+ need not be in the usual range. However, YEAR1 must not be less
+ than 2 * INT_MIN or greater than 2 * INT_MAX.
+
+ The result may overflow. It is the caller's responsibility to
+ detect overflow. */
+
+static __time64_t
+ydhms64_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
+ int year0, int yday0, int hour0, int min0, int sec0)
+{
+ verify (C99_integer_division, -1 / 2 == 0);
+
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid integer overflow here. */
+ int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
+ int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = SHR (a100, 2);
+ int b400 = SHR (b100, 2);
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+
+ /* Compute the desired time in __time64_t precision. Overflow might
+ occur here. */
+ __time64_t tyear1 = year1;
+ __time64_t years = tyear1 - year0;
+ __time64_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
+ __time64_t hours = 24 * days + hour1 - hour0;
+ __time64_t minutes = 60 * hours + min1 - min0;
+ __time64_t seconds = 60 * minutes + sec1 - sec0;
+ return seconds;
+}
+
+/* Return the average of A and B, even if A + B would overflow. */
+static __time64_t
+time64_t_avg (__time64_t a, __time64_t b)
+{
+ return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
+}
+
+/* Return 1 if A + B does not overflow. If __time64_t is unsigned and if
+ B's top bit is set, assume that the sum represents A - -B, and
+ return 1 if the subtraction does not wrap around. */
+static int
+time64_t_add_ok (__time64_t a, __time64_t b)
+{
+ if (! TYPE_SIGNED (__time64_t))
+ {
+ __time64_t sum = a + b;
+ return (sum < a) == (TIME_T_MIDPOINT <= b);
+ }
+ else if (WRAPV)
+ {
+ __time64_t sum = a + b;
+ return (sum < a) == (b < 0);
+ }
+ else
+ {
+ __time64_t avg = time64_t_avg (a, b);
+ return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+ }
+}
+
+/* Return 1 if A + B does not overflow. */
+static int
+time64_t_int_add_ok (__time64_t a, int b)
+{
+ verify (int_no_wider_than_time64_t, INT_MAX <= TIME_T_MAX);
+ if (WRAPV)
+ {
+ __time64_t sum = a + b;
+ return (sum < a) == (b < 0);
+ }
+ else
+ {
+ int a_odd = a & 1;
+ __time64_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
+ return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+ }
+}
+
+/* Return a __time64_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
+ assuming that *T corresponds to *TP and that no clock adjustments
+ occurred between *TP and the desired time.
+ If TP is null, return a value not equal to *T; this avoids false matches.
+ If overflow occurs, yield the minimal or maximal value, except do not
+ yield a value equal to *T. */
+static __time64_t
+guess_time64_tm (long_int year, long_int yday, int hour, int min, int sec,
+ const __time64_t *t, const struct tm *tp)
+{
+ if (tp)
+ {
+ __time64_t d = ydhms64_diff (year, yday, hour, min, sec,
+ tp->tm_year, tp->tm_yday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ if (time64_t_add_ok (*t, d))
+ return *t + d;
+ }
+
+ /* Overflow occurred one way or another. Return the nearest result
+ that is actually in range, except don't report a zero difference
+ if the actual difference is nonzero, as that would cause a false
+ match; and don't oscillate between two values, as that would
+ confuse the spring-forward gap detector. */
+ return (*t < TIME_T_MIDPOINT
+ ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
+ : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
+}
+
+/* Use CONVERT to convert *T to a broken down time in *TP.
+ If *T is out of range for conversion, adjust it so that
+ it is the nearest in-range value and then convert that. */
+static struct tm *
+ranged64_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
+ __time64_t *t, struct tm *tp)
+{
+ struct tm *r = convert (t, tp);
+
+ if (!r && *t)
+ {
+ __time64_t bad = *t;
+ __time64_t ok = 0;
+
+ /* BAD is a known unconvertible __time64_t, and OK is a known good one.
+ Use binary search to narrow the range between BAD and OK until
+ they differ by 1. */
+ while (bad != ok + (bad < 0 ? -1 : 1))
+ {
+ __time64_t mid = *t = time64_t_avg (ok, bad);
+ r = convert (t, tp);
+ if (r)
+ ok = mid;
+ else
+ bad = mid;
+ }
+
+ if (!r && ok)
+ {
+ /* The last conversion attempt failed;
+ revert to the most recent successful attempt. */
+ *t = ok;
+ r = convert (t, tp);
+ }
+ }
+
+ return r;
+}
+
+
+/* Convert *TP to a __time64_t value, inverting
+ the monotonic and mostly-unit-linear conversion function CONVERT.
+ Use *OFFSET to keep track of a guess at the offset of the result,
+ compared to what the result would be for UTC without leap seconds.
+ If *OFFSET's guess is correct, only one CONVERT call is needed.
+ This function is external because it is used also by timegm.c. */
+__time64_t
+__mktime64_internal (struct tm *tp,
+ struct tm *(*convert) (const __time64_t *, struct tm *),
+ __time64_t *offset)
+{
+ __time64_t t, gt, t0, t1, t2;
+ struct tm tm;
+
+ /* The maximum number of probes (calls to CONVERT) should be enough
+ to handle any combinations of time zone rule changes, solar time,
+ leap seconds, and oscillations around a spring-forward gap.
+ POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
+ int remaining_probes = 6;
+
+ /* Time requested. Copy it in case CONVERT modifies *TP; this can
+ occur if TP is localtime's returned value and CONVERT is localtime. */
+ int sec = tp->tm_sec;
+ int min = tp->tm_min;
+ int hour = tp->tm_hour;
+ int mday = tp->tm_mday;
+ int mon = tp->tm_mon;
+ int year_requested = tp->tm_year;
+ int isdst = tp->tm_isdst;
+
+ /* 1 if the previous probe was DST. */
+ int dst2;
+
+ /* Ensure that mon is in range, and set year accordingly. */
+ int mon_remainder = mon % 12;
+ int negative_mon_remainder = mon_remainder < 0;
+ int mon_years = mon / 12 - negative_mon_remainder;
+ long_int lyear_requested = year_requested;
+ long_int year = lyear_requested + mon_years;
+
+ /* The other values need not be in range:
+ the remaining code handles minor overflows correctly,
+ assuming int and __time64_t arithmetic wraps around.
+ Major overflows are caught at the end. */
+
+ /* Calculate day of year from year, month, and day of month.
+ The result need not be in range. */
+ int mon_yday = ((__mon_yday[leapyear (year)]
+ [mon_remainder + 12 * negative_mon_remainder])
+ - 1);
+ long_int lmday = mday;
+ long_int yday = mon_yday + lmday;
+
+ __time64_t guessed_offset = *offset;
+
+ int sec_requested = sec;
+
+ if (LEAP_SECONDS_POSSIBLE)
+ {
+ /* Handle out-of-range seconds specially,
+ since ydhms_tm_diff assumes every minute has 60 seconds. */
+ if (sec < 0)
+ sec = 0;
+ if (59 < sec)
+ sec = 59;
+ }
+
+ /* Invert CONVERT by probing. First assume the same offset as last
+ time. */
+
+ t0 = ydhms64_diff (year, yday, hour, min, sec,
+ EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
+
+ if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
+ {
+ /* __time64_t isn't large enough to rule out overflows, so check
+ for major overflows. A gross check suffices, since if t0
+ has overflowed, it is off by a multiple of TIME_T_MAX -
+ TIME_T_MIN + 1. So ignore any component of the difference
+ that is bounded by a small value. */
+
+ /* Approximate log base 2 of the number of time units per
+ biennium. A biennium is 2 years; use this unit instead of
+ years to avoid integer overflow. For example, 2 average
+ Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
+ which is 63113904 seconds, and rint (log2 (63113904)) is
+ 26. */
+ int ALOG2_SECONDS_PER_BIENNIUM = 26;
+ int ALOG2_MINUTES_PER_BIENNIUM = 20;
+ int ALOG2_HOURS_PER_BIENNIUM = 14;
+ int ALOG2_DAYS_PER_BIENNIUM = 10;
+ int LOG2_YEARS_PER_BIENNIUM = 1;
+
+ int approx_requested_biennia =
+ (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
+ - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
+ + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
+ + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
+ + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
+ + (LEAP_SECONDS_POSSIBLE
+ ? 0
+ : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
+
+ int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
+ int diff = approx_biennia - approx_requested_biennia;
+ int approx_abs_diff = diff < 0 ? -1 - diff : diff;
+
+ /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
+ gives a positive value of 715827882. Setting a variable
+ first then doing math on it seems to work.
+ (***@caip.rutgers.edu) */
+ __time64_t time64_t_max = TIME_T_MAX;
+ __time64_t time64_t_min = TIME_T_MIN;
+ __time64_t overflow_threshold =
+ (time64_t_max / 3 - time64_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
+
+ if (overflow_threshold < approx_abs_diff)
+ {
+ /* Overflow occurred. Try repairing it; this might work if
+ the time zone offset is enough to undo the overflow. */
+ __time64_t repaired_t0 = -1 - t0;
+ approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
+ diff = approx_biennia - approx_requested_biennia;
+ approx_abs_diff = diff < 0 ? -1 - diff : diff;
+ if (overflow_threshold < approx_abs_diff)
+ return -1;
+ guessed_offset += repaired_t0 - t0;
+ t0 = repaired_t0;
+ }
+ }
+
+ /* Repeatedly use the error to improve the guess. */
+
+ for (t = t1 = t2 = t0, dst2 = 0;
+ (gt = guess_time64_tm (year, yday, hour, min, sec, &t,
+ ranged64_convert (convert, &t, &tm)),
+ t != gt);
+ t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
+ if (t == t1 && t != t2
+ && (tm.tm_isdst < 0
+ || (isdst < 0
+ ? dst2 <= (tm.tm_isdst != 0)
+ : (isdst != 0) != (tm.tm_isdst != 0))))
+ /* We can't possibly find a match, as we are oscillating
+ between two values. The requested time probably falls
+ within a spring-forward gap of size GT - T. Follow the common
+ practice in this case, which is to return a time that is GT - T
+ away from the requested time, preferring a time whose
+ tm_isdst differs from the requested value. (If no tm_isdst
+ was requested and only one of the two values has a nonzero
+ tm_isdst, prefer that value.) In practice, this is more
+ useful than returning -1. */
+ goto offset_found;
+ else if (--remaining_probes == 0)
+ return -1;
+
+ /* We have a match. Check whether tm.tm_isdst has the requested
+ value, if any. */
+ if (isdst_differ (isdst, tm.tm_isdst))
+ {
+ /* tm.tm_isdst has the wrong value. Look for a neighboring
+ time with the right value, and use its UTC offset.
+
+ Heuristic: probe the adjacent timestamps in both directions,
+ looking for the desired isdst. This should work for all real
+ time zone histories in the tz database. */
+
+ /* Distance between probes when looking for a DST boundary. In
+ tzdata2003a, the shortest period of DST is 601200 seconds
+ (e.g., America/Recife starting 2000-10-08 01:00), and the
+ shortest period of non-DST surrounded by DST is 694800
+ seconds (Africa/Tunis starting 1943-04-17 01:00). Use the
+ minimum of these two values, so we don't miss these short
+ periods when probing. */
+ int stride = 601200;
+
+ /* The longest period of DST in tzdata2003a is 536454000 seconds
+ (e.g., America/Jujuy starting 1946-10-01 01:00). The longest
+ period of non-DST is much longer, but it makes no real sense
+ to search for more than a year of non-DST, so use the DST
+ max. */
+ int duration_max = 536454000;
+
+ /* Search in both directions, so the maximum distance is half
+ the duration; add the stride to avoid off-by-1 problems. */
+ int delta_bound = duration_max / 2 + stride;
+
+ int delta, direction;
+
+ for (delta = stride; delta < delta_bound; delta += stride)
+ for (direction = -1; direction <= 1; direction += 2)
+ if (time64_t_int_add_ok (t, delta * direction))
+ {
+ __time64_t ot = t + delta * direction;
+ struct tm otm;
+ ranged64_convert (convert, &ot, &otm);
+ if (! isdst_differ (isdst, otm.tm_isdst))
+ {
+ /* We found the desired tm_isdst.
+ Extrapolate back to the desired time. */
+ t = guess_time64_tm (year, yday, hour, min, sec, &ot, &otm);
+ ranged64_convert (convert, &t, &tm);
+ goto offset_found;
+ }
+ }
+ }
+
+ offset_found:
+ *offset = guessed_offset + t - t0;
+
+ if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
+ {
+ /* Adjust time to reflect the tm_sec requested, not the normalized value.
+ Also, repair any damage from a false match due to a leap second. */
+ int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
+ if (! time64_t_int_add_ok (t, sec_requested))
+ return -1;
+ t1 = t + sec_requested;
+ if (! time64_t_int_add_ok (t1, sec_adjustment))
+ return -1;
+ t2 = t1 + sec_adjustment;
+ if (! convert (&t2, &tm))
+ return -1;
+ t = t2;
+ }
+
+ *tp = tm;
+ return t;
+}
+
+
+/* This uses a signed type wide enough to hold any UTC offset in seconds. */
+static __time64_t localtime64_offset;
+
+/* Convert *TP to a __time64_t value. */
+__time64_t
+__mktime64 (struct tm *tp)
+{
+#ifdef _LIBC
+ /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+ time zone names contained in the external variable 'tzname' shall
+ be set as if the tzset() function had been called. */
+ __tzset ();
+#endif
+
+ return __mktime64_internal (tp, __localtime64_r, &localtime64_offset);
+}

#if defined DEBUG_MKTIME && DEBUG_MKTIME
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:32 UTC
Permalink
Implementation is based on the same __mktime64_internal function
which was introduced in the '__mktime64' implementation change.

Again, the implementation does not require a Y2038-proof kernel.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/arm/Versions | 1 +
time/timegm.c | 11 +++++++++++
2 files changed, 12 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 546d7c60ee..f7feda3650 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -26,5 +26,6 @@ libc {
__gmtime64; __gmtime64_r;
__localtime64; __localtime64_r;
__mktime64; __timelocal64_r;
+ __timegm64;
}
}
diff --git a/time/timegm.c b/time/timegm.c
index b0f5d16d16..0c8879285a 100644
--- a/time/timegm.c
+++ b/time/timegm.c
@@ -36,6 +36,9 @@
time_t __mktime_internal (struct tm *,
struct tm * (*) (time_t const *, struct tm *),
time_t *);
+__time64_t __mktime64_internal (struct tm *,
+ struct tm * (*) (__time64_t const *, struct tm *),
+ __time64_t *);
#endif

time_t
@@ -45,3 +48,11 @@ timegm (struct tm *tmp)
tmp->tm_isdst = 0;
return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
}
+
+__time64_t
+__timegm64 (struct tm *tmp)
+{
+ static __time64_t gmtime64_offset;
+ tmp->tm_isdst = 0;
+ return __mktime64_internal (tmp, __gmtime64_r, &gmtime64_offset);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:33 UTC
Permalink
To be Y2038-proof, struct __timespec64 needs its tv_sec field to
be a __time64_t rather than a __time_t. However, the question is
which type should the tv_nsec field be.

Keeping tv_nsec a long (32-bit) would be compatible with Posix
requirements but would result in the GLIBC struct timespec being
binary-incompatible with the Linux 64-bit struct timespec, which
contains a 64-bit, not 32-bit, signed tv_nsec field.

In order to maintain Posix compatibility yet simplify conversion
between Posix and Linux struct timespec values, the Y2038-proof
struct time stores its tv_nsec field as a 32-bit signed integer
plus a padding which can serve as a 64-bit sign extension. This
both meets Posix requirements and makes the GLIBC and Linux
struct timespec binary compatible.

Note that in the API (which is not modified here, and will be
later alongside all Y2038-sensitive APIs), this padding is made
'invisible' by defining it as an anonymous bitfield; whereas
the struct __timespec64 introduced here has a named field for
the padding, allowing implementations to read and write it.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/include/time.h b/include/time.h
index 79ab6ab6a1..c436c44539 100644
--- a/include/time.h
+++ b/include/time.h
@@ -4,6 +4,8 @@
#ifndef _ISOMAC
# include <bits/types/locale_t.h>

+#include <endian.h>
+
extern __typeof (strftime_l) __strftime_l;
libc_hidden_proto (__strftime_l)
extern __typeof (strptime_l) __strptime_l;
@@ -18,6 +20,22 @@ libc_hidden_proto (localtime)
libc_hidden_proto (strftime)
libc_hidden_proto (strptime)

+#if BYTE_ORDER == BIG_ENDIAN
+struct __timespec64
+{
+ __time64_t tv_sec; /* Seconds */
+ int tv_pad: 32; /* Padding named for checking/setting */
+ __syscall_slong_t tv_nsec; /* Nanoseconds */
+};
+#else
+struct __timespec64
+{
+ __time64_t tv_sec; /* Seconds */
+ __syscall_slong_t tv_nsec; /* Nanoseconds */
+ int tv_pad: 32; /* Padding named for checking/setting */
+};
+#endif
+
extern __typeof (clock_getres) __clock_getres;
extern __typeof (clock_gettime) __clock_gettime;
libc_hidden_proto (__clock_gettime)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:34 UTC
Permalink
Note: __clock_gettime64 is implemented in VDSO.
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 8 ++++++
sysdeps/unix/clock_gettime.c | 46 ++++++++++++++++++++++++++++++++
sysdeps/unix/sysv/linux/arm/Versions | 3 +++
sysdeps/unix/sysv/linux/arm/init-first.c | 15 +++++++++++
sysdeps/unix/sysv/linux/arm/libc-vdso.h | 1 +
sysdeps/unix/sysv/linux/clock_gettime.c | 44 ++++++++++++++++++++++++++++++
6 files changed, 117 insertions(+)

diff --git a/include/time.h b/include/time.h
index c436c44539..eeefbb4e98 100644
--- a/include/time.h
+++ b/include/time.h
@@ -20,6 +20,11 @@ libc_hidden_proto (localtime)
libc_hidden_proto (strftime)
libc_hidden_proto (strptime)

+/* Indicates whether the underlying kernel has 64-bit time support.
+ This is required for e.g. librt, which cannot directly check the
+ flag variable that init-first.c sets when detecting support. */
+extern int __y2038_kernel_support (void);
+
#if BYTE_ORDER == BIG_ENDIAN
struct __timespec64
{
@@ -43,6 +48,9 @@ extern __typeof (clock_settime) __clock_settime;
extern __typeof (clock_nanosleep) __clock_nanosleep;
extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;

+extern int __clock_gettime64 (clockid_t __clock_id,
+ struct __timespec64 *__tp) __THROW;
+
/* Now define the internal interfaces. */
struct tm;

diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 5262066f51..ac224c919b 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -134,3 +134,49 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
}
weak_alias (__clock_gettime, clock_gettime)
libc_hidden_def (__clock_gettime)
+
+/* Get current value of CLOCK and store it in TP, 64-bit version. */
+int
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
+{
+ int retval = -1;
+
+ switch (clock_id)
+ {
+#ifdef SYSDEP_GETTIME64
+ SYSDEP_GETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+ case CLOCK_REALTIME:
+ {
+ struct timeval tv;
+ retval = gettimeofday (&tv, NULL);
+ if (retval == 0)
+ TIMEVAL_TO_TIMESPEC (&tv, tp);
+ }
+ break;
+#endif
+
+ default:
+#ifdef SYSDEP_GETTIME64_CPU
+ SYSDEP_GETTIME64_CPU (clock_id, tp);
+#endif
+#if HP_TIMING_AVAIL
+ if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+ == CLOCK_THREAD_CPUTIME_ID)
+ retval = hp_timing_gettime (clock_id, tp);
+ else
+#endif
+ __set_errno (EINVAL);
+ break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+ case CLOCK_PROCESS_CPUTIME_ID:
+ retval = hp_timing_gettime (clock_id, tp);
+ break;
+#endif
+ }
+
+ return retval;
+}
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index f7feda3650..a2655d6262 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -27,5 +27,8 @@ libc {
__localtime64; __localtime64_r;
__mktime64; __timelocal64_r;
__timegm64;
+ __clock_gettime64;
+ __vdso_clock_gettime64;
+ __y2038_kernel_support;
}
}
diff --git a/sysdeps/unix/sysv/linux/arm/init-first.c b/sysdeps/unix/sysv/linux/arm/init-first.c
index 3c289c2a25..61c01a56a7 100644
--- a/sysdeps/unix/sysv/linux/arm/init-first.c
+++ b/sysdeps/unix/sysv/linux/arm/init-first.c
@@ -23,6 +23,14 @@

int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *) attribute_hidden;
int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);
+
+int __y2038_linux_support;
+
+int __y2038_kernel_support (void)
+{
+ return __y2038_linux_support;
+}

static inline void
_libc_vdso_platform_setup (void)
@@ -36,6 +44,13 @@ _libc_vdso_platform_setup (void)
p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
PTR_MANGLE (p);
VDSO_SYMBOL (clock_gettime) = p;
+
+ /* (aaribaud) TODO: map to version where clock_gettime64 officially appears */
+ p = _dl_vdso_vsym ("__vdso_clock_gettime64", NULL);
+ PTR_MANGLE (p);
+ VDSO_SYMBOL (clock_gettime64) = p;
+
+ __y2038_linux_support = (p != NULL) ? 1 : 0;
}

# define VDSO_SETUP _libc_vdso_platform_setup
diff --git a/sysdeps/unix/sysv/linux/arm/libc-vdso.h b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
index ae37b574e1..ee0e5941c0 100644
--- a/sysdeps/unix/sysv/linux/arm/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
@@ -27,6 +27,7 @@
extern int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *)
attribute_hidden;
extern int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+extern long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);

#endif

diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index e232f69a4f..df4e16e6db 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -44,4 +44,48 @@
break
#define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */

+/* 64-bit versions */
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+ kernel. */
+#define SYSDEP_GETTIME64 \
+ SYSDEP_GETTIME64_CPUTIME; \
+ case CLOCK_REALTIME: \
+ case CLOCK_MONOTONIC: \
+ if (__y2038_linux_support) \
+ { \
+ retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); \
+ } \
+ else \
+ { \
+ retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); \
+ if (retval==0) \
+ { \
+ tp->tv_sec = ts32.tv_sec; \
+ tp->tv_nsec = ts32.tv_nsec; \
+ tp->tv_pad = 0; \
+ } \
+ } \
+ break
+
+#define SYSDEP_GETTIME64_CPU(clock_id, tp) \
+ if (__y2038_linux_support) \
+ { \
+ retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp); \
+ } \
+ else \
+ { \
+ retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32); \
+ if (retval==0) \
+ { \
+ tp->tv_sec = ts32.tv_sec; \
+ tp->tv_nsec = ts32.tv_nsec; \
+ tp->tv_pad = 0; \
+ } \
+ } \
+ break
+#define SYSDEP_GETTIME64_CPUTIME \
+ struct timespec ts32; \
+ extern int __y2038_linux_support;
+
#include <sysdeps/unix/clock_gettime.c>
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:35 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 2 ++
sysdeps/unix/clock_settime.c | 56 ++++++++++++++++++++++++++++++++-
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/clock_settime.c | 23 ++++++++++++++
4 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index eeefbb4e98..63237e23f4 100644
--- a/include/time.h
+++ b/include/time.h
@@ -50,6 +50,8 @@ extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;

extern int __clock_gettime64 (clockid_t __clock_id,
struct __timespec64 *__tp) __THROW;
+extern int __clock_settime64 (clockid_t __clock_id,
+ const struct __timespec64 *__tp) __THROW;

/* Now define the internal interfaces. */
struct tm;
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index e744cae6a9..8d7de2a310 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -68,8 +68,62 @@ hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
}
#endif

+/* Set CLOCK to value TP, 64-bit Y2038-safe version. */
+int
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
+{
+ int retval = EOVERFLOW;
+
+ /* Make sure the time cvalue is OK. */
+ if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ switch (clock_id)
+ {
+#define HANDLE_REALTIME \
+ do { \
+ struct timeval tv; \
+ TIMESPEC_TO_TIMEVAL (&tv, tp); \
+ \
+ retval = settimeofday (&tv, NULL); \
+ } while (0)
+
+#ifdef SYSDEP_SETTIME64
+ SYSDEP_SETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+ case CLOCK_REALTIME:
+ HANDLE_REALTIME;
+ break;
+#endif
+
+ default:
+#ifdef SYSDEP_SETTIME64_CPU
+ SYSDEP_SETTIME64_CPU;
+#endif
+#ifndef HANDLED_CPUTIME
+# if HP_TIMING_AVAIL
+ if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
+ || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
+ retval = hp_timing_settime (clock_id, tp);
+ else
+# endif
+ {
+ __set_errno (EINVAL);
+ retval = -1;
+ }
+#endif
+ break;
+ }
+
+ return retval;
+}

-/* Set CLOCK to value TP. */
+/* Set CLOCK to value TP, 64-bit Y2038-unsafe version. */
int
__clock_settime (clockid_t clock_id, const struct timespec *tp)
{
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index a2655d6262..553cdd7543 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -30,5 +30,6 @@ libc {
__clock_gettime64;
__vdso_clock_gettime64;
__y2038_kernel_support;
+ __clock_settime64;
}
}
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 058c518e5a..40760ff494 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -35,4 +35,27 @@
#define SYSDEP_SETTIME_CPU \
retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)

+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+#define SYSDEP_SETTIME64 \
+ case CLOCK_REALTIME: \
+ if (__y2038_linux_support) \
+ { \
+ struct __timespec64 ts64; \
+ ts64.tv_sec = tp->tv_sec; \
+ ts64.tv_nsec = tp->tv_nsec; \
+ ts64.tv_pad = 0; \
+ retval = INLINE_SYSCALL (clock_settime64, 2, clock_id, &ts64); \
+ } \
+ else if (tp->tv_sec <= INT_MAX) \
+ { \
+ struct timespec ts32; \
+ ts32.tv_sec = tp->tv_sec; \
+ ts32.tv_nsec = tp->tv_nsec; \
+ retval = INLINE_SYSCALL (clock_settime, 2, clock_id, &ts32); \
+ } \
+ break
+
#include <sysdeps/unix/clock_settime.c>
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:36 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 2 +
sysdeps/posix/clock_getres.c | 87 +++++++++++++++++++++++++++++++++-
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/clock_getres.c | 40 ++++++++++++++++
4 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 63237e23f4..00bdb2853a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -52,6 +52,8 @@ extern int __clock_gettime64 (clockid_t __clock_id,
struct __timespec64 *__tp) __THROW;
extern int __clock_settime64 (clockid_t __clock_id,
const struct __timespec64 *__tp) __THROW;
+extern int __clock_getres64 (clockid_t __clock_id,
+ struct __timespec64 *__res) __THROW;

/* Now define the internal interfaces. */
struct tm;
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index b6248bef2c..3b74014d41 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -23,7 +23,6 @@
#include <sys/param.h>
#include <libc-internal.h>

-
#if HP_TIMING_AVAIL
static long int nsec; /* Clock frequency of the processor. */

@@ -53,6 +52,33 @@ hp_timing_getres (struct timespec *res)

return 0;
}
+
+static int
+hp_timing_getres64 (struct __timespec64 *res)
+{
+ if (__glibc_unlikely (nsec == 0))
+ {
+ hp_timing_t freq;
+
+ /* This can only happen if we haven't initialized the `nsec'
+ variable yet. Do this now. We don't have to protect this
+ code against multiple execution since all of them should
+ lead to the same result. */
+ freq = __get_clockfreq ();
+ if (__glibc_unlikely (freq == 0))
+ /* Something went wrong. */
+ return -1;
+
+ nsec = MAX (UINT64_C (1000000000) / freq, 1);
+ }
+
+ /* Fill in the values.
+ The seconds are always zero (unless we have a 1Hz machine). */
+ res->tv_sec = 0;
+ res->tv_nsec = nsec;
+
+ return 0;
+}
#endif

static inline int
@@ -73,6 +99,24 @@ realtime_getres (struct timespec *res)
return -1;
}

+static inline int
+realtime_getres64 (struct __timespec64 *res)
+{
+ long int clk_tck = sysconf (_SC_CLK_TCK);
+
+ if (__glibc_likely (clk_tck != -1))
+ {
+ /* This implementation assumes that the realtime clock has a
+ resolution higher than 1 second. This is the case for any
+ reasonable implementation. */
+ res->tv_sec = 0;
+ res->tv_nsec = 1000000000 / clk_tck;
+ return 0;
+ }
+
+ return -1;
+}
+

/* Get resolution of clock. */
int
@@ -116,3 +160,44 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
return retval;
}
weak_alias (__clock_getres, clock_getres)
+
+int
+__clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
+{
+ int retval = -1;
+
+ switch (clock_id)
+ {
+#ifdef SYSDEP_GETRES64
+ SYSDEP_GETRES64;
+#endif
+
+#ifndef HANDLED_REALTIME64
+ case CLOCK_REALTIME64:
+ retval = realtime_getres64 (res);
+ break;
+#endif /* handled REALTIME */
+
+ default:
+#ifdef SYSDEP_GETRES_CPU64
+ SYSDEP_GETRES_CPU64;
+#endif
+#if HP_TIMING_AVAIL
+ if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+ == CLOCK_THREAD_CPUTIME_ID)
+ retval = hp_timing_getres64 (res);
+ else
+#endif
+ __set_errno (EINVAL);
+ break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+ case CLOCK_PROCESS_CPUTIME_ID:
+ case CLOCK_THREAD_CPUTIME_ID:
+ retval = hp_timing_getres64 (res);
+ break;
+#endif
+ }
+
+ return retval;
+}
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 553cdd7543..4b03cce526 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -31,5 +31,6 @@ libc {
__vdso_clock_gettime64;
__y2038_kernel_support;
__clock_settime64;
+ __clock_getres64;
}
}
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 2b7bb65e55..095b284b23 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -48,4 +48,44 @@
#define SYSDEP_GETRES_CPU SYSCALL_GETRES
#define SYSDEP_GETRES_CPUTIME /* Default catches them too. */

+/* The 64-bit version */
+
+extern int __y2038_linux_support;
+
+#define SYSCALL_GETRES64 \
+ if (__y2038_linux_support) \
+ { \
+ retval = INLINE_VSYSCALL (clock_getres64, 2, clock_id, res); \
+ } \
+ else \
+ { \
+ retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32); \
+ if (retval==0) \
+ { \
+ res->tv_sec = ts32.tv_sec; \
+ res->tv_nsec = ts32.tv_nsec; \
+ res->tv_pad = 0; \
+ } \
+ } \
+ break
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+ kernel. */
+#define SYSDEP_GETRES64 \
+ SYSDEP_GETRES_CPUTIME64 \
+ case CLOCK_REALTIME: \
+ case CLOCK_MONOTONIC: \
+ case CLOCK_MONOTONIC_RAW: \
+ case CLOCK_REALTIME_COARSE: \
+ case CLOCK_MONOTONIC_COARSE: \
+ SYSCALL_GETRES64
+
+/* We handled the REALTIME clock here. */
+#define HANDLED_REALTIME64 1
+#define HANDLED_CPUTIME64 1
+
+#define SYSDEP_GETRES_CPU64 SYSCALL_GETRES64
+#define SYSDEP_GETRES_CPUTIME64 \
+ struct timespec ts32;
+
#include <sysdeps/posix/clock_getres.c>
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:37 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 3 ++
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/clock_nanosleep.c | 87 ++++++++++++++++++++++++++++++-
3 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 00bdb2853a..90c1385d13 100644
--- a/include/time.h
+++ b/include/time.h
@@ -54,6 +54,9 @@ extern int __clock_settime64 (clockid_t __clock_id,
const struct __timespec64 *__tp) __THROW;
extern int __clock_getres64 (clockid_t __clock_id,
struct __timespec64 *__res) __THROW;
+extern int __clock_nanosleep64 (clockid_t __clock_id, int __flags,
+ const struct __timespec64 *__req,
+ struct __timespec64 *__rem);

/* Now define the internal interfaces. */
struct tm;
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 4b03cce526..fd94c63672 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -32,5 +32,6 @@ libc {
__y2038_kernel_support;
__clock_settime64;
__clock_getres64;
+ __clock_nanosleep64;
}
}
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 93bc4cf47e..7d00176c3e 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -21,7 +21,6 @@
#include <sysdep-cancel.h>
#include "kernel-posix-cpu-timers.h"

-
/* We can simply use the syscall. The CPU clocks are not supported
with this function. */
int
@@ -52,3 +51,89 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
}
weak_alias (__clock_nanosleep, clock_nanosleep)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+ const struct __timespec64 *req,
+ struct __timespec64 *rem)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ int r;
+ struct __timespec64 req64;
+ struct timespec req32, rem32;
+
+ if (clock_id == CLOCK_THREAD_CPUTIME_ID)
+ return EINVAL;
+ if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
+ clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
+
+ if (SINGLE_THREAD_P)
+ {
+ if (__y2038_linux_support)
+ {
+ req64.tv_sec = req->tv_sec;
+ req64.tv_nsec = req->tv_nsec;
+ req64.tv_pad = 0;
+ r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+ &req64, rem);
+ }
+ else if (req->tv_sec > INT_MAX)
+ r = EOVERFLOW;
+ else
+ {
+ req32.tv_sec = req->tv_sec;
+ req32.tv_nsec = req->tv_nsec;
+ r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+ &req32, &rem32);
+ if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+ {
+ rem->tv_sec = rem32.tv_sec;
+ rem->tv_nsec = rem32.tv_nsec;
+ rem->tv_pad = 0;
+ }
+ }
+ }
+ else
+ {
+ int oldstate = LIBC_CANCEL_ASYNC ();
+
+ if (__y2038_linux_support)
+ {
+ req64.tv_sec = req->tv_sec;
+ req64.tv_nsec = req->tv_nsec;
+ req64.tv_pad = 0;
+ r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+ &req64, rem);
+ }
+ else if (req->tv_sec > INT_MAX)
+ r = EOVERFLOW;
+ else
+ {
+ req32.tv_sec = req->tv_sec;
+ req32.tv_nsec = req->tv_nsec;
+ r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+ &req32, &rem32);
+ if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+ {
+ rem->tv_sec = rem32.tv_sec;
+ rem->tv_nsec = rem32.tv_nsec;
+ rem->tv_pad = 0;
+ }
+ }
+
+ LIBC_CANCEL_RESET (oldstate);
+ }
+
+ if (INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ return INTERNAL_SYSCALL_ERRNO (r, err);
+ }
+ else
+ {
+ return 0;
+ }
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:38 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/timespec_get.c | 35 ++++++++++++++++++++++++++++++++++
time/Versions | 7 +++++++
2 files changed, 42 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
index 1f63e57e39..b43b5aec7b 100644
--- a/sysdeps/unix/sysv/linux/timespec_get.c
+++ b/sysdeps/unix/sysv/linux/timespec_get.c
@@ -44,3 +44,38 @@ timespec_get (struct timespec *ts, int base)

return base;
}
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__timespec_get64 (struct __timespec64 *ts, int base)
+{
+ switch (base)
+ {
+ int res;
+ INTERNAL_SYSCALL_DECL (err);
+ case TIME_UTC:
+ if (__y2038_linux_support)
+ {
+ res = INTERNAL_VSYSCALL (clock_gettime64, err, 2, CLOCK_REALTIME, ts);
+ }
+ else
+ {
+ struct timespec ts32;
+ res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, &ts32);
+ if (INTERNAL_SYSCALL_ERROR_P (res, err))
+ return 0;
+ ts->tv_sec = ts32.tv_sec;
+ ts->tv_nsec = ts32.tv_nsec;
+ ts->tv_pad = 0;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return base;
+}
diff --git a/time/Versions b/time/Versions
index fd838181e4..3fe860862a 100644
--- a/time/Versions
+++ b/time/Versions
@@ -65,4 +65,11 @@ libc {
GLIBC_2.16 {
timespec_get;
}
+
+ # Y2038 symbols are given their own version until they can be put in
+ # the right place
+
+ GLIBC_Y2038 {
+ __timespec_get64;
+ }
}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:39 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
io/futimens.c | 9 +++++++++
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/futimens.c | 38 ++++++++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+)

diff --git a/io/futimens.c b/io/futimens.c
index 27fc1ae6ef..516e64efde 100644
--- a/io/futimens.c
+++ b/io/futimens.c
@@ -21,6 +21,7 @@
#include <string.h>
#include <time.h>
#include <sysdep.h>
+#include <kernel_timespec.h>


/* Change the access time of the file associated with FD to TSP[0] and
@@ -32,3 +33,11 @@ futimens (int fd, const struct timespec tsp[2])
return -1;
}
stub_warning (futimens)
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__futimens64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index fd94c63672..08dfae2b61 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -33,5 +33,6 @@ libc {
__clock_settime64;
__clock_getres64;
__clock_nanosleep64;
+ __futimens64;
}
}
diff --git a/sysdeps/unix/sysv/linux/futimens.c b/sysdeps/unix/sysv/linux/futimens.c
index b4985e034c..64f1a35663 100644
--- a/sysdeps/unix/sysv/linux/futimens.c
+++ b/sysdeps/unix/sysv/linux/futimens.c
@@ -36,3 +36,41 @@ futimens (int fd, const struct timespec tsp[2])
/* Avoid implicit array coercion in syscall macros. */
return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0);
}
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+ struct __timespec64 ts64[2];
+ struct timespec ts32[2];
+
+ if (fd < 0)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+
+ if (__y2038_linux_support)
+ {
+ if (fd < 0)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+ ts64[0].tv_sec = tsp[0].tv_sec;
+ ts64[0].tv_nsec = tsp[0].tv_nsec;
+ ts64[0].tv_pad = 0;
+ ts64[1].tv_sec = tsp[1].tv_sec;
+ ts64[1].tv_nsec = tsp[1].tv_nsec;
+ ts64[1].tv_pad = 0;
+ return INLINE_SYSCALL (utimensat64, 4, fd, NULL, &ts64[0], 0);
+ }
+
+ if (tsp[0].tv_sec > INT_MAX || tsp[1].tv_sec > INT_MAX)
+ {
+ return EOVERFLOW;
+ }
+
+ ts32[0].tv_sec = tsp[0].tv_sec;
+ ts32[0].tv_nsec = tsp[0].tv_nsec;
+ ts32[1].tv_sec = tsp[1].tv_sec;
+ ts32[1].tv_nsec = tsp[1].tv_nsec;
+ return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32[0], 0);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:40 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
io/utimensat.c | 9 +++++++++
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/utimensat.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 46 insertions(+)

diff --git a/io/utimensat.c b/io/utimensat.c
index f45eb73b93..6b9cf43d4b 100644
--- a/io/utimensat.c
+++ b/io/utimensat.c
@@ -30,3 +30,12 @@ utimensat (int fd, const char *file, const struct timespec tsp[2],
return -1;
}
stub_warning (utimensat)
+
+int
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+ int flags)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__utimensat64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 08dfae2b61..2620d81fdc 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -34,5 +34,6 @@ libc {
__clock_getres64;
__clock_nanosleep64;
__futimens64;
+ __utimensat64;
}
}
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 87f1ef04e0..baa718686e 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <sys/stat.h>
#include <sysdep.h>
+#include <stdio.h>


/* Change the access time of FILE to TSP[0] and
@@ -34,3 +35,38 @@ utimensat (int fd, const char *file, const struct timespec tsp[2],
/* Avoid implicit array coercion in syscall macros. */
return INLINE_SYSCALL (utimensat, 4, fd, file, &tsp[0], flags);
}
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+ int flags)
+{
+ struct __timespec64 ts64[2];
+ struct timespec ts32[2];
+
+ if (file == NULL)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+ if (!tsp)
+ return INLINE_SYSCALL (utimensat64, 4, fd, file, NULL, flags);
+
+ if (__y2038_linux_support)
+ {
+ ts64[0].tv_sec = tsp[0].tv_sec;
+ ts64[0].tv_nsec = tsp[0].tv_nsec;
+ ts64[0].tv_pad = 0;
+ ts64[1].tv_sec = tsp[1].tv_sec;
+ ts64[1].tv_nsec = tsp[1].tv_nsec;
+ ts64[1].tv_pad = 0;
+ return INLINE_SYSCALL (utimensat64, 4, fd, file, &ts64, flags);
+ }
+
+ ts32[0].tv_sec = tsp[0].tv_sec;
+ ts32[0].tv_nsec = tsp[0].tv_nsec;
+ ts32[1].tv_sec = tsp[1].tv_sec;
+ ts32[1].tv_nsec = tsp[1].tv_nsec;
+ return INLINE_SYSCALL (utimensat, 4, fd, file, &ts32, flags);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:41 UTC
Permalink
This post might be inappropriate. Click to display it.
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:42 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/include/time.h b/include/time.h
index 90c1385d13..648cef2786 100644
--- a/include/time.h
+++ b/include/time.h
@@ -41,6 +41,12 @@ struct __timespec64
};
#endif

+struct __timeval64
+{
+ __time64_t tv_sec; /* Seconds */
+ __int64_t tv_usec; /* Microseconds */
+};
+
extern __typeof (clock_getres) __clock_getres;
extern __typeof (clock_gettime) __clock_gettime;
libc_hidden_proto (__clock_gettime)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:43 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
misc/futimes.c | 9 +++++++
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/futimes.c | 52 ++++++++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+)

diff --git a/misc/futimes.c b/misc/futimes.c
index 6dad9996fa..e4c9ee2239 100644
--- a/misc/futimes.c
+++ b/misc/futimes.c
@@ -30,3 +30,12 @@ __futimes (int fd, const struct timeval tvp[2])
weak_alias (__futimes, futimes)

stub_warning (futimes)
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+
+stub_warning (__futimes64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 630e3f8569..155b7889eb 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -36,5 +36,6 @@ libc {
__futimens64;
__utimensat64;
__sigtimedwait64;
+ __futimes64;
}
}
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index af79cb1508..f30e6ad7a0 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -49,3 +49,55 @@ __futimes (int fd, const struct timeval tvp[2])
return INLINE_SYSCALL (utimensat, 4, fd, NULL, tvp ? &ts : NULL, 0);
}
weak_alias (__futimes, futimes)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+ /* The utimensat system call expects timespec not timeval. */
+ struct __timespec64 ts64[2];
+ struct timespec ts32[2];
+
+ if (__y2038_linux_support)
+ {
+ if (tvp != NULL)
+ {
+ if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+ || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+ ts64[0].tv_sec = tvp[0].tv_sec;
+ ts64[0].tv_nsec = tvp[0].tv_usec * 1000;
+ ts64[0].tv_pad = 0;
+ ts64[1].tv_sec = tvp[1].tv_sec;
+ ts64[1].tv_nsec = tvp[1].tv_usec * 1000;
+ ts64[1].tv_pad = 0;
+
+ return INLINE_SYSCALL (utimensat64, 4, fd, NULL, &ts64, 0);
+ }
+
+ return INLINE_SYSCALL (utimensat64, 4, fd, NULL, NULL, 0);
+ }
+
+ if (tvp != NULL)
+ {
+ if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+ || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+ if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
+
+ ts32[0].tv_sec = tvp[0].tv_sec;
+ ts32[0].tv_nsec = tvp[0].tv_usec * 1000;
+ ts32[1].tv_sec = tvp[1].tv_sec;
+ ts32[1].tv_nsec = tvp[1].tv_usec * 1000;
+
+ return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32, 0);
+ }
+
+ return INLINE_SYSCALL (utimensat, 4, fd, NULL, NULL, 0);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:44 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
misc/lutimes.c | 8 ++++++
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/lutimes.c | 53 ++++++++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+)

diff --git a/misc/lutimes.c b/misc/lutimes.c
index c4cce8f3b6..e01b5c996a 100644
--- a/misc/lutimes.c
+++ b/misc/lutimes.c
@@ -31,3 +31,11 @@ __lutimes (const char *file, const struct timeval tvp[2])
weak_alias (__lutimes, lutimes)

stub_warning (lutimes)
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__lutimes64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 155b7889eb..edac9cf007 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -37,5 +37,6 @@ libc {
__utimensat64;
__sigtimedwait64;
__futimes64;
+ __lutimes64;
}
}
diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c
index 433fb06701..c94273abf5 100644
--- a/sysdeps/unix/sysv/linux/lutimes.c
+++ b/sysdeps/unix/sysv/linux/lutimes.c
@@ -42,3 +42,56 @@ lutimes (const char *file, const struct timeval tvp[2])
return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL,
AT_SYMLINK_NOFOLLOW);
}
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+ /* The system call expects timespec, not timeval. */
+ struct __timespec64 ts64[2];
+ struct timespec ts32[2];
+
+ if (__y2038_linux_support)
+ {
+ if (tvp != NULL)
+ {
+ if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+ || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+ ts64[0].tv_sec = tvp[0].tv_sec;
+ ts64[0].tv_nsec = tvp[0].tv_usec * 1000;
+ ts64[0].tv_pad = 0;
+ ts64[1].tv_sec = tvp[1].tv_sec;
+ ts64[1].tv_nsec = tvp[1].tv_usec * 1000;
+ ts64[1].tv_pad = 0;
+
+ return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, &ts64,
+ AT_SYMLINK_NOFOLLOW);
+ }
+
+ return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, NULL,
+ AT_SYMLINK_NOFOLLOW);
+ }
+
+ if (tvp != NULL)
+ {
+ if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+ || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+ ts32[0].tv_sec = tvp[0].tv_sec;
+ ts32[0].tv_nsec = tvp[0].tv_usec * 1000;
+ ts32[1].tv_sec = tvp[1].tv_sec;
+ ts32[1].tv_nsec = tvp[1].tv_usec * 1000;
+
+ return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, &ts32,
+ AT_SYMLINK_NOFOLLOW);
+ }
+
+ return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, NULL,
+ AT_SYMLINK_NOFOLLOW);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:45 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/include/time.h b/include/time.h
index 648cef2786..1d585184d8 100644
--- a/include/time.h
+++ b/include/time.h
@@ -47,6 +47,12 @@ struct __timeval64
__int64_t tv_usec; /* Microseconds */
};

+struct __itimerspec64
+{
+ struct __timespec64 it_interval;
+ struct __timespec64 it_value;
+};
+
extern __typeof (clock_getres) __clock_getres;
extern __typeof (clock_gettime) __clock_gettime;
libc_hidden_proto (__clock_gettime)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:46 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
rt/Versions | 7 +++++++
sysdeps/unix/sysv/linux/timer_gettime.c | 24 ++++++++++++++++++++++++
2 files changed, 31 insertions(+)

diff --git a/rt/Versions b/rt/Versions
index 91e3fd2a20..f07c8e2b18 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -37,4 +37,11 @@ librt {
GLIBC_2.7 {
__mq_open_2;
}
+
+ # Y2038 symbols are given their own version until they can be put in
+ # the right place
+
+ GLIBC_Y2038 {
+ __timer_gettime64;
+ }
}
diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
index 849c56a30a..09aa6e5abf 100644
--- a/sysdeps/unix/sysv/linux/timer_gettime.c
+++ b/sysdeps/unix/sysv/linux/timer_gettime.c
@@ -39,3 +39,27 @@ timer_gettime (timer_t timerid, struct itimerspec *value)

return res;
}
+
+/* 64-bit time version */
+
+int
+__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
+{
+ struct itimerspec value32;
+ struct timer *kt = (struct timer *) timerid;
+
+ if (__y2038_kernel_support())
+ return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
+
+ int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, &value32);
+
+ if (res == 0)
+ {
+ value->it_value.tv_sec = value32.it_value.tv_sec;
+ value->it_value.tv_nsec = value32.it_value.tv_nsec;
+ value->it_interval.tv_sec = value32.it_interval.tv_sec;
+ value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+ }
+
+ return res;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:47 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
rt/Versions | 1 +
sysdeps/unix/sysv/linux/timer_settime.c | 49 +++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)

diff --git a/rt/Versions b/rt/Versions
index f07c8e2b18..4933197aa5 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -43,5 +43,6 @@ librt {

GLIBC_Y2038 {
__timer_gettime64;
+ __timer_settime64;
}
}
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index ba35036355..d75b24ada8 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -41,3 +41,52 @@ timer_settime (timer_t timerid, int flags, const struct itimerspec *value,

return res;
}
+
+/* 64-bit time version */
+
+int
+__timer_settime64 (timer_t timerid, int flags, const struct itimerspec *value,
+ struct itimerspec *ovalue)
+{
+ struct timer *kt = (struct timer *) timerid;
+ struct __itimerspec64 value64;
+ struct itimerspec value32, ovalue32;
+
+ if (value == NULL)
+ return EFAULT;
+
+ if (__y2038_kernel_support())
+ {
+ value64.it_value.tv_sec = value->it_value.tv_sec;
+ value64.it_value.tv_nsec = value->it_value.tv_nsec;
+ value64.it_value.tv_pad = 0;
+ value64.it_interval.tv_sec = value->it_interval.tv_sec;
+ value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+ value64.it_interval.tv_pad = 0;
+
+ return INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
+ &value64, ovalue);
+ }
+
+ if (value->it_value.tv_sec > INT_MAX
+ || value->it_interval.tv_sec > INT_MAX)
+ return EOVERFLOW;
+
+ value32.it_value.tv_sec = value->it_value.tv_sec;
+ value32.it_value.tv_nsec = value->it_value.tv_nsec;
+ value32.it_interval.tv_sec = value->it_interval.tv_sec;
+ value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+ int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
+ &value32, &ovalue32);
+
+ if (res == 0 && ovalue != NULL)
+ {
+ ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+ ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+ ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+ ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+ }
+
+ return res;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:48 UTC
Permalink
Note: this tests the return value of function __y2038_kernel_support()
rather than the value of variable __y2038_linux_upport, because the
latter cannot be accessed from librt while the former can.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
rt/Makefile | 3 +-
rt/Versions | 1 +
rt/timerfd_gettime64.c | 28 ++++++++++++++++++
sysdeps/unix/sysv/linux/timerfd_gettime64.c | 44 +++++++++++++++++++++++++++++
4 files changed, 75 insertions(+), 1 deletion(-)
create mode 100644 rt/timerfd_gettime64.c
create mode 100644 sysdeps/unix/sysv/linux/timerfd_gettime64.c

diff --git a/rt/Makefile b/rt/Makefile
index 9740dc2ad8..56bfb856ae 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -32,7 +32,8 @@ clock-routines := get_clockfreq clock_getcpuclockid \
clock_getres clock_gettime clock_settime \
clock_nanosleep
timer-routines := timer_create timer_delete timer_getoverr \
- timer_gettime timer_settime
+ timer_gettime timer_settime \
+ timerfd_gettime64
shm-routines := shm_open shm_unlink
mq-routines := mq_open mq_close mq_unlink mq_getattr mq_setattr \
mq_notify mq_send mq_receive mq_timedsend \
diff --git a/rt/Versions b/rt/Versions
index 4933197aa5..254e36dd2d 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -44,5 +44,6 @@ librt {
GLIBC_Y2038 {
__timer_gettime64;
__timer_settime64;
+ __timerfd_gettime64;
}
}
diff --git a/rt/timerfd_gettime64.c b/rt/timerfd_gettime64.c
new file mode 100644
index 0000000000..9496fcaef0
--- /dev/null
+++ b/rt/timerfd_gettime64.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1999-2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <time.h>
+
+/* Get current value of timer TIMERID and store it in VLAUE. */
+int
+__timerfd_gettime64 (int fd, struct itimerspec *value)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__timerfd_gettime64)
diff --git a/sysdeps/unix/sysv/linux/timerfd_gettime64.c b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
new file mode 100644
index 0000000000..5843e23c8b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <***@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_gettime64 (int fd, struct __itimerspec64 *value)
+{
+ struct itimerspec value32;
+
+ if (__y2038_kernel_support())
+ return INLINE_SYSCALL (timerfd_gettime64, 2, fd, value);
+
+ int res = INLINE_SYSCALL (timerfd_gettime, 2, fd, &value32);
+
+ if (res == 0)
+ {
+ value->it_value.tv_sec = value32.it_value.tv_sec;
+ value->it_value.tv_nsec = value32.it_value.tv_nsec;
+ value->it_interval.tv_sec = value32.it_interval.tv_sec;
+ value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+ }
+
+ return res;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:49 UTC
Permalink
Note: this tests the return value of function __y2038_kernel_support()
rather than the value of variable __y2038_linux_upport, because the
latter cannot be accessed from librt while the former can.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
rt/Makefile | 2 +-
rt/Versions | 1 +
rt/timerfd_settime64.c | 29 ++++++++++++
sysdeps/unix/sysv/linux/timerfd_settime64.c | 71 +++++++++++++++++++++++++++++
4 files changed, 102 insertions(+), 1 deletion(-)
create mode 100644 rt/timerfd_settime64.c
create mode 100644 sysdeps/unix/sysv/linux/timerfd_settime64.c

diff --git a/rt/Makefile b/rt/Makefile
index 56bfb856ae..2a6be1bcbf 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -33,7 +33,7 @@ clock-routines := get_clockfreq clock_getcpuclockid \
clock_nanosleep
timer-routines := timer_create timer_delete timer_getoverr \
timer_gettime timer_settime \
- timerfd_gettime64
+ timerfd_gettime64 timerfd_settime64
shm-routines := shm_open shm_unlink
mq-routines := mq_open mq_close mq_unlink mq_getattr mq_setattr \
mq_notify mq_send mq_receive mq_timedsend \
diff --git a/rt/Versions b/rt/Versions
index 254e36dd2d..761fbb8a4c 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -45,5 +45,6 @@ librt {
__timer_gettime64;
__timer_settime64;
__timerfd_gettime64;
+ __timerfd_settime64;
}
}
diff --git a/rt/timerfd_settime64.c b/rt/timerfd_settime64.c
new file mode 100644
index 0000000000..8551c7adb0
--- /dev/null
+++ b/rt/timerfd_settime64.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1999-2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <time.h>
+
+/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */
+int
+__timerfd_settime64 (int fd, int flags, const struct itimerspec *value,
+ struct itimerspec *ovalue)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__timerfd_settime64)
diff --git a/sysdeps/unix/sysv/linux/timerfd_settime64.c b/sysdeps/unix/sysv/linux/timerfd_settime64.c
new file mode 100644
index 0000000000..9701452c0a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_settime64.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <***@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
+ struct __itimerspec64 *ovalue)
+{
+ int res;
+ struct __itimerspec64 value64;
+ struct itimerspec value32;
+ struct itimerspec ovalue32;
+
+ if (value == NULL)
+ return EFAULT;
+
+ if (__y2038_kernel_support())
+ {
+ value64.it_value.tv_sec = value->it_value.tv_sec;
+ value64.it_value.tv_nsec = value->it_value.tv_nsec;
+ value64.it_value.tv_pad = 0;
+ value64.it_interval.tv_sec = value->it_interval.tv_sec;
+ value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+ value64.it_interval.tv_pad = 0;
+
+ return INLINE_SYSCALL (timerfd_settime64, 4, fd, flags,
+ &value64, ovalue);
+ }
+
+ if (value->it_value.tv_sec > INT_MAX
+ || value->it_interval.tv_sec > INT_MAX)
+ return EOVERFLOW;
+
+ value32.it_value.tv_sec = value->it_value.tv_sec;
+ value32.it_value.tv_nsec = value->it_value.tv_nsec;
+ value32.it_interval.tv_sec = value->it_interval.tv_sec;
+ value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+ res = INLINE_SYSCALL (timerfd_settime, 4, fd, flags,
+ &value32, &ovalue32);
+
+ if (res == 0 && ovalue != NULL)
+ {
+ ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+ ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+ ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+ ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+ }
+
+ return res;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:50 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/stat.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 4f31c00eca..300cf8bbc4 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -1,7 +1,32 @@
#ifndef _SYS_STAT_H
#include <io/sys/stat.h>
+#include <include/time.h>

#ifndef _ISOMAC
+
+/* Used for 64-bit time implementations */
+struct __stat64_t64
+ {
+ __dev_t st_dev; /* Device. */
+ unsigned int __pad1;
+
+ __ino_t __st_ino; /* 32bit file serial number. */
+ __mode_t st_mode; /* File mode. */
+ __nlink_t st_nlink; /* Link count. */
+ __uid_t st_uid; /* User ID of the file's owner. */
+ __gid_t st_gid; /* Group ID of the file's group.*/
+ __dev_t st_rdev; /* Device number, if device. */
+ unsigned int __pad2;
+ __off64_t st_size; /* Size of file, in bytes. */
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
+
+ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
+ struct __timespec64 st_atim; /* Time of last access. */
+ struct __timespec64 st_mtim; /* Time of last modification. */
+ struct __timespec64 st_ctim; /* Time of last status change. */
+ __ino64_t st_ino; /* File serial number. */
+ };
+
/* Now define the internal interfaces. */
extern int __stat (const char *__file, struct stat *__buf);
extern int __fstat (int __fd, struct stat *__buf);
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:51 UTC
Permalink
There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/stat.h | 2 ++
io/Versions | 7 ++++++
io/fstat64.c | 7 ++++++
sysdeps/unix/sysv/linux/fxstat64.c | 50 ++++++++++++++++++++++++++++++++++++++
4 files changed, 66 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 300cf8bbc4..2961849e35 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -37,6 +37,8 @@ extern __mode_t __umask (__mode_t __mask);
extern int __mkdir (const char *__path, __mode_t __mode);
extern int __mknod (const char *__path,
__mode_t __mode, __dev_t __dev);
+extern int __fxstat64_t64 (int __ver, int __fildes,
+ struct __stat64_t64 *__stat_buf);
#if IS_IN (libc) || IS_IN (rtld)
hidden_proto (__fxstat)
hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index 64316cd025..747ae5d9d6 100644
--- a/io/Versions
+++ b/io/Versions
@@ -125,4 +125,11 @@ libc {
GLIBC_2.23 {
fts64_children; fts64_close; fts64_open; fts64_read; fts64_set;
}
+
+ # Y2038 symbols are given their own version until they can be put in
+ # the right place
+
+ GLIBC_Y2038 {
+ __fxstat64_t64;
+ }
}
diff --git a/io/fstat64.c b/io/fstat64.c
index 69c80e5e45..a972304c0a 100644
--- a/io/fstat64.c
+++ b/io/fstat64.c
@@ -50,3 +50,10 @@ fstat64 (int fd, struct stat64 *buf)
{
return __fxstat64 (_STAT_VER, fd, buf);
}
+
+int
+attribute_hidden
+__fstat64_t64 (int fd, struct __stat64_t64 *buf)
+{
+ return __fxstat64_t64 (_STAT_VER, fd, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 8a59d86d31..6097257b2a 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -24,6 +24,8 @@
#include <sysdep.h>
#include <sys/syscall.h>

+#include <xstatconv.h>
+
#include <kernel-features.h>

/* Get information about the file FD in BUF. */
@@ -51,3 +53,51 @@ hidden_ver (___fxstat64, __fxstat64)
strong_alias (___fxstat64, __fxstat64)
hidden_def (__fxstat64)
#endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__fxstat64_t64 (int vers, int fd, struct __stat64_t64 *buf)
+{
+ int result;
+ struct stat64 st64;
+
+ if (__y2038_linux_support)
+ {
+ // TODO: use 64-bit syscalls when they become available
+ }
+
+ result = INLINE_SYSCALL (fstat64, 2, fd, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+ if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+ st64.st_ino = st64.__st_ino;
+#endif
+ if (!result)
+ {
+ buf->st_dev = st64.st_dev;
+ buf->__pad1 = st64.__pad1;
+
+ buf->__st_ino = st64.__st_ino;
+ buf->st_mode = st64.st_mode;
+ buf->st_nlink = st64.st_nlink;
+ buf->st_uid = st64.st_uid;
+ buf->st_gid = st64.st_gid;
+ buf->st_rdev = st64.st_rdev;
+ buf->__pad2 = st64.__pad2;
+ buf->st_size = st64.st_size;
+ buf->st_blksize = st64.st_blksize;
+
+ buf->st_blocks = st64.st_blocks;
+ buf->st_atim.tv_sec = st64.st_atim.tv_sec;
+ buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;
+ buf->st_mtim.tv_sec = st64.st_mtim.tv_sec;
+ buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
+ buf->st_ctim.tv_sec = st64.st_ctim.tv_sec;
+ buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
+
+ buf->st_ino = st64.st_ino;
+ }
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:52 UTC
Permalink
There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/stat.h | 2 ++
io/Versions | 1 +
io/stat64.c | 7 ++++++
sysdeps/unix/sysv/linux/xstat64.c | 50 +++++++++++++++++++++++++++++++++++++++
4 files changed, 60 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 2961849e35..8cd3fbedae 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -39,6 +39,8 @@ extern int __mknod (const char *__path,
__mode_t __mode, __dev_t __dev);
extern int __fxstat64_t64 (int __ver, int __fildes,
struct __stat64_t64 *__stat_buf);
+extern int __xstat64_t64 (int __ver, const char *__filename,
+ struct __stat64_t64 *__stat_buf);
#if IS_IN (libc) || IS_IN (rtld)
hidden_proto (__fxstat)
hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index 747ae5d9d6..e2befdbdf7 100644
--- a/io/Versions
+++ b/io/Versions
@@ -131,5 +131,6 @@ libc {

GLIBC_Y2038 {
__fxstat64_t64;
+ __xstat64_t64;
}
}
diff --git a/io/stat64.c b/io/stat64.c
index 704cbb34a6..22fc0db13d 100644
--- a/io/stat64.c
+++ b/io/stat64.c
@@ -50,3 +50,10 @@ stat64 (const char *file, struct stat64 *buf)
{
return __xstat64 (_STAT_VER, file, buf);
}
+
+int
+attribute_hidden
+__stat64_t64 (const char *file, struct __stat64_t64 *buf)
+{
+ return __xstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index b3fbe6a383..325ed36d1d 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -24,6 +24,8 @@
#include <sysdep.h>
#include <sys/syscall.h>

+#include <xstatconv.h>
+
#include <kernel-features.h>

/* Get information about the file NAME in BUF. */
@@ -52,3 +54,51 @@ hidden_ver (___xstat64, __xstat64)
strong_alias (___xstat64, __xstat64)
hidden_def (__xstat64)
#endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__xstat64_t64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+ int result;
+ struct stat64 st64;
+
+ if (__y2038_linux_support)
+ {
+ // TODO: use 64-bit syscalls when they become available
+ }
+
+ result = INLINE_SYSCALL (stat64, 2, name, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+ if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+ st64.st_ino = st64.__st_ino;
+#endif
+ if (!result)
+ {
+ buf->st_dev = st64.st_dev;
+ buf->__pad1 = st64.__pad1;
+
+ buf->__st_ino = st64.__st_ino;
+ buf->st_mode = st64.st_mode;
+ buf->st_nlink = st64.st_nlink;
+ buf->st_uid = st64.st_uid;
+ buf->st_gid = st64.st_gid;
+ buf->st_rdev = st64.st_rdev;
+ buf->__pad2 = st64.__pad2;
+ buf->st_size = st64.st_size;
+ buf->st_blksize = st64.st_blksize;
+
+ buf->st_blocks = st64.st_blocks;
+ buf->st_atim.tv_sec = st64.st_ctim.tv_sec;
+ buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;
+ buf->st_mtim.tv_sec = st64.st_mtim.tv_sec;
+ buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
+ buf->st_ctim.tv_sec = st64.st_ctim.tv_sec;
+ buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
+
+ buf->st_ino = st64.st_ino;
+ }
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:53 UTC
Permalink
There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/stat.h | 2 ++
io/Versions | 1 +
io/lstat64.c | 7 ++++++
sysdeps/unix/sysv/linux/lxstat64.c | 50 ++++++++++++++++++++++++++++++++++++++
4 files changed, 60 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 8cd3fbedae..9b0782a9a4 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -41,6 +41,8 @@ extern int __fxstat64_t64 (int __ver, int __fildes,
struct __stat64_t64 *__stat_buf);
extern int __xstat64_t64 (int __ver, const char *__filename,
struct __stat64_t64 *__stat_buf);
+extern int __lxstat64_t64 (int __ver, const char *__filename,
+ struct __stat64_t64 *__stat_buf);
#if IS_IN (libc) || IS_IN (rtld)
hidden_proto (__fxstat)
hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index e2befdbdf7..fcd1b71f80 100644
--- a/io/Versions
+++ b/io/Versions
@@ -132,5 +132,6 @@ libc {
GLIBC_Y2038 {
__fxstat64_t64;
__xstat64_t64;
+ __lxstat64_t64;
}
}
diff --git a/io/lstat64.c b/io/lstat64.c
index c29492aa9f..50bf7df493 100644
--- a/io/lstat64.c
+++ b/io/lstat64.c
@@ -50,3 +50,10 @@ lstat64 (const char *file, struct stat64 *buf)
{
return __lxstat64 (_STAT_VER, file, buf);
}
+
+int
+attribute_hidden
+__lstat64_t64 (const char *file, struct __stat64_t64 *buf)
+{
+ return __lxstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index 9bc548f91c..dbea8a7654 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -24,6 +24,8 @@
#include <sysdep.h>
#include <sys/syscall.h>

+#include <xstatconv.h>
+
#include <kernel-features.h>

/* Get information about the file NAME in BUF. */
@@ -50,3 +52,51 @@ hidden_ver (___lxstat64, __lxstat64)
strong_alias (___lxstat64, __lxstat64);
hidden_def (__lxstat64)
#endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__lxstat64_t64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+ int result;
+ struct stat64 st64;
+
+ if (__y2038_linux_support)
+ {
+ // TODO: use 64-bit syscalls when they become available
+ }
+
+ result = INLINE_SYSCALL (lstat64, 2, name, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+ if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+ st64.st_ino = st64.__st_ino;
+#endif
+ if (!result)
+ {
+ buf->st_dev = st64.st_dev;
+ buf->__pad1 = st64.__pad1;
+
+ buf->__st_ino = st64.__st_ino;
+ buf->st_mode = st64.st_mode;
+ buf->st_nlink = st64.st_nlink;
+ buf->st_uid = st64.st_uid;
+ buf->st_gid = st64.st_gid;
+ buf->st_rdev = st64.st_rdev;
+ buf->__pad2 = st64.__pad2;
+ buf->st_size = st64.st_size;
+ buf->st_blksize = st64.st_blksize;
+
+ buf->st_blocks = st64.st_blocks;
+ buf->st_atim.tv_sec = st64.st_atim.tv_sec;
+ buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;
+ buf->st_mtim.tv_sec = st64.st_mtim.tv_sec;
+ buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
+ buf->st_ctim.tv_sec = st64.st_ctim.tv_sec;
+ buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
+
+ buf->st_ino = st64.st_ino;
+ }
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:54 UTC
Permalink
There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/stat.h | 4 +++
io/Versions | 1 +
io/fstatat64.c | 7 +++++
sysdeps/unix/sysv/linux/fxstatat64.c | 54 ++++++++++++++++++++++++++++++++++++
4 files changed, 66 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 9b0782a9a4..71f6d63e3e 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -43,6 +43,10 @@ extern int __xstat64_t64 (int __ver, const char *__filename,
struct __stat64_t64 *__stat_buf);
extern int __lxstat64_t64 (int __ver, const char *__filename,
struct __stat64_t64 *__stat_buf);
+extern int __fxstatat64_t64 (int __ver, int __fildes,
+ const char *__filename,
+ struct __stat64_t64 *__stat_buf,
+ int __flag);
#if IS_IN (libc) || IS_IN (rtld)
hidden_proto (__fxstat)
hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index fcd1b71f80..33629a0d4e 100644
--- a/io/Versions
+++ b/io/Versions
@@ -133,5 +133,6 @@ libc {
__fxstat64_t64;
__xstat64_t64;
__lxstat64_t64;
+ __fxstatat64_t64;
}
}
diff --git a/io/fstatat64.c b/io/fstatat64.c
index 13a9ebc870..4e13f072ff 100644
--- a/io/fstatat64.c
+++ b/io/fstatat64.c
@@ -50,3 +50,10 @@ fstatat64 (int fd, const char *file, struct stat64 *buf, int flag)
{
return __fxstatat64 (_STAT_VER, fd, file, buf, flag);
}
+
+int
+attribute_hidden
+__fstatat64_t64 (int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+ return __fxstatat64_t64 (_STAT_VER, fd, file, buf, flag);
+}
diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c
index ef1e132c11..070ed78861 100644
--- a/sysdeps/unix/sysv/linux/fxstatat64.c
+++ b/sysdeps/unix/sysv/linux/fxstatat64.c
@@ -26,6 +26,8 @@
#include <sysdep.h>
#include <sys/syscall.h>

+#include <xstatconv.h>
+
/* Get information about the file NAME in BUF. */

int
@@ -45,3 +47,55 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
err));
}
libc_hidden_def (__fxstatat64)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__fxstatat64_t64 (int vers, int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+ if (__glibc_unlikely (vers != _STAT_VER_LINUX))
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+ int result;
+ struct stat64 st64;
+ INTERNAL_SYSCALL_DECL (err);
+
+ if (__y2038_linux_support)
+ {
+ // TODO: use 64-bit syscalls when they become available
+ }
+
+ result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag);
+ if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
+ {
+ buf->st_dev = st64.st_dev;
+ buf->__pad1 = st64.__pad1;
+
+ buf->__st_ino = st64.__st_ino;
+ buf->st_mode = st64.st_mode;
+ buf->st_nlink = st64.st_nlink;
+ buf->st_uid = st64.st_uid;
+ buf->st_gid = st64.st_gid;
+ buf->st_rdev = st64.st_rdev;
+ buf->__pad2 = st64.__pad2;
+ buf->st_size = st64.st_size;
+ buf->st_blksize = st64.st_blksize;
+
+ buf->st_blocks = st64.st_blocks;
+ buf->st_atim.tv_sec = st64.st_atim.tv_sec;
+ buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;
+ buf->st_mtim.tv_sec = st64.st_mtim.tv_sec;
+ buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
+ buf->st_ctim.tv_sec = st64.st_ctim.tv_sec;
+ buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
+
+ buf->st_ino = st64.st_ino;
+
+ return 0;
+ }
+ else
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
+ err));
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:55 UTC
Permalink
These implementations use only 32-bit time kernel syscalls.

Therefore, stime() will always set errno to EOVERFLOW and return -1 for dates beyond Y2038.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/posix/time.c | 26 ++++++++++++++++++++++++++
sysdeps/unix/sysv/linux/time.c | 22 ++++++++++++++++++++++
time/Versions | 1 +
time/time.c | 13 +++++++++++++
4 files changed, 62 insertions(+)

diff --git a/sysdeps/posix/time.c b/sysdeps/posix/time.c
index 32ca177514..a4c4a03c55 100644
--- a/sysdeps/posix/time.c
+++ b/sysdeps/posix/time.c
@@ -38,3 +38,29 @@ time (time_t *t)
return result;
}
libc_hidden_def (time)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+__time64_t
+__time_t64 (__time64_t *t)
+{
+ struct timeval tv32;
+ __time64_t result;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement using 64-bit time syscall */
+ }
+
+ if (__gettimeofday (&tv32, (struct timezone *) NULL))
+ result = (__time64_t) -1;
+ else
+ result = (__time64_t) tv32.tv_sec;
+
+ if (t != NULL)
+ *t = result;
+
+ return result;
+}
diff --git a/sysdeps/unix/sysv/linux/time.c b/sysdeps/unix/sysv/linux/time.c
index 72d4040cbc..b6c7e61844 100644
--- a/sysdeps/unix/sysv/linux/time.c
+++ b/sysdeps/unix/sysv/linux/time.c
@@ -34,6 +34,28 @@ time (time_t *t)
}
libc_hidden_def (time)

+/* 64-BIT TIME VERSION */
+
+extern int __y2038_linux_support;
+
+__time64_t
+__time_t64 (__time64_t *t)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ __time64_t res;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement using 64-bit time syscall */
+ }
+
+ res = INTERNAL_SYSCALL (time, err, 1, NULL);
+ /* There cannot be any error. */
+ if (t != NULL)
+ *t = res;
+ return res;
+}
+
#else

# include <sysdeps/posix/time.c>
diff --git a/time/Versions b/time/Versions
index 3fe860862a..02dc8d6146 100644
--- a/time/Versions
+++ b/time/Versions
@@ -71,5 +71,6 @@ libc {

GLIBC_Y2038 {
__timespec_get64;
+ __time_t64;
}
}
diff --git a/time/time.c b/time/time.c
index e375035265..a487068468 100644
--- a/time/time.c
+++ b/time/time.c
@@ -31,3 +31,16 @@ time (time_t *timer)
libc_hidden_def (time)

stub_warning (time)
+
+/* 64-bit time version */
+
+__time64_t
+__time_t64 (__time64_ *timer)
+{
+ __set_errno (ENOSYS);
+
+ if (timer != NULL)
+ *timer = (__time64_t) -1;
+ return (__time64_t) -1;
+}
+libc_hidden_def (__time_t64)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:56 UTC
Permalink
These implementations use only 32-bit time kernel syscalls.

Therefore, stime() will always set errno to EOVERFLOW and return -1 for dates beyond Y2038.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/stime.c | 70 +++++++++++++++++++++++++++++++++++++++++
time/Versions | 1 +
time/stime.c | 17 ++++++++++
3 files changed, 88 insertions(+)
create mode 100644 sysdeps/unix/sysv/linux/stime.c

diff --git a/sysdeps/unix/sysv/linux/stime.c b/sysdeps/unix/sysv/linux/stime.c
new file mode 100644
index 0000000000..177c9334ef
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/stime.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 1992-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stddef.h> /* For NULL. */
+#include <sys/time.h>
+#include <time.h>
+
+/* Set the system clock to *WHEN. */
+
+int
+stime (const time_t *when)
+{
+ struct timeval tv;
+
+ if (when == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ tv.tv_sec = *when;
+ tv.tv_usec = 0;
+ return __settimeofday (&tv, (struct timezone *) 0);
+}
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__stime_t64 (const __time64_t *when)
+{
+ struct timeval tv32;
+
+ if (when == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement 64-bit-time syscall case */
+ }
+
+ if (*when > INT_MAX)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ tv32.tv_sec = *when;
+ tv32.tv_usec = 0;
+ return __settimeofday (&tv32, (struct timezone *) 0);
+}
diff --git a/time/Versions b/time/Versions
index 02dc8d6146..3dca51abcb 100644
--- a/time/Versions
+++ b/time/Versions
@@ -72,5 +72,6 @@ libc {
GLIBC_Y2038 {
__timespec_get64;
__time_t64;
+ __stime_t64;
}
}
diff --git a/time/stime.c b/time/stime.c
index 723eedacf1..c1c7c4c9b5 100644
--- a/time/stime.c
+++ b/time/stime.c
@@ -35,3 +35,20 @@ stime (const time_t *when)
}

stub_warning (stime)
+
+/* 64-bit time version */
+
+int
+__stime_t64 (const __time64_t *when)
+{
+ if (when == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+
+stub_warning (__stime_t64)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:57 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/time.h | 6 ++++++
misc/utimes.c | 15 +++++++++++++++
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/utimes.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 53 insertions(+)

diff --git a/include/sys/time.h b/include/sys/time.h
index 95c431f7b3..b46873f6f4 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -20,6 +20,9 @@
# include <time/sys/time.h>

# ifndef _ISOMAC
+
+# include <include/time.h>
+
extern int __gettimeofday (struct timeval *__tv,
struct timezone *__tz);
libc_hidden_proto (__gettimeofday)
@@ -39,5 +42,8 @@ extern int __utimes (const char *__file, const struct timeval __tvp[2])
attribute_hidden;
extern int __futimes (int fd, const struct timeval tvp[2]) attribute_hidden;

+extern int __utimes_t64 (const char *file, const struct __timeval64 tvp[2])
+ attribute_hidden;
+
# endif
#endif
diff --git a/misc/utimes.c b/misc/utimes.c
index 73d91ace1c..5bb1a6f963 100644
--- a/misc/utimes.c
+++ b/misc/utimes.c
@@ -37,3 +37,18 @@ __utimes (const char *file, const struct timeval tvp[2])
weak_alias (__utimes, utimes)

stub_warning (utimes)
+
+int
+__utimes_t64 (const char *file, const struct __timeval64 tvp[2])
+{
+ if (file == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+
+stub_warning (__utimes_t64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index edac9cf007..68a4cb7384 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -38,5 +38,6 @@ libc {
__sigtimedwait64;
__futimes64;
__lutimes64;
+ __utimes_t64;
}
}
diff --git a/sysdeps/unix/sysv/linux/utimes.c b/sysdeps/unix/sysv/linux/utimes.c
index 038ff20ba0..91d1ac2b53 100644
--- a/sysdeps/unix/sysv/linux/utimes.c
+++ b/sysdeps/unix/sysv/linux/utimes.c
@@ -34,3 +34,34 @@ __utimes (const char *file, const struct timeval tvp[2])
}

weak_alias (__utimes, utimes)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__utimes_t64 (const char *file, const struct __timeval64 tvp[2])
+{
+ struct timeval tv32[2], *tvp32 = NULL;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement using 64-bit time syscall */
+ }
+
+ if (tvp != NULL)
+ {
+ if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX)
+ {
+ __set_errno(EOVERFLOW);
+ return -1;
+ }
+ tv32[0].tv_sec = tvp[0].tv_sec;
+ tv32[0].tv_usec = tvp[0].tv_usec;
+ tv32[1].tv_sec = tvp[1].tv_sec;
+ tv32[1].tv_usec = tvp[1].tv_usec;
+ tvp32 = tv32;
+ }
+
+ return INLINE_SYSCALL (utimes, 2, file, tvp32);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:58 UTC
Permalink
Implementing a 64-bit settimeofday requires adding a new
file to build under time/ and we cannot name that new file
'settimeofday.c' or it will break the 32-bit settimeofday
symbol, so we call it 'settimeofday64.c'.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/gettimeofday.c | 26 ++++++++++++++++++++++++++
time/Versions | 1 +
time/gettimeofday.c | 10 ++++++++++
3 files changed, 37 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/gettimeofday.c b/sysdeps/unix/sysv/linux/gettimeofday.c
index 6afa407ac4..5ebbddef4f 100644
--- a/sysdeps/unix/sysv/linux/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/gettimeofday.c
@@ -37,3 +37,29 @@ __gettimeofday (struct timeval *tv, struct timezone *tz)
libc_hidden_def (__gettimeofday)
weak_alias (__gettimeofday, gettimeofday)
libc_hidden_weak (gettimeofday)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__gettimeofday_t64 (struct __timeval64 *tv, struct timezone *tz)
+{
+ struct timeval tv32;
+ int result;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement using 64-bit time syscall */
+ }
+
+ result = INLINE_VSYSCALL (gettimeofday, 2, &tv32, tz);
+
+ if (result == 0)
+ {
+ tv->tv_sec = tv32.tv_sec;
+ tv->tv_usec = tv32.tv_usec;
+ }
+
+ return result;
+}
diff --git a/time/Versions b/time/Versions
index 3dca51abcb..7daf158a8b 100644
--- a/time/Versions
+++ b/time/Versions
@@ -73,5 +73,6 @@ libc {
__timespec_get64;
__time_t64;
__stime_t64;
+ __gettimeofday_t64;
}
}
diff --git a/time/gettimeofday.c b/time/gettimeofday.c
index 1d675b6b23..b21d7d4b71 100644
--- a/time/gettimeofday.c
+++ b/time/gettimeofday.c
@@ -32,3 +32,13 @@ weak_alias (__gettimeofday, gettimeofday)
libc_hidden_weak (gettimeofday)

stub_warning (gettimeofday)
+
+/* 64-bit time version */
+
+int
+__gettimeofday_t64 (struct timeval *tv, struct timezone *tz)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__gettimeofday_t64)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:41:59 UTC
Permalink
Implementing a 64-bit settimeofday requires adding a new
file to build under time/ and we cannot name that new file
'settimeofday.c' or it will break the 32-bit settimeofday
symbol, so we call it 'settimeofday64.c'.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/settimeofday64.c | 44 ++++++++++++++++++++++++++++++++
time/Makefile | 3 ++-
time/Versions | 1 +
time/settimeofday.c | 8 ++++++
4 files changed, 55 insertions(+), 1 deletion(-)
create mode 100644 sysdeps/unix/sysv/linux/settimeofday64.c

diff --git a/sysdeps/unix/sysv/linux/settimeofday64.c b/sysdeps/unix/sysv/linux/settimeofday64.c
new file mode 100644
index 0000000000..7aaef1c613
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/settimeofday64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <errno.h>
+#include <sys/time.h>
+
+extern int __y2038_linux_support;
+
+int __settimeofday_t64(const struct __timeval64 *tv,
+ const struct timezone *tz)
+{
+ struct timeval tv32;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit syscall */
+ }
+
+ if (tv && tv->tv_sec > INT_MAX)
+ {
+ __set_errno(EOVERFLOW);
+ return -1;
+ }
+
+ tv32.tv_sec = tv->tv_sec;
+ tv32.tv_usec = tv->tv_usec;
+
+ return settimeofday(&tv32, tz);
+}
diff --git a/time/Makefile b/time/Makefile
index 317c4d8901..5fb26f6dbf 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -36,7 +36,8 @@ routines := offtime asctime clock ctime ctime_r difftime \
stime dysize timegm ftime \
getdate strptime strptime_l \
strftime wcsftime strftime_l wcsftime_l \
- timespec_get
+ timespec_get \
+ settimeofday64
aux := era alt_digit lc-time-cleanup

tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index 7daf158a8b..d420770af3 100644
--- a/time/Versions
+++ b/time/Versions
@@ -74,5 +74,6 @@ libc {
__time_t64;
__stime_t64;
__gettimeofday_t64;
+ __settimeofday_t64;
}
}
diff --git a/time/settimeofday.c b/time/settimeofday.c
index 317c93d35f..65db5ab6e5 100644
--- a/time/settimeofday.c
+++ b/time/settimeofday.c
@@ -29,3 +29,11 @@ __settimeofday (const struct timeval *tv, const struct timezone *tz)
stub_warning (settimeofday)

weak_alias (__settimeofday, settimeofday)
+
+int
+__settimeofday_t64 (const struct timeval *tv, const struct timezone *tz)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__settimeofday_t64)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:00 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
rt/Makefile | 3 ++-
rt/Versions | 1 +
rt/mq_timedreceive_t64.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 rt/mq_timedreceive_t64.c

diff --git a/rt/Makefile b/rt/Makefile
index 2a6be1bcbf..0b529233b5 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -37,7 +37,8 @@ timer-routines := timer_create timer_delete timer_getoverr \
shm-routines := shm_open shm_unlink
mq-routines := mq_open mq_close mq_unlink mq_getattr mq_setattr \
mq_notify mq_send mq_receive mq_timedsend \
- mq_timedreceive
+ mq_timedreceive \
+ mq_timedreceive_t64

routines = $(clock-routines)

diff --git a/rt/Versions b/rt/Versions
index 761fbb8a4c..cb88f7196c 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -46,5 +46,6 @@ librt {
__timer_settime64;
__timerfd_gettime64;
__timerfd_settime64;
+ __mq_timedreceive_t64;
}
}
diff --git a/rt/mq_timedreceive_t64.c b/rt/mq_timedreceive_t64.c
new file mode 100644
index 0000000000..54ba50fe84
--- /dev/null
+++ b/rt/mq_timedreceive_t64.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <mqueue.h>
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+/* Receive the oldest from highest priority messages in message queue
+ MQDES, stop waiting if ABS_TIMEOUT expires. */
+ssize_t
+__mq_timedreceive_t64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len,
+ unsigned int *__restrict msg_prio,
+ const struct timespec *__restrict abs_timeout)
+{
+ struct timespec ts32, *tsp32 = NULL;
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit syscall */
+ }
+
+ if (abs_timeout)
+ {
+ ts32.tv_sec = abs_timeout->tv_sec;
+ ts32.tv_nsec = abs_timeout->tv_nsec;
+ tsp32 = &ts32;
+ }
+ return mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, tsp32);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:01 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
rt/Makefile | 2 +-
rt/Versions | 1 +
rt/mq_timedsend_t64.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 46 insertions(+), 1 deletion(-)
create mode 100644 rt/mq_timedsend_t64.c

diff --git a/rt/Makefile b/rt/Makefile
index 0b529233b5..a1dccd048d 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -38,7 +38,7 @@ shm-routines := shm_open shm_unlink
mq-routines := mq_open mq_close mq_unlink mq_getattr mq_setattr \
mq_notify mq_send mq_receive mq_timedsend \
mq_timedreceive \
- mq_timedreceive_t64
+ mq_timedreceive_t64 mq_timedsend_t64

routines = $(clock-routines)

diff --git a/rt/Versions b/rt/Versions
index cb88f7196c..1eef2e604f 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -47,5 +47,6 @@ librt {
__timerfd_gettime64;
__timerfd_settime64;
__mq_timedreceive_t64;
+ __mq_timedsend_t64;
}
}
diff --git a/rt/mq_timedsend_t64.c b/rt/mq_timedsend_t64.c
new file mode 100644
index 0000000000..27cf166547
--- /dev/null
+++ b/rt/mq_timedsend_t64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <mqueue.h>
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+/* Add message pointed by MSG_PTR to message queue MQDES, stop blocking
+ on full message queue if ABS_TIMEOUT expires. */
+int
+__mq_timedsend_t64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
+ unsigned int msg_prio, const struct __timespec64 *abs_timeout)
+{
+ struct timespec ts32, *tsp32 = NULL;
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit syscall */
+ }
+
+ if (abs_timeout)
+ {
+ ts32.tv_sec = abs_timeout->tv_sec;
+ ts32.tv_nsec = abs_timeout->tv_nsec;
+ tsp32 = &ts32;
+ }
+ return mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, tsp32);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:02 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/Versions | 7 ++++
sysdeps/unix/sysv/linux/bits/msq.h | 20 +++++++++++
sysdeps/unix/sysv/linux/msgctl.c | 72 ++++++++++++++++++++++++++++++++++++++
3 files changed, 99 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 202ffccc29..3fcd1c252b 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -172,4 +172,11 @@ libc {
# functions used by nscd
__netlink_assert_response;
}
+
+ # Y2038 symbols are given their own version until they can be put in
+ # the right place
+
+ GLIBC_Y2038 {
+ __msgctl_t64;
+ }
}
diff --git a/sysdeps/unix/sysv/linux/bits/msq.h b/sysdeps/unix/sysv/linux/bits/msq.h
index 31c4863e7b..ba3f24f720 100644
--- a/sysdeps/unix/sysv/linux/bits/msq.h
+++ b/sysdeps/unix/sysv/linux/bits/msq.h
@@ -35,6 +35,25 @@ typedef unsigned long int msglen_t;

/* Structure of record for one message inside the kernel.
The type `struct msg' is opaque. */
+#ifdef __USE_TIME_BITS64
+struct msqid_ds
+{
+ struct ipc_perm msg_perm; /* structure describing operation permission */
+ __time64_t msg_stime; /* time of last msgsnd command */
+ unsigned long int __glibc_reserved1;
+ __time64_t msg_rtime; /* time of last msgrcv command */
+ unsigned long int __glibc_reserved2;
+ __time64_t msg_ctime; /* time of last change */
+ unsigned long int __glibc_reserved3;
+ unsigned long int __msg_cbytes; /* current number of bytes on queue */
+ msgqnum_t msg_qnum; /* number of messages currently on queue */
+ msglen_t msg_qbytes; /* max number of bytes allowed on queue */
+ __pid_t msg_lspid; /* pid of last msgsnd() */
+ __pid_t msg_lrpid; /* pid of last msgrcv() */
+ unsigned long int __glibc_reserved4;
+ unsigned long int __glibc_reserved5;
+};
+#else
struct msqid_ds
{
struct ipc_perm msg_perm; /* structure describing operation permission */
@@ -52,6 +71,7 @@ struct msqid_ds
unsigned long int __glibc_reserved4;
unsigned long int __glibc_reserved5;
};
+#endif

#ifdef __USE_MISC

diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index e5ae621420..d62faf71ce 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -69,3 +69,75 @@ __old_msgctl (int msqid, int cmd, struct __old_msqid_ds *buf)
}
compat_symbol (libc, __old_msgctl, msgctl, GLIBC_2_0);
#endif
+
+/* 64-bit time version */
+
+struct __msqid_ds_t64
+{
+ struct ipc_perm msg_perm; /* structure describing operation permission */
+ __time64_t msg_stime; /* time of last msgsnd command */
+ unsigned long int __glibc_reserved1;
+ __time64_t msg_rtime; /* time of last msgrcv command */
+ unsigned long int __glibc_reserved2;
+ __time64_t msg_ctime; /* time of last change */
+ unsigned long int __glibc_reserved3;
+ unsigned long int __msg_cbytes; /* current number of bytes on queue */
+ msgqnum_t msg_qnum; /* number of messages currently on queue */
+ msglen_t msg_qbytes; /* max number of bytes allowed on queue */
+ __pid_t msg_lspid; /* pid of last msgsnd() */
+ __pid_t msg_lrpid; /* pid of last msgrcv() */
+ unsigned long int __glibc_reserved4;
+ unsigned long int __glibc_reserved5;
+};
+
+extern int __y2038_linux_support;
+
+int
+__msgctl_t64 (int msqid, int cmd, struct __msqid_ds_t64 *buf)
+{
+ int result;
+ struct msqid_ds buf32, *pbuf32 = NULL;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit syscalls */
+ }
+
+ if (cmd == IPC_SET && buf != NULL)
+ {
+ buf32.msg_qbytes = buf->msg_qbytes;
+ buf32.msg_perm.uid = buf->msg_perm.uid;
+ buf32.msg_perm.gid = buf->msg_perm.gid;
+ buf32.msg_perm.mode = buf->msg_perm.mode;
+ }
+
+ if (cmd == IPC_SET || cmd == IPC_STAT)
+ pbuf32 = &buf32;
+
+#ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
+ result = INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, pbuf32);
+#else
+ result = INLINE_SYSCALL_CALL (ipc, IPCOP_msgctl, msqid, cmd | __IPC_64,
+ 0, pbuf32);
+#endif
+
+ if (cmd == IPC_STAT && result == 0 && buf != NULL)
+ {
+ buf->msg_perm = buf32.msg_perm;
+ buf->msg_stime = buf32.msg_stime;
+ buf->__glibc_reserved1 = buf32.__glibc_reserved1;
+ buf->msg_rtime = buf32.msg_rtime;
+ buf->__glibc_reserved2 = buf32.__glibc_reserved2;
+ buf->msg_ctime = buf32.msg_ctime;
+ buf->__glibc_reserved3 = buf32.__glibc_reserved3;
+ buf->__msg_cbytes = buf32.__msg_cbytes;
+ buf->msg_qnum = buf32.msg_qnum;
+ buf->msg_qbytes = buf32.msg_qbytes;
+ buf->msg_lspid = buf32.msg_lspid;
+ buf->msg_lrpid = buf32.msg_lrpid;
+ buf->__glibc_reserved4 = buf32.__glibc_reserved4;
+ buf->__glibc_reserved5 = buf32.__glibc_reserved5;
+ }
+
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:03 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
posix/Makefile | 3 ++-
posix/Versions | 7 +++++++
posix/sched_rr_gi64.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+), 1 deletion(-)
create mode 100644 posix/sched_rr_gi64.c

diff --git a/posix/Makefile b/posix/Makefile
index 33abcaed7a..e5b8fd28f3 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -61,7 +61,8 @@ routines := \
spawnattr_getsigmask spawnattr_getschedpolicy spawnattr_getschedparam \
spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
posix_madvise \
- get_child_max sched_cpucount sched_cpualloc sched_cpufree
+ get_child_max sched_cpucount sched_cpualloc sched_cpufree \
+ sched_rr_gi64

aux := init-posix environ
tests := test-errno tstgetopt testfnm runtests runptests \
diff --git a/posix/Versions b/posix/Versions
index bb481a505b..dd6d8340d5 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -137,4 +137,11 @@ libc {
GLIBC_PRIVATE {
__libc_fork; __libc_pread; __libc_pwrite;
}
+
+ # Y2038 symbols are given their own version until they can be put in
+ # the right place
+
+ GLIBC_Y2038 {
+ __sched_rr_get_interval_t64;
+ }
}
diff --git a/posix/sched_rr_gi64.c b/posix/sched_rr_gi64.c
new file mode 100644
index 0000000000..7f4f5cf729
--- /dev/null
+++ b/posix/sched_rr_gi64.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sched.h>
+#include <sys/types.h>
+
+extern int __y2038_linux_support;
+
+/* Get the SCHED_RR interval for the named process. */
+
+int
+__sched_rr_get_interval_t64 (pid_t pid, struct __timespec64 *t)
+{
+ struct timespec ts32;
+ int result;
+
+ if (t == NULL)
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit syscall */
+ }
+
+ result = sched_rr_get_interval(pid, &ts32);
+ if (result == 0)
+ {
+ t->tv_sec = ts32.tv_sec;
+ t->tv_nsec = ts32.tv_nsec;
+ t->tv_pad = 0;
+ }
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:04 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
time/Makefile | 2 +-
time/Versions | 1 +
time/nanosleep64.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 time/nanosleep64.c

diff --git a/time/Makefile b/time/Makefile
index 5fb26f6dbf..d50c3ddfd8 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,7 +37,7 @@ routines := offtime asctime clock ctime ctime_r difftime \
getdate strptime strptime_l \
strftime wcsftime strftime_l wcsftime_l \
timespec_get \
- settimeofday64
+ settimeofday64 nanosleep64
aux := era alt_digit lc-time-cleanup

tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index d420770af3..e6812240e9 100644
--- a/time/Versions
+++ b/time/Versions
@@ -75,5 +75,6 @@ libc {
__stime_t64;
__gettimeofday_t64;
__settimeofday_t64;
+ __nanosleep_t64;
}
}
diff --git a/time/nanosleep64.c b/time/nanosleep64.c
new file mode 100644
index 0000000000..b43b7595eb
--- /dev/null
+++ b/time/nanosleep64.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <time.h>
+
+extern int __y2038_linux_support;
+
+/* Pause execution for a number of nanoseconds. */
+int
+__nanosleep_t64 (const struct __timespec64 *requested_time,
+ struct __timespec64 *remaining)
+{
+ struct timespec treq32, *treqp32 = NULL;
+ struct timespec trem32, *tremp32 = NULL;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit time syscalls */
+ }
+
+ if (requested_time)
+ {
+ if (requested_time->tv_sec > INT_MAX)
+ {
+ __set_errno(EOVERFLOW);
+ return -1;
+ }
+ treq32.tv_sec = requested_time->tv_sec;
+ treq32.tv_nsec = requested_time->tv_nsec;
+ treqp32 = & treq32;
+ }
+
+ if (remaining)
+ tremp32 = &trem32;
+
+ int result = nanosleep(treqp32, tremp32);
+
+ if (result == 1 && errno == EINTR && remaining)
+ {
+ remaining->tv_sec = trem32.tv_sec;
+ remaining->tv_nsec = trem32.tv_nsec;
+ remaining->tv_pad = 0;
+ }
+
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:05 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/adjtime.c | 43 +++++++++++++++++++++++++++++++++++++++
time/Versions | 1 +
time/adjtime.c | 10 +++++++++
3 files changed, 54 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index d98d77064e..28a75a2e40 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -90,3 +90,46 @@ ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv)
#ifdef NO_LOCAL_ADJTIME
weak_alias (__adjtime, adjtime)
#endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int __adjtime_t64 (const struct __timeval64 *itv,
+ struct __timeval64 *otv)
+{
+ struct TIMEX tntx;
+
+ if (itv)
+ {
+ struct TIMEVAL tmp;
+
+ /* We will do some check here. */
+ tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L;
+ tmp.tv_usec = itv->tv_usec % 1000000L;
+ if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC)
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+ tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L;
+ tntx.modes = ADJ_OFFSET_SINGLESHOT;
+ }
+ else
+ tntx.modes = ADJ_OFFSET_SS_READ;
+
+ if (__glibc_unlikely (ADJTIMEX (&tntx) < 0))
+ return -1;
+
+ if (otv)
+ {
+ if (tntx.offset < 0)
+ {
+ otv->tv_usec = -(-tntx.offset % 1000000);
+ otv->tv_sec = -(-tntx.offset / 1000000);
+ }
+ else
+ {
+ otv->tv_usec = tntx.offset % 1000000;
+ otv->tv_sec = tntx.offset / 1000000;
+ }
+ }
+ return 0;
+}
diff --git a/time/Versions b/time/Versions
index e6812240e9..0f4600f33c 100644
--- a/time/Versions
+++ b/time/Versions
@@ -76,5 +76,6 @@ libc {
__gettimeofday_t64;
__settimeofday_t64;
__nanosleep_t64;
+ __adjtime_t64;
}
}
diff --git a/time/adjtime.c b/time/adjtime.c
index 180bf48e13..8c01bd0787 100644
--- a/time/adjtime.c
+++ b/time/adjtime.c
@@ -31,3 +31,13 @@ __adjtime (const struct timeval *delta, struct timeval *olddelta)
stub_warning (adjtime)

weak_alias (__adjtime, adjtime)
+
+/* 64-bit time version */
+
+int
+__adjtime_t64 (const struct __timeval64 *delta, struct __timeval64 *olddelta)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__adjtime_t64)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:06 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/utime.h | 7 +++++++
io/Versions | 1 +
io/utime.c | 16 ++++++++++++++++
sysdeps/posix/utime.c | 22 ++++++++++++++++++++++
4 files changed, 46 insertions(+)

diff --git a/include/utime.h b/include/utime.h
index 5049251311..eb907f7472 100644
--- a/include/utime.h
+++ b/include/utime.h
@@ -6,4 +6,11 @@
libc_hidden_proto (utime)
#endif

+/* Structure describing file times, 64-bit time version. */
+struct __utimbuf64
+ {
+ __time64_t actime; /* Access time. */
+ __time64_t modtime; /* Modification time. */
+ };
+
#endif /* utime.h */
diff --git a/io/Versions b/io/Versions
index 33629a0d4e..622eb6fe12 100644
--- a/io/Versions
+++ b/io/Versions
@@ -134,5 +134,6 @@ libc {
__xstat64_t64;
__lxstat64_t64;
__fxstatat64_t64;
+ __utime_t64;
}
}
diff --git a/io/utime.c b/io/utime.c
index 242ccd120a..776203896b 100644
--- a/io/utime.c
+++ b/io/utime.c
@@ -37,3 +37,19 @@ utime (const char *file, const struct utimbuf *times)
libc_hidden_def (utime)

stub_warning (utime)
+
+/* 64-bit time version */
+
+int
+__utime_t64 (const char *file, const struct utimbuf *times)
+{
+ if (file == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (__utime_t64)
diff --git a/sysdeps/posix/utime.c b/sysdeps/posix/utime.c
index c8fe60ba91..d6662b7d4b 100644
--- a/sysdeps/posix/utime.c
+++ b/sysdeps/posix/utime.c
@@ -45,3 +45,25 @@ utime (const char *file, const struct utimbuf *times)
return __utimes (file, tvp);
}
libc_hidden_def (utime)
+
+/* 64-bit time version */
+
+int
+__utime_t64 (const char *file, const struct __utimbuf64 *times)
+{
+ struct __timeval64 timevals[2];
+ struct __timeval64 *tvp;
+
+ if (times != NULL)
+ {
+ timevals[0].tv_sec = (time_t) times->actime;
+ timevals[0].tv_usec = 0L;
+ timevals[1].tv_sec = (time_t) times->modtime;
+ timevals[1].tv_usec = 0L;
+ tvp = timevals;
+ }
+ else
+ tvp = NULL;
+
+ return __utimes_t64 (file, tvp);
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:08 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
time/Makefile | 3 ++-
time/Versions | 1 +
time/getitimer64.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 time/getitimer64.c

diff --git a/time/Makefile b/time/Makefile
index d50c3ddfd8..f2b50626b6 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,7 +37,8 @@ routines := offtime asctime clock ctime ctime_r difftime \
getdate strptime strptime_l \
strftime wcsftime strftime_l wcsftime_l \
timespec_get \
- settimeofday64 nanosleep64
+ settimeofday64 nanosleep64 \
+ getitimer64
aux := era alt_digit lc-time-cleanup

tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index 0f4600f33c..cc05014bd8 100644
--- a/time/Versions
+++ b/time/Versions
@@ -77,5 +77,6 @@ libc {
__settimeofday_t64;
__nanosleep_t64;
__adjtime_t64;
+ __getitimer_t64;
}
}
diff --git a/time/getitimer64.c b/time/getitimer64.c
new file mode 100644
index 0000000000..2b19adf953
--- /dev/null
+++ b/time/getitimer64.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+extern int __y2038_linux_support;
+
+/* Set *VALUE to the current setting of timer WHICH.
+ Return 0 on success, -1 on errors. */
+int
+__getitimer_t64 (enum __itimer_which which,
+ struct __itimerval_t64 *value)
+{
+ struct itimerval value32, *value32p= NULL;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit syscall */
+ }
+
+ if (value != NULL)
+ value32p = &value32;
+
+ int result = getitimer(which, value32p);
+
+ if (result == 0 && value != NULL)
+ {
+ value->it_interval.tv_sec = value32.it_interval.tv_sec;
+ value->it_interval.tv_usec = value32.it_interval.tv_usec;
+ value->it_value.tv_sec = value32.it_value.tv_sec;
+ value->it_value.tv_usec = value32.it_value.tv_usec;
+ }
+
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:09 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
time/Makefile | 2 +-
time/Versions | 1 +
time/setitimer64.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+), 1 deletion(-)
create mode 100644 time/setitimer64.c

diff --git a/time/Makefile b/time/Makefile
index f2b50626b6..5a36d1274b 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -38,7 +38,7 @@ routines := offtime asctime clock ctime ctime_r difftime \
strftime wcsftime strftime_l wcsftime_l \
timespec_get \
settimeofday64 nanosleep64 \
- getitimer64
+ getitimer64 setitimer64
aux := era alt_digit lc-time-cleanup

tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index cc05014bd8..b847718757 100644
--- a/time/Versions
+++ b/time/Versions
@@ -78,5 +78,6 @@ libc {
__nanosleep_t64;
__adjtime_t64;
__getitimer_t64;
+ __setitimer_t64;
}
}
diff --git a/time/setitimer64.c b/time/setitimer64.c
new file mode 100644
index 0000000000..79cd1ef486
--- /dev/null
+++ b/time/setitimer64.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+extern int __y2038_linux_support;
+
+/* Set the timer WHICH to *NEW. If OLD is not NULL,
+ set *OLD to the old value of timer WHICH.
+ Returns 0 on success, -1 on errors. */
+int
+__setitimer_t64 (enum __itimer_which which,
+ const struct __itimerval_t64 *new,
+ struct __itimerval_t64 *old)
+{
+ struct itimerval new32, *new32p = NULL;
+ struct itimerval old32, *old32p = NULL;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: use 64-bit syscall */
+ }
+
+ if (new != NULL)
+ {
+ if (new->it_interval.tv_sec > INT_MAX ||
+ new->it_value.tv_sec > INT_MAX)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ new32.it_interval.tv_sec = new->it_interval.tv_sec;
+ new32.it_interval.tv_usec = new->it_interval.tv_usec;
+ new32.it_value.tv_sec = new->it_value.tv_sec;
+ new32.it_value.tv_usec = new->it_value.tv_usec;
+ new32p = &new32;
+ }
+
+ if (old != NULL)
+ old32p = &old32;
+
+ int result = setitimer(which, new32p, old32p);
+
+ if (old)
+ {
+ old->it_interval.tv_sec = old32.it_interval.tv_sec;
+ old->it_interval.tv_usec = old32.it_interval.tv_usec;
+ old->it_value.tv_sec = old32.it_value.tv_sec;
+ old->it_value.tv_usec = old32.it_value.tv_usec;
+ }
+
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:11 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
resource/Makefile | 2 +-
resource/Versions | 7 ++
resource/getrusage64.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 193 insertions(+), 1 deletion(-)
create mode 100644 resource/getrusage64.c

diff --git a/resource/Makefile b/resource/Makefile
index 06bc7a2fb2..81a865105b 100644
--- a/resource/Makefile
+++ b/resource/Makefile
@@ -23,7 +23,7 @@ headers := sys/resource.h bits/resource.h sys/vlimit.h sys/vtimes.h \
ulimit.h bits/types/struct_rusage.h

routines := getrlimit setrlimit getrlimit64 setrlimit64 getrusage ulimit \
- vlimit vtimes getpriority setpriority nice
+ vlimit vtimes getpriority setpriority nice getrusage64

tests = tst-getrlimit bug-ulimit1

diff --git a/resource/Versions b/resource/Versions
index d6c2ccee1b..84f3a79769 100644
--- a/resource/Versions
+++ b/resource/Versions
@@ -25,4 +25,11 @@ libc {
GLIBC_PRIVATE {
__getrlimit;
}
+
+ # Y2038 symbols are given their own version until they can be put in
+ # the right place
+
+ GLIBC_Y2038 {
+ __getrusage_t64;
+ }
}
diff --git a/resource/getrusage64.c b/resource/getrusage64.c
new file mode 100644
index 0000000000..6c81137a8b
--- /dev/null
+++ b/resource/getrusage64.c
@@ -0,0 +1,185 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/resource.h>
+#include <include/time.h>
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+/* Structure which says how much of each resource has been used. */
+/* 64-bit time version */
+/* The purpose of all the unions is to have the kernel-compatible layout
+ while keeping the API type as 'long int', and among machines where
+ __syscall_slong_t is not 'long int', this only does the right thing
+ for little-endian ones, like x32. */
+struct __rusage_t64
+ {
+ /* Total amount of user time used. */
+ struct __timeval64 ru_utime;
+ /* Total amount of system time used. */
+ struct __timeval64 ru_stime;
+ /* Maximum resident set size (in kilobytes). */
+ __extension__ union
+ {
+ long int ru_maxrss;
+ __syscall_slong_t __ru_maxrss_word;
+ };
+ /* Amount of sharing of text segment memory
+ with other processes (kilobyte-seconds). */
+ /* Maximum resident set size (in kilobytes). */
+ __extension__ union
+ {
+ long int ru_ixrss;
+ __syscall_slong_t __ru_ixrss_word;
+ };
+ /* Amount of data segment memory used (kilobyte-seconds). */
+ __extension__ union
+ {
+ long int ru_idrss;
+ __syscall_slong_t __ru_idrss_word;
+ };
+ /* Amount of stack memory used (kilobyte-seconds). */
+ __extension__ union
+ {
+ long int ru_isrss;
+ __syscall_slong_t __ru_isrss_word;
+ };
+ /* Number of soft page faults (i.e. those serviced by reclaiming
+ a page from the list of pages awaiting reallocation. */
+ __extension__ union
+ {
+ long int ru_minflt;
+ __syscall_slong_t __ru_minflt_word;
+ };
+ /* Number of hard page faults (i.e. those that required I/O). */
+ __extension__ union
+ {
+ long int ru_majflt;
+ __syscall_slong_t __ru_majflt_word;
+ };
+ /* Number of times a process was swapped out of physical memory. */
+ __extension__ union
+ {
+ long int ru_nswap;
+ __syscall_slong_t __ru_nswap_word;
+ };
+ /* Number of input operations via the file system. Note: This
+ and `ru_oublock' do not include operations with the cache. */
+ __extension__ union
+ {
+ long int ru_inblock;
+ __syscall_slong_t __ru_inblock_word;
+ };
+ /* Number of output operations via the file system. */
+ __extension__ union
+ {
+ long int ru_oublock;
+ __syscall_slong_t __ru_oublock_word;
+ };
+ /* Number of IPC messages sent. */
+ __extension__ union
+ {
+ long int ru_msgsnd;
+ __syscall_slong_t __ru_msgsnd_word;
+ };
+ /* Number of IPC messages received. */
+ __extension__ union
+ {
+ long int ru_msgrcv;
+ __syscall_slong_t __ru_msgrcv_word;
+ };
+ /* Number of signals delivered. */
+ __extension__ union
+ {
+ long int ru_nsignals;
+ __syscall_slong_t __ru_nsignals_word;
+ };
+ /* Number of voluntary context switches, i.e. because the process
+ gave up the process before it had to (usually to wait for some
+ resource to be available). */
+ __extension__ union
+ {
+ long int ru_nvcsw;
+ __syscall_slong_t __ru_nvcsw_word;
+ };
+ /* Number of involuntary context switches, i.e. a higher priority process
+ became runnable or the current process used up its time slice. */
+ __extension__ union
+ {
+ long int ru_nivcsw;
+ __syscall_slong_t __ru_nivcsw_word;
+ };
+ };
+
+extern int __y2038_linux_support;
+
+int __getrusage_t64 (__rusage_who_t __who, struct __rusage_t64 *__usage)
+{
+ int result;
+ struct rusage usage32;
+
+ if (__y2038_linux_support)
+ {
+ // TODO: use 64-bit-time syscall if available
+ }
+
+ result = INLINE_SYSCALL(getrusage, 2, __who, &usage32);
+ /* Copy fields from 32-bit into 64-bit rusage structure */
+ /* Total amount of user time used. */
+ __usage->ru_utime.tv_sec = usage32.ru_utime.tv_sec;
+ __usage->ru_utime.tv_usec = usage32.ru_utime.tv_usec;
+ /* Total amount of system time used. */
+ __usage->ru_stime.tv_sec = usage32.ru_stime.tv_sec;
+ __usage->ru_stime.tv_usec = usage32.ru_stime.tv_usec;
+ /* Maximum resident set size (in kilobytes). */
+ __usage->ru_maxrss = usage32.ru_maxrss;
+ /* Amount of sharing of text segment memory
+ with other processes (kilobyte-seconds). */
+ /* Maximum resident set size (in kilobytes). */
+ __usage->ru_ixrss = usage32.ru_ixrss;
+ /* Amount of data segment memory used (kilobyte-seconds). */
+ __usage->ru_idrss = usage32.ru_idrss;
+ /* Amount of stack memory used (kilobyte-seconds). */
+ __usage->ru_isrss = usage32.ru_isrss;
+ /* Number of soft page faults (i.e. those serviced by reclaiming
+ a page from the list of pages awaiting reallocation. */
+ __usage->ru_minflt = usage32.ru_minflt;
+ /* Number of hard page faults (i.e. those that required I/O). */
+ __usage->ru_majflt = usage32.ru_majflt;
+ /* Number of times a process was swapped out of physical memory. */
+ __usage->ru_nswap = usage32.ru_nswap;
+ /* Number of input operations via the file system. Note: This
+ and `ru_oublock' do not include operations with the cache. */
+ __usage->ru_inblock = usage32.ru_inblock;
+ /* Number of output operations via the file system. */
+ __usage->ru_oublock = usage32.ru_oublock;
+ /* Number of IPC messages sent. */
+ __usage->ru_msgsnd = usage32.ru_msgsnd;
+ /* Number of IPC messages received. */
+ __usage->ru_msgrcv = usage32.ru_msgrcv;
+ /* Number of signals delivered. */
+ __usage->ru_nsignals = usage32.ru_nsignals;
+ /* Number of voluntary context switches, i.e. because the process
+ gave up the process before it had to (usually to wait for some
+ resource to be available). */
+ __usage->ru_nvcsw = usage32.ru_nvcsw;
+ /* Number of involuntary context switches, i.e. a higher priority process
+ became runnable or the current process used up its time slice. */
+ __usage->ru_nivcsw = usage32.ru_nivcsw;
+
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:12 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/include/time.h b/include/time.h
index 47ec6e67b6..5db1d44470 100644
--- a/include/time.h
+++ b/include/time.h
@@ -59,6 +59,19 @@ struct __itimerval_t64
struct __timeval64 it_value;
};

+struct __ntptimeval_t64
+{
+ struct __timeval64 time; /* current time (ro) */
+ long int maxerror; /* maximum error (us) (ro) */
+ long int esterror; /* estimated error (us) (ro) */
+ long int tai; /* TAI offset (ro) */
+
+ long int __glibc_reserved1;
+ long int __glibc_reserved2;
+ long int __glibc_reserved3;
+ long int __glibc_reserved4;
+};
+
extern __typeof (clock_getres) __clock_getres;
extern __typeof (clock_gettime) __clock_gettime;
libc_hidden_proto (__clock_gettime)
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:13 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/Versions | 1 +
sysdeps/unix/sysv/linux/ntp_gettime.c | 25 +++++++++++++++++++++++++
2 files changed, 26 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 3fcd1c252b..38739b062a 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -178,5 +178,6 @@ libc {

GLIBC_Y2038 {
__msgctl_t64;
+ __ntp_gettime_t64;
}
}
diff --git a/sysdeps/unix/sysv/linux/ntp_gettime.c b/sysdeps/unix/sysv/linux/ntp_gettime.c
index 915b099dc5..3d6a52c8b9 100644
--- a/sysdeps/unix/sysv/linux/ntp_gettime.c
+++ b/sysdeps/unix/sysv/linux/ntp_gettime.c
@@ -18,6 +18,7 @@
#define ntp_gettime ntp_gettime_redirect

#include <sys/timex.h>
+#include <include/time.h>

#undef ntp_gettime

@@ -39,3 +40,27 @@ ntp_gettime (struct ntptimeval *ntv)
ntv->esterror = tntx.esterror;
return result;
}
+
+/* The 64-bit-time version */
+
+extern int __y2038_linux_support;
+
+int
+__ntp_gettime_t64 (struct __ntptimeval_t64 *ntv)
+{
+ struct timex tntx;
+ int result;
+
+ if (__y2038_linux_support)
+ {
+ // TODO: use 64-bit syscall if possible
+ }
+
+ tntx.modes = 0;
+ result = __adjtimex (&tntx);
+ ntv->time.tv_sec = tntx.time.tv_sec;
+ ntv->time.tv_usec = tntx.time.tv_usec;
+ ntv->maxerror = tntx.maxerror;
+ ntv->esterror = tntx.esterror;
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:14 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sysdeps/unix/sysv/linux/Versions | 1 +
sysdeps/unix/sysv/linux/ntp_gettimex.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 38739b062a..5f9a7ab08d 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -179,5 +179,6 @@ libc {
GLIBC_Y2038 {
__msgctl_t64;
__ntp_gettime_t64;
+ __ntp_gettimex_t64;
}
}
diff --git a/sysdeps/unix/sysv/linux/ntp_gettimex.c b/sysdeps/unix/sysv/linux/ntp_gettimex.c
index 8ac180163d..c47da4daff 100644
--- a/sysdeps/unix/sysv/linux/ntp_gettimex.c
+++ b/sysdeps/unix/sysv/linux/ntp_gettimex.c
@@ -16,6 +16,7 @@
<http://www.gnu.org/licenses/>. */

#include <sys/timex.h>
+#include <include/time.h>

#ifndef MOD_OFFSET
# define modes mode
@@ -40,3 +41,33 @@ ntp_gettimex (struct ntptimeval *ntv)
ntv->__glibc_reserved4 = 0;
return result;
}
+
+/* The 64-bit-time version */
+
+extern int __y2038_linux_support;
+
+int
+__ntp_gettimex_t64 (struct __ntptimeval_t64 *ntv)
+{
+ struct timex tntx;
+ int result;
+
+ if (__y2038_linux_support)
+ {
+ // TODO: use 64-bit syscall if possible
+ }
+
+ tntx.modes = 0;
+ result = __adjtimex (&tntx);
+ ntv->time.tv_sec = tntx.time.tv_sec;
+ ntv->time.tv_usec = tntx.time.tv_usec;
+ ntv->maxerror = tntx.maxerror;
+ ntv->maxerror = tntx.maxerror;
+ ntv->esterror = tntx.esterror;
+ ntv->tai = tntx.tai;
+ ntv->__glibc_reserved1 = 0;
+ ntv->__glibc_reserved2 = 0;
+ ntv->__glibc_reserved3 = 0;
+ ntv->__glibc_reserved4 = 0;
+ return result;
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:15 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/time.h | 31 +++++++++++++++
sysdeps/unix/sysv/linux/adjtime.c | 81 +++++++++++++++++++++++++++++++++++++++
time/Versions | 1 +
3 files changed, 113 insertions(+)

diff --git a/include/time.h b/include/time.h
index 5db1d44470..1914c20a75 100644
--- a/include/time.h
+++ b/include/time.h
@@ -72,6 +72,37 @@ struct __ntptimeval_t64
long int __glibc_reserved4;
};

+/* 64-bit time version of the current struct timex */
+struct __timex_t64
+{
+ unsigned int modes; /* mode selector */
+ __syscall_slong_t offset; /* time offset (usec) */
+ __syscall_slong_t freq; /* frequency offset (scaled ppm) */
+ __syscall_slong_t maxerror; /* maximum error (usec) */
+ __syscall_slong_t esterror; /* estimated error (usec) */
+ int status; /* clock command/status */
+ __syscall_slong_t constant; /* pll time constant */
+ __syscall_slong_t precision; /* clock precision (usec) (ro) */
+ __syscall_slong_t tolerance; /* clock frequency tolerance (ppm) (ro) */
+ struct __timeval64 time; /* (read only, except for ADJ_SETOFFSET) */
+ __syscall_slong_t tick; /* (modified) usecs between clock ticks */
+ __syscall_slong_t ppsfreq; /* pps frequency (scaled ppm) (ro) */
+ __syscall_slong_t jitter; /* pps jitter (us) (ro) */
+ int shift; /* interval duration (s) (shift) (ro) */
+ __syscall_slong_t stabil; /* pps stability (scaled ppm) (ro) */
+ __syscall_slong_t jitcnt; /* jitter limit exceeded (ro) */
+ __syscall_slong_t calcnt; /* calibration intervals (ro) */
+ __syscall_slong_t errcnt; /* calibration errors (ro) */
+ __syscall_slong_t stbcnt; /* stability limit exceeded (ro) */
+
+ int tai; /* TAI offset (ro) */
+
+ /* ??? */
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32;
+};
+
extern __typeof (clock_getres) __clock_getres;
extern __typeof (clock_gettime) __clock_gettime;
libc_hidden_proto (__clock_gettime)
diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index 28a75a2e40..60211a5223 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -19,6 +19,7 @@
#include <limits.h>
#include <sys/time.h>
#include <sys/timex.h>
+#include <include/time.h>

#define MAX_SEC (INT_MAX / 1000000L - 2)
#define MIN_SEC (INT_MIN / 1000000L + 2)
@@ -133,3 +134,83 @@ int __adjtime_t64 (const struct __timeval64 *itv,
}
return 0;
}
+
+int
+__adjtimex_t64(struct __timex_t64 *tx)
+{
+ struct timex tx32;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement with a 64-bit time syscall */
+ }
+
+ if (tx == NULL)
+ {
+ __set_errno (EFAULT);
+ return -1;
+ }
+
+ if ((tx->modes & ADJ_SETOFFSET) != 0 && tx->time.tv_sec > INT_MAX)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ /* Implement with existing 32-bit time syscall */
+
+ /* Just copy everything */
+ tx32.modes = tx->modes;
+ tx32.offset = tx->offset;
+ tx32.freq = tx->freq;
+ tx32.maxerror = tx->maxerror;
+ tx32.esterror = tx->esterror;
+ tx32.status = tx->status;
+ tx32.constant = tx->constant;
+ tx32.precision = tx->precision;
+ tx32.tolerance = tx->tolerance;
+ tx32.time.tv_sec = tx->time.tv_sec;
+ tx32.time.tv_usec = tx->time.tv_usec;
+ tx32.tick = tx->tick;
+ tx32.ppsfreq = tx->ppsfreq;
+ tx32.jitter = tx->jitter;
+ tx32.shift = tx->shift;
+ tx32.stabil = tx->stabil;
+ tx32.jitcnt = tx->jitcnt;
+ tx32.calcnt = tx->calcnt;
+ tx32.errcnt = tx->errcnt;
+ tx32.stbcnt = tx->stbcnt;
+
+ tx32.tai = tx->tai;
+ /* WARNING -- anonymous fields after TAI are not copied. */
+
+ int result = ADJTIMEX(&tx32);
+
+ if (result == 0)
+ {
+ /* Just copy back everything */
+ tx->modes = tx32.modes;
+ tx->offset = tx32.offset;
+ tx->freq = tx32.freq;
+ tx->maxerror = tx32.maxerror;
+ tx->esterror = tx32.esterror;
+ tx->status = tx32.status;
+ tx->constant = tx32.constant;
+ tx->precision = tx32.precision;
+ tx->tolerance = tx32.tolerance;
+ tx->time.tv_sec = tx32.time.tv_sec;
+ tx->time.tv_usec = tx32.time.tv_usec;
+ tx->tick = tx32.tick;
+ tx->ppsfreq = tx32.ppsfreq;
+ tx->jitter = tx32.jitter;
+ tx->shift = tx32.shift;
+ tx->stabil = tx32.stabil;
+ tx->jitcnt = tx32.jitcnt;
+ tx->calcnt = tx32.calcnt;
+ tx->errcnt = tx32.errcnt;
+ tx->stbcnt = tx32.stbcnt;
+ }
+
+ return result;
+}
+weak_alias (__adjtimex_t64, __ntp_adjtime_t64);
diff --git a/time/Versions b/time/Versions
index b847718757..9e23793cfb 100644
--- a/time/Versions
+++ b/time/Versions
@@ -79,5 +79,6 @@ libc {
__adjtime_t64;
__getitimer_t64;
__setitimer_t64;
+ __adjtimex_t64;
}
}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-07 22:42:16 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/select.h | 10 +++++++
sysdeps/unix/sysv/linux/pselect.c | 61 +++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+)

diff --git a/include/sys/select.h b/include/sys/select.h
index 07bb49b994..3eb76faf9d 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -3,6 +3,9 @@

#ifndef _ISOMAC
/* Now define the internal interfaces. */
+
+#include <include/time.h>
+
extern int __pselect (int __nfds, fd_set *__readfds,
fd_set *__writefds, fd_set *__exceptfds,
const struct timespec *__timeout,
@@ -14,5 +17,12 @@ extern int __select (int __nfds, fd_set *__restrict __readfds,
struct timeval *__restrict __timeout);
libc_hidden_proto (__select)

+/* 64-bit time version */
+
+extern int __pselect_t64 (int __nfds, fd_set *__readfds,
+ fd_set *__writefds, fd_set *__exceptfds,
+ const struct __timespec64 *__timeout,
+ const __sigset_t *__sigmask);
+
#endif
#endif
diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
index b5e8c7fbcd..ce8db34843 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -79,6 +79,67 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
}
weak_alias (__pselect, pselect)

+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__pselect_t64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ const struct __timespec64 *timeout, const sigset_t *sigmask)
+{
+ struct timespec tval32, *timeout32 = NULL;
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement using Linux kernel system call */
+ }
+
+ /* The Linux kernel can in some situations update the timeout value.
+ We do not want that so use a local variable. */
+ if (timeout != NULL)
+ {
+ if (timeout->tv_sec > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ tval32.tv_sec = timeout->tv_sec;
+ tval32.tv_nsec = timeout->tv_nsec;
+ timeout32 = &tval32;
+ }
+
+ /* Note: the system call expects 7 values but on most architectures
+ we can only pass in 6 directly. If there is an architecture with
+ support for more parameters a new version of this file needs to
+ be created. */
+ struct
+ {
+ __syscall_ulong_t ss;
+ __syscall_ulong_t ss_len;
+ } data;
+
+ data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
+ data.ss_len = _NSIG / 8;
+
+ int result;
+
+#ifndef CALL_PSELECT6
+# define CALL_PSELECT6(nfds, readfds, writefds, exceptfds, timeout, data) \
+ SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds, timeout32, data)
+#endif
+
+ result = CALL_PSELECT6 (nfds, readfds, writefds, exceptfds, timeout32,
+ &data);
+
+# ifndef __ASSUME_PSELECT
+ if (result == -1 && errno == ENOSYS)
+ result = __generic_pselect (nfds, readfds, writefds, exceptfds, timeout32,
+ sigmask);
+# endif
+
+ return result;
+}
+
# ifndef __ASSUME_PSELECT
# define __pselect static __generic_pselect
# endif
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-08 17:49:07 UTC
Permalink
Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
include/sys/select.h | 5 +++
sysdeps/unix/sysv/linux/select.c | 66 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+)

diff --git a/include/sys/select.h b/include/sys/select.h
index 3eb76faf9d..df10085e72 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -24,5 +24,10 @@ extern int __pselect_t64 (int __nfds, fd_set *__readfds,
const struct __timespec64 *__timeout,
const __sigset_t *__sigmask);

+extern int __select_t64 (int __nfds, fd_set *__restrict __readfds,
+ fd_set *__restrict __writefds,
+ fd_set *__restrict __exceptfds,
+ struct __timeval64 *__restrict __timeout);
+
#endif
#endif
diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c
index be4a456a51..3e6140621c 100644
--- a/sysdeps/unix/sysv/linux/select.c
+++ b/sysdeps/unix/sysv/linux/select.c
@@ -33,6 +33,8 @@
# define __NR_select __NR__newselect
#endif

+extern int __y2038_linux_support;
+
int
__select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
@@ -69,3 +71,67 @@ libc_hidden_def (__select)

weak_alias (__select, select)
weak_alias (__select, __libc_select)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__select_t64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct __timeval64 *timeout)
+{
+ struct timeval tval32, *timeout32 = NULL;
+#ifndef __NR_select
+ int result;
+ struct timespec ts32, *tsp32 = NULL;
+#endif
+
+ if (__y2038_linux_support)
+ {
+ /* TODO: implement using Linux kernel system call */
+ }
+
+ if (timeout != NULL)
+ {
+ if (timeout->tv_sec > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ tval32.tv_sec = timeout->tv_sec;
+ tval32.tv_usec = timeout->tv_usec;
+ timeout32 = &tval32;
+ }
+
+#ifdef __NR_select
+ return SYSCALL_CANCEL (select, nfds, readfds, writefds, exceptfds,
+ timeout32);
+#else
+ if (timeout)
+ {
+ if (timeout->tv_sec > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ ts32.tv_sec = timeout->tv_sec;
+ ts32.tv_nsec = timeout->tv_usec * 1000;
+ tsp32 = &ts32;
+ }
+
+ result = SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds, tsp32,
+ NULL);
+
+ if (timeout)
+ {
+ /* Linux by default will update the timeout after a pselect6 syscall
+ (though the pselect() glibc call suppresses this behavior).
+ Since select() on Linux has the same behavior as the pselect6
+ syscall, we update the timeout here. */
+ timeout->tv_sec = ts32.tv_sec;
+ timeout->tv_usec = ts32.tv_nsec / 1000;
+ }
+
+ return result;
+#endif
+}
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-08 17:49:08 UTC
Permalink
Three functions in RPC have a struct timeval in their arguments:
pmap_rmtcall, clntudp_create, and clntudp_bufcreate.

Since these struct timeval arguments contain relative timeouts, and
since RPC timeouts can reasonably be expected to be small enough to
still fit in 32-bit representations, the implementations of these
functions just verify that the 64-bit timeout they received can fit
in 32 bits, convert it to 32 bit, and pass it to their 32-bit-time
counterparts.

Signed-off-by: Albert ARIBAUD (3ADEV) <***@3adev.fr>
---
sunrpc/clnt_udp.c | 27 +++++++++++++++++++++++++++
sunrpc/pmap_rmt.c | 23 +++++++++++++++++++++++
sunrpc/rpc/clnt.h | 24 ++++++++++++++++++++++++
sunrpc/rpc/pmap_clnt.h | 15 +++++++++++++++
4 files changed, 89 insertions(+)

diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
index df21e28f64..b02b80e2c4 100644
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -644,3 +644,30 @@ clntudp_destroy (CLIENT *cl)
mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
mem_free ((caddr_t) cl, sizeof (CLIENT));
}
+
+/* 64-bit time versions */
+
+CLIENT *
+__clntudp_create64 (struct sockaddr_in *raddr, u_long program, u_long version,
+ struct __timeval64 wait, int *sockp)
+{
+ struct timeval wait32;
+ if (wait.tv_sec > INT_MAX)
+ {
+ return NULL;
+ }
+ return clntudp_create (raddr, program, version, wait32, sockp);
+}
+
+CLIENT *
+__clntudp_bufcreate64 (struct sockaddr_in *raddr, u_long program, u_long version,
+ struct __timeval64 wait, int *sockp, u_int sendsz,
+ u_int recvsz)
+{
+ struct timeval wait32;
+ if (wait.tv_sec > INT_MAX)
+ {
+ return NULL;
+ }
+ return clntudp_bufcreate (raddr, program, version, wait32, sockp, sendsz, recvsz);
+}
diff --git a/sunrpc/pmap_rmt.c b/sunrpc/pmap_rmt.c
index 6d4ed7206c..6dd360edcd 100644
--- a/sunrpc/pmap_rmt.c
+++ b/sunrpc/pmap_rmt.c
@@ -391,3 +391,26 @@ done_broad:
return stat;
}
libc_hidden_nolink_sunrpc (clnt_broadcast, GLIBC_2_0)
+
+/* 64-bit-time version */
+
+/* The 64-bit-time version of pmap_rmtcall.
+ * Only handles 64-bit-time timeouts smaller than 2^^31 seconds.
+ */
+enum clnt_stat
+__pmap_rmtcall_t64 (struct sockaddr_in *addr, u_long prog, u_long vers,
+ u_long proc, xdrproc_t xdrargs, caddr_t argsp,
+ xdrproc_t xdrres, caddr_t resp,
+ struct __timeval64 tout, u_long *port_ptr)
+{
+ struct timeval tout32;
+ if (tout.tv_sec > INT_MAX)
+ {
+ return RPC_SYSTEMERROR;
+ }
+ tout32.tv_sec = tout.tv_sec;
+ tout32.tv_usec = tout.tv_usec;
+
+ return pmap_rmtcall (addr, prog, vers, proc, xdrargs, argsp, xdrres,
+ resp, tout32, port_ptr);
+}
diff --git a/sunrpc/rpc/clnt.h b/sunrpc/rpc/clnt.h
index f4d4a941c7..e559242eeb 100644
--- a/sunrpc/rpc/clnt.h
+++ b/sunrpc/rpc/clnt.h
@@ -329,9 +329,33 @@ extern CLIENT *clnttcp_create (struct sockaddr_in *__raddr, u_long __prog,
* u_int sendsz;
* u_int recvsz;
*/
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern CLIENT * __REDIRECT (clntudp_create,(struct sockaddr_in *__raddr,
+ u_long __program,
+ u_long __version,
+ struct timeval __wait_resend,
+ int *__sockp),
+ __clntudp_create_t64) __THROW;
+# else
+# define clntudp_create __clntudp_create_t64
+# endif
+#endif
extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, u_long __program,
u_long __version, struct timeval __wait_resend,
int *__sockp) __THROW;
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern CLIENT * __REDIRECT (clntudp_bufcreate,(struct sockaddr_in *__raddr,
+ u_long __program, u_long __version,
+ struct __timeval64 __wait_resend,
+ int *__sockp, u_int __sendsz,
+ u_int __recvsz),
+ __clntudp_bufcreate_t64) __THROW;
+# else
+# define clntudp_bufcreate __clntudp_bufcreate_t64
+# endif
+#endif
extern CLIENT *clntudp_bufcreate (struct sockaddr_in *__raddr,
u_long __program, u_long __version,
struct timeval __wait_resend, int *__sockp,
diff --git a/sunrpc/rpc/pmap_clnt.h b/sunrpc/rpc/pmap_clnt.h
index 1cc94b8fee..70ec89b723 100644
--- a/sunrpc/rpc/pmap_clnt.h
+++ b/sunrpc/rpc/pmap_clnt.h
@@ -71,6 +71,21 @@ extern bool_t pmap_set (const u_long __program, const u_long __vers,
extern bool_t pmap_unset (const u_long __program, const u_long __vers)
__THROW;
extern struct pmaplist *pmap_getmaps (struct sockaddr_in *__address) __THROW;
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern enum clnt_stat __REDIRECT (pmap_rmtcall, (struct sockaddr_in *__addr,
+ const u_long __prog,
+ const u_long __vers,
+ const u_long __proc,
+ xdrproc_t __xdrargs,
+ caddr_t __argsp, xdrproc_t __xdrres,
+ caddr_t __resp, struct timeval __tout,
+ u_long *__port_ptr),
+ __pmap_rmtcall_t64) __THROW;
+# else
+# define pmap_rmtcall __pmap_rmtcall_t64
+# endif
+#endif
extern enum clnt_stat pmap_rmtcall (struct sockaddr_in *__addr,
const u_long __prog,
const u_long __vers,
--
2.11.0
Albert ARIBAUD (3ADEV)
2017-09-08 17:49:09 UTC
Permalink
This post might be inappropriate. Click to display it.
Joseph Myers
2017-09-08 19:47:40 UTC
Permalink
I'd expect this patch to include the previously discussed #error (in
features.h) if _TIME_BITS=64 is used without _FILE_OFFSET_BITS=64.
--
Joseph S. Myers
***@codesourcery.com
Joseph Myers
2017-09-08 19:46:55 UTC
Permalink
Since the RPC functions are already obsoleted (compat symbols unless you
use --enable-obsolete-rpc), I think there is a good case for not providing
_TIME_BITS=64 variants of them (#error in the relevant headers if used
with _TIME_BITS=64), leaving it to TIRPC to provide such versions.
--
Joseph S. Myers
***@codesourcery.com
Paul Eggert
2017-09-08 19:59:27 UTC
Permalink
Post by Albert ARIBAUD (3ADEV)
+CLIENT *
+__clntudp_create64 (struct sockaddr_in *raddr, u_long program, u_long version,
+ struct __timeval64 wait, int *sockp)
+{
+ struct timeval wait32;
+ if (wait.tv_sec > INT_MAX)
+ {
+ return NULL;
+ }
+ return clntudp_create (raddr, program, version, wait32, sockp);
+}
I'm not seeing how this could work. The code does not copy the value of
'wait' to 'wait32'. And the code doesn't have a proper check for fitting
in 'int', e.g., it will do the wrong thing for INT_MIN - 1L. And there's
no error status set when the time is out of range.

I haven't reviewed the patches carefully, just caught this in a spot
check. Please look systematically for similar errors.

While you're doing that systematic review, I suggest putting something
like the following code into a suitable private include file, and using
it to tell whether a __time64_t value is in time_t range. This will
generate zero instructions when time_t is 64-bit, so generic callers can
use this function without needing any ifdefs and without losing any
performance on 64-bit time_t platforms. You should write similar static
functions for checking whether struct __timeval64 is in struct timeval
range, and similarly for struct __timespec64. These can check for the
subseconds parts being in range, as needed (watch for x32 here). The
idea is to be systematic about this stuff and to do it in one place, to
avoid ticky-tack range bugs such as are in the above-quoted code.

  /* time_t is always 'long int' in the GNU C Library.  */
  #define TIME_T_MIN LONG_MIN
  #define TIME_T_MAX LONG_MAX

  static inline bool
  fits_in_time_t (__time64_t t)
  {
  #if 7 <= __GNUC__
    return !__builtin_add_overflow_p (t, 0, TIME_T_MAX);
  #endif
    return TIME_T_MIN <= t && t <= TIME_T_MAX;
  }
Albert ARIBAUD
2017-09-09 14:37:28 UTC
Permalink
Hi Paul,
Post by Paul Eggert
Post by Albert ARIBAUD (3ADEV)
+CLIENT *
+__clntudp_create64 (struct sockaddr_in *raddr, u_long program, u_long version,
+ struct __timeval64 wait, int *sockp)
+{
+ struct timeval wait32;
+ if (wait.tv_sec > INT_MAX)
+ {
+ return NULL;
+ }
+ return clntudp_create (raddr, program, version, wait32, sockp);
+}
I'm not seeing how this could work. The code does not copy the value
of 'wait' to 'wait32'. And the code doesn't have a proper check for
fitting in 'int', e.g., it will do the wrong thing for INT_MIN - 1L.
And there's no error status set when the time is out of range.
That's a cut/paste typo during a recent cleanup round :( --
__clntudp_bufcreate64 is missing the same two lines which are present
in __pmap_rmtcall_t64 and copy the timeout into its 32-bit counterpart.
Thanks for spotting this, will add the missing lines (or possibly a
call to a conversion function, similar to your suggestion below).
Post by Paul Eggert
I haven't reviewed the patches carefully, just caught this in a spot
check. Please look systematically for similar errors.
Will do.
Post by Paul Eggert
While you're doing that systematic review, I suggest putting something
like the following code into a suitable private include file, and using
it to tell whether a __time64_t value is in time_t range. This will
generate zero instructions when time_t is 64-bit, so generic callers can
use this function without needing any ifdefs and without losing any
performance on 64-bit time_t platforms. You should write similar static
functions for checking whether struct __timeval64 is in struct timeval
range, and similarly for struct __timespec64. These can check for the
subseconds parts being in range, as needed (watch for x32 here). The
idea is to be systematic about this stuff and to do it in one place, to
avoid ticky-tack range bugs such as are in the above-quoted code.
  /* time_t is always 'long int' in the GNU C Library.  */
  #define TIME_T_MIN LONG_MIN
  #define TIME_T_MAX LONG_MAX
BTW, time_t is a signed int, but its negative range is not completely
usable since (time_t)-1 is used as an error status. So should the
TIME_T_MIN limit be LONG_MIN or should it be 0?
Post by Paul Eggert
  static inline bool
  fits_in_time_t (__time64_t t)
  {
  #if 7 <= __GNUC__
    return !__builtin_add_overflow_p (t, 0, TIME_T_MAX);
  #endif
    return TIME_T_MIN <= t && t <= TIME_T_MAX;
  }
Will do -- in fact, as I hinted above, I'll probably augment this with
timeval and timespec test and conversion functions to automate things
such as setting errno to EOVERFLOW if the conversion cannot be done.

Thanks for your comment and suggestion!

Cordialement,
Albert ARIBAUD
3ADEV
Paul Eggert
2017-09-11 06:33:01 UTC
Permalink
Post by Albert ARIBAUD
time_t is a signed int, but its negative range is not completely
usable since (time_t)-1 is used as an error status. So should the
TIME_T_MIN limit be LONG_MIN or should it be 0?
Definitely LONG_MIN. Functions like localtime accept -1 as valid input meaning
1969-12-31 23:59:59 UTC.

Even for some functions like mktime that return -1 as an error indicator, -1 can
also be a valid (non-error) return value. I help maintain application code that
can tell the difference between the two seemingly-identical -1s that mktime
returns, so that the time_t range is completely usable there too. Admittedly
it's not an ideal API.
Paul Eggert
2017-09-11 07:05:57 UTC
Permalink
/* time_t is always 'long int' in the GNU C Library. */
#define TIME_T_MIN LONG_MIN
#define TIME_T_MAX LONG_MAX
static inline bool
fits_in_time_t (__time64_t t)
{
#if 7 <= __GNUC__
return !__builtin_add_overflow_p (t, 0, TIME_T_MAX);
#endif
return TIME_T_MIN <= t && t <= TIME_T_MAX;
}
Marc Glisse suggested a simpler solution:

static inline bool
fits_in_time_t (__time64_t t)
{
return t == (time64_t) t;
}

This is documented to work for GCC, something I had forgotten, and it generates
better code for pre-7 GCC. See:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82170#c2
Paul Eggert
2017-09-11 14:07:29 UTC
Permalink
Post by Paul Eggert
static inline bool
fits_in_time_t (__time64_t t)
{
return t == (time64_t) t;
}
Ooops, that last statement should be "return t == (time_t) t;" of course. Sorry.
Albert ARIBAUD
2017-09-11 15:59:51 UTC
Permalink
Hi Paul,
Post by Paul Eggert
Post by Paul Eggert
static inline bool
fits_in_time_t (__time64_t t)
{
return t == (time64_t) t;
}
Ooops, that last statement should be "return t == (time_t) t;" of course. Sorry.
Noted -- and thanks to you and Marc for the simpler formulation.

Cordialement,
Albert ARIBAUD
3ADEV

Joseph Myers
2017-09-07 23:21:16 UTC
Permalink
General observations on this patch series:

* Nothing should use a GLIBC_Y2038 version. Use GLIBC_2.27 and update as
necessary during rebases if this doesn't get into 2.27.

* Nothing should go in architecture-specific files such as
sysdeps/unix/sysv/linux/arm/Versions. For OS-independent interfaces use
files such as time/Versions - wherever the existing versions of those
interfaces for existing time_t are.

* How such a patch series was tested needs to be described in the summary
of the series. For a series like this, full testsuite runs on multiple
32-bit and 64-bit architectures as well as use of build-many-glibcs.py to
do the compilation tests for (almost) all configurations is important (or
if a series is a preliminary version with limited architecture support,
that should be stated explicitly, but the full testsuite should still pass
on at least one 32-bit and one 64-bit architecture).

* I'd expect lots of extra tests using _TIME_BITS=64 to be added in such a
patch series, to make sure that every new ABI is covered by the testsuite.

* Documentation of _TIME_BITS is clearly needed.

* You need to make sure that new ABIs are not added / used on platforms
where time_t is already 64-bit.

* All new files need a descriptive first line before the copyright notice.

* All copyright ranges in new files should end with 2017.

* No "Contributed by" in new files.
--
Joseph S. Myers
***@codesourcery.com
Zack Weinberg
2017-09-08 16:19:08 UTC
Permalink
Post by Joseph Myers
* You need to make sure that new ABIs are not added / used on platforms
where time_t is already 64-bit.
Elaborating on this, when time_t is already 64 bits, defining
_TIME_BITS=64 should have no effect on the generated code, and
defining _TIME_BITS=32 should cause a compile-time error.

* We are not going to land these patches until the kernel side is
finalized. All of the places where you have "// TODO: implement after
the kernel does" must be replaced with an actual implementation.
Likewise, we need a complete implementation for all supported
architectures before landing. You're not on the hook to implement
this feature for the Hurd, but you should coordinate with Samuel
Thibault so that at least you do not make glibc-for-Hurd more broken
than it already is.

(But I would encourage you to create a named branch in glibc git for
this project if you haven't already, to make it easier for others to
experiment with it.)

* I understand that you are trying to make the transition as seamless
as possible with _TIME_BITS and so on, but I would seriously question
whether it is appropriate to preserve super-legacy APIs such as
'stime' and 'utime' in the extended mode. (I'd put the cutoff at
'gettimeofday', which is still heavily used even though
'clock_gettime' officially supersedes it.)

* The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
is, as discussed at great length earlier, incorrect and should be
ignored. It should instead be a new typedef 'nsec_t' available in
<sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
field (all _t names are reserved for future extension, so the typedef
doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
HTML5 folks put it) must, of course, be documented.

* We do not use Signed-off-by: and we actively want you to _not_
include it in your patch submissions. (We have the FSF-mandated
actual copyright assignments instead.)

* The patch series is split too finely. I recommend breaking it up by
type instead of by function -- time64_t + all the functions that use
only time64_t; struct timeval64 + all the functions that use only
time64_t and/or struct timeval64; and so on.

zw
Joseph Myers
2017-09-08 16:43:14 UTC
Permalink
Post by Zack Weinberg
* I understand that you are trying to make the transition as seamless
as possible with _TIME_BITS and so on, but I would seriously question
whether it is appropriate to preserve super-legacy APIs such as
'stime' and 'utime' in the extended mode. (I'd put the cutoff at
'gettimeofday', which is still heavily used even though
'clock_gettime' officially supersedes it.)
I don't think utime is super-legacy; it's in the 2008 edition of POSIX.
Now, stime is not part of any supported standard (it was withdrawn in
XPG3) - such old BSD/SVID interfaces that are now in __USE_MISC but no
other standard are definitely worth considering for obsoletion (removing
declarations / documentation, making into compat symbols not available for
new ports / static linking) if there are clear replacements for any
current uses / not much current use. And such obsoletion for nonstandard
time-related interfaces may well be a useful preliminary to reduce the
number of interfaces needing _TIME_BITS=64 versions. (Many such
interfaces are of course not time-related but just as deserving of
consideration for obsoletion; in general obsoletion of one such interface
is independent of obsoletion of any others.)
Post by Zack Weinberg
* The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
is, as discussed at great length earlier, incorrect and should be
ignored. It should instead be a new typedef 'nsec_t' available in
And as discussed, I disagree and don't think we should invent any such
typedef or deviate from this requirement, given that long is fully able to
represent all valid nanoseconds values, in the absence of clear evidence
that POSIX and ISO C agree with removing that requirement (e.g. an Austin
Group issue tagged issue8 with accepted changes for the next revision of
POSIX, combined with acceptance for C2X in WG14 minutes of the issue
raised by the Austin Group liaison - or a WG14 change accepted for C2X
with agreement on the Austin Group side following the change being passed
in the other direction). When the matter was raised with the Austin Group
in May 2014, no-one contradicted Rich Felker's comment (which I agree
with) that the x32 issue is just a Linux kernel bug which needs to be
fixed. (I think this use of long is *less* of an issue than e.g. printf
returning int, since you can legitimately print more characters than fit
in int.)
Post by Zack Weinberg
<sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
field (all _t names are reserved for future extension, so the typedef
doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
They are not reserved in ISO C, only in POSIX.
--
Joseph S. Myers
***@codesourcery.com
Paul Eggert
2017-09-08 16:53:55 UTC
Permalink
(I think this use of long is*less* of an issue than e.g. printf
returning int, since you can legitimately print more characters than fit
in int.)
printf is obviously more-important since it's used all over the place
and is more likely to run into the arbitrary int limit. That being said,
in practice GNU Coreutils, GNU Emacs, and other application code that I
help maintain long ago stopped assuming the POSIX requirement that
tv_nsec must be of type 'long', precisely because we want to be portable
to x32. So from my point of view this ship already sailed and the POSIX
requirement is no longer helpful; on the contrary, it is misleading
programmers who are trying to write portable software.

If the issue is raised again at the Austin Group level, please let us
know. I at least would like to put in my two cents.
Zack Weinberg
2017-09-08 17:01:03 UTC
Permalink
Post by Joseph Myers
Post by Zack Weinberg
* I understand that you are trying to make the transition as seamless
as possible with _TIME_BITS and so on, but I would seriously question
whether it is appropriate to preserve super-legacy APIs such as
'stime' and 'utime' in the extended mode. (I'd put the cutoff at
'gettimeofday', which is still heavily used even though
'clock_gettime' officially supersedes it.)
I don't think utime is super-legacy; it's in the 2008 edition of POSIX.
Hmm, OK.
Post by Joseph Myers
Now, stime is not part of any supported standard (it was withdrawn in
XPG3) - such old BSD/SVID interfaces that are now in __USE_MISC but no
other standard are definitely worth considering for obsoletion (removing
declarations / documentation, making into compat symbols not available for
new ports / static linking) if there are clear replacements for any
current uses / not much current use.
That's a good point. What I should have said is "before we do this,
we should inspect all affected interfaces and see whether any of them
are obsolete to the point where we should demote them to compat
symbols, at which point they don't need time64 versions".

stime is the only one I _know_ falls into that category: withdrawn in
XPG3 + completely superseded by newer APIs + niche usage (there are
very few programs that need to _set_ the system time, after all)
(unfortunately, a lot of the hits on codesearch.debian.net are
unrelated use of the same name, to the point where I can't actually
tell how many real uses there are, but I would bet any program that
still uses it does so only as a fallback-for-legacy-OSes from
clock_settime and friends).
Post by Joseph Myers
Post by Zack Weinberg
* The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
is, as discussed at great length earlier, incorrect and should be
ignored. It should instead be a new typedef 'nsec_t' available in
And as discussed, I disagree and don't think we should invent any such
typedef or deviate from this requirement, given that long is fully able to
represent all valid nanoseconds values
Neither you, nor Rich, nor anyone else on the cited Austin Group
discussion has addressed the actual issue, which is that this is a
datum embedded in structures passed across the kernel/user boundary by
reference, it is impossible to enumerate all such structures,
therefore its type _must_ be a typedef so that it can be made to match
the kernel's expectations, whatever those might be.

(And I don't particularly see why people seem to think this is an
x32-specific issue. It potentially affects *any* 32-bit ABI on a
64-bit kernel.)
Post by Joseph Myers
Post by Zack Weinberg
<sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
field (all _t names are reserved for future extension, so the typedef
doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
They are not reserved in ISO C, only in POSIX.
<sys/types.h> doesn't exist in ISO C as far as I know, so how could it
be? But any program that uses it opts into POSIX's specification for
that header, even if compiled with -std=c89 and no _foo_SOURCE
definitions.

zw
Joseph Myers
2017-09-08 17:24:39 UTC
Permalink
Post by Zack Weinberg
Post by Joseph Myers
And as discussed, I disagree and don't think we should invent any such
typedef or deviate from this requirement, given that long is fully able to
represent all valid nanoseconds values
Neither you, nor Rich, nor anyone else on the cited Austin Group
discussion has addressed the actual issue, which is that this is a
datum embedded in structures passed across the kernel/user boundary by
reference, it is impossible to enumerate all such structures,
therefore its type _must_ be a typedef so that it can be made to match
the kernel's expectations, whatever those might be.
I don't see this as in any way an issue for having a definition of struct
timespec that conforms to ISO C and POSIX requirements. Code passing data
to the kernel knows the structures being used locally and needs to convert
it to the kernel's layout, which might be e.g. struct __kernel_timespec64.
I don't see that as different in essence from e.g. converting a local-time
broken down date/hours/minutes/seconds/nanoseconds value before passing it
to the kernel, if that's the form the particular application stores time
in. It just so happens that, as an optimization, we can arrange the
layout so that we both are POSIX-compatible and do not require any layout
conversions between timestamps coming *from* the kernel and struct
timespec.
Post by Zack Weinberg
(And I don't particularly see why people seem to think this is an
x32-specific issue. It potentially affects *any* 32-bit ABI on a
64-bit kernel.)
The kernel does the conversion just fine for a pure 32-bit struct timespec
- as it does for the entire compat interface - and could do them perfectly
well for a structure with 64-bit seconds and 32-bit (+ padding)
nanoseconds. It just so happens not to for the very specific case of x32.
Post by Zack Weinberg
Post by Joseph Myers
Post by Zack Weinberg
<sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
field (all _t names are reserved for future extension, so the typedef
doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
They are not reserved in ISO C, only in POSIX.
<sys/types.h> doesn't exist in ISO C as far as I know, so how could it
be? But any program that uses it opts into POSIX's specification for
My point is that you can't expose nsec_t, even as a typedef for long, in
<time.h> for C11.
--
Joseph S. Myers
***@codesourcery.com
Zack Weinberg
2017-09-08 18:32:43 UTC
Permalink
Post by Joseph Myers
Post by Zack Weinberg
Neither you, nor Rich, nor anyone else on the cited Austin Group
discussion has addressed the actual issue, which is that this is a
datum embedded in structures passed across the kernel/user boundary by
reference, it is impossible to enumerate all such structures,
therefore its type _must_ be a typedef so that it can be made to match
the kernel's expectations, whatever those might be.
I don't see this as in any way an issue for having a definition of struct
timespec that conforms to ISO C and POSIX requirements. Code passing data
to the kernel knows the structures being used locally and needs to convert
it to the kernel's layout, which might be e.g. struct __kernel_timespec64.
This only works if all such structures can be enumerated and forced
through a compatibility layer. History indicates that it is not, in
fact, possible to enumerate all such structures (the problem case I
know about is device-specific ioctl operations, which tend to be
created by driver authors who don't realize the need for ABI
compatibility shims until it's too late).
Post by Joseph Myers
Post by Zack Weinberg
(And I don't particularly see why people seem to think this is an
x32-specific issue. It potentially affects *any* 32-bit ABI on a
64-bit kernel.)
The kernel does the conversion just fine for a pure 32-bit struct timespec
- as it does for the entire compat interface
For the reason given above, I confidently predict that there is at
least one failure to do this conversion correctly in every released
kernel ever.
Post by Joseph Myers
Post by Zack Weinberg
<sys/types.h> doesn't exist in ISO C as far as I know, so how could it
be? But any program that uses it opts into POSIX's specification for
My point is that you can't expose nsec_t, even as a typedef for long, in
<time.h> for C11.
I suppose it could be __nsec_t in time.h, but I would prefer to
include "and time.h defines nsec_t" in the scope of the willful
violation of C11.

zw
Albert ARIBAUD
2017-09-08 17:41:54 UTC
Permalink
Hi Zack,
Post by Zack Weinberg
Post by Joseph Myers
* You need to make sure that new ABIs are not added / used on platforms
where time_t is already 64-bit.
Elaborating on this, when time_t is already 64 bits, defining
_TIME_BITS=64 should have no effect on the generated code, and
defining _TIME_BITS=32 should cause a compile-time error.
Will add.
Post by Zack Weinberg
* We are not going to land these patches until the kernel side is
finalized. All of the places where you have "// TODO: implement after
the kernel does" must be replaced with an actual implementation.
Likewise, we need a complete implementation for all supported
architectures before landing. You're not on the hook to implement
this feature for the Hurd, but you should coordinate with Samuel
Thibault so that at least you do not make glibc-for-Hurd more broken
than it already is.
Regarding whether the patches should land only once the kernel is
Y0238-safe: these patches are intended to run even on a current and thus
completely Y2038-unsafe kernel, in which case they use 64-bit-time on
user side (to make applications compiled with _TIME_BITS==64 happy at
least until Y2038 happens) and 32-bit time on kernel side. So I don't
see why these patches should wait for a Y2038-safe kernel per se.

Re the TODOs: note that right now, all these TODOs are coded in such a
way that the implementation "falls through" to using 32-bit syscalls or
code, just like it would if running on an older kernel.
Post by Zack Weinberg
(But I would encourage you to create a named branch in glibc git for
this project if you haven't already, to make it easier for others to
experiment with it.)
There is such a branch, mentioned in the implementation part of the
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign document.
Post by Zack Weinberg
* I understand that you are trying to make the transition as seamless
as possible with _TIME_BITS and so on, but I would seriously question
whether it is appropriate to preserve super-legacy APIs such as
'stime' and 'utime' in the extended mode. (I'd put the cutoff at
'gettimeofday', which is still heavily used even though
'clock_gettime' officially supersedes it.)
I'm all for not adding 64-bit-time versions of APIs which are obsolete.
The patch series is organized to facilitate removing or adding types and
functions.

As to which APIs should be made obsolete, there appears to be room for
debate.

I will add a section in the design document listing obsolete(d) APIs
(there are a few which are tagged as such, but not in a section of
their own yet) and as consensus emerges, I will update the patch series
and document.
Post by Zack Weinberg
* The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
is, as discussed at great length earlier, incorrect and should be
ignored. It should instead be a new typedef 'nsec_t' available in
<sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
field (all _t names are reserved for future extension, so the typedef
doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
HTML5 folks put it) must, of course, be documented.
(seems to be a topic for debate)
Post by Zack Weinberg
* We do not use Signed-off-by: and we actively want you to _not_
include it in your patch submissions. (We have the FSF-mandated
actual copyright assignments instead.)
Will fix.
Post by Zack Weinberg
* The patch series is split too finely. I recommend breaking it up by
type instead of by function -- time64_t + all the functions that use
only time64_t; struct timeval64 + all the functions that use only
time64_t and/or struct timeval64; and so on.
As indicated above, I broke it up by type and function (except when
dependencies made it really impractical) to easy adding or removing (and
reviewing) individual functions. 50-odd patches are manageable IMO, but
maybe some people may be put off by it... What I'll do is keep two
branches: this fine-grained one, and a coarser-grained one where all
changes related to one type are grouped. Best of both worlds.
Post by Zack Weinberg
zw
Thanks for your review!

Cordialement,
Albert ARIBAUD
3ADEV
Joseph Myers
2017-09-08 17:59:00 UTC
Permalink
Post by Albert ARIBAUD
Regarding whether the patches should land only once the kernel is
Y0238-safe: these patches are intended to run even on a current and thus
completely Y2038-unsafe kernel, in which case they use 64-bit-time on
user side (to make applications compiled with _TIME_BITS==64 happy at
least until Y2038 happens) and 32-bit time on kernel side. So I don't
see why these patches should wait for a Y2038-safe kernel per se.
Where the kernel layouts of structures are suitable for use by glibc, we'd
like to avoid translation layers. E.g., we need to know what the kernel's
struct stat64 variant for 64-bit time_t will look like to ensure no
translation layer is needed. (If the answer is that statx is the
interface that should be used for 64-bit times in struct stat so the
kernel doesn't need to define such a stat64 variant, then the translation
layer is needed anyway and we should maybe use the asm-generic 64-bit
struct stat variant of the layout on all 32-bit platforms.)
--
Joseph S. Myers
***@codesourcery.com
Albert ARIBAUD
2017-09-08 18:16:19 UTC
Permalink
On Fri, 8 Sep 2017 17:59:00 +0000, Joseph Myers
Post by Joseph Myers
Post by Albert ARIBAUD
Regarding whether the patches should land only once the kernel is
Y0238-safe: these patches are intended to run even on a current and thus
completely Y2038-unsafe kernel, in which case they use 64-bit-time on
user side (to make applications compiled with _TIME_BITS==64 happy at
least until Y2038 happens) and 32-bit time on kernel side. So I don't
see why these patches should wait for a Y2038-safe kernel per se.
Where the kernel layouts of structures are suitable for use by glibc, we'd
like to avoid translation layers. E.g., we need to know what the kernel's
struct stat64 variant for 64-bit time_t will look like to ensure no
translation layer is needed. (If the answer is that statx is the
interface that should be used for 64-bit times in struct stat so the
kernel doesn't need to define such a stat64 variant, then the translation
layer is needed anyway and we should maybe use the asm-generic 64-bit
struct stat variant of the layout on all 32-bit platforms.)
Understood -- but as soon as 64-bit-time types are frozen on the kernel
side, we could freeze the corresponding GLIBC API types (hopefully
without a translation layer needed) and then if GLIBC gets out there
before the kernel does, it won't be a problem since in any case the
64-bit-time implementation must fall back to 32-bit syscalls if the
64-bit syscalls return an ENOSYS.

Cordialement,
Albert ARIBAUD
3ADEV
Zack Weinberg
2017-09-08 18:36:07 UTC
Permalink
Post by Albert ARIBAUD
On Fri, 8 Sep 2017 17:59:00 +0000, Joseph Myers
Post by Joseph Myers
Post by Albert ARIBAUD
Regarding whether the patches should land only once the kernel is
Y0238-safe: these patches are intended to run even on a current and thus
completely Y2038-unsafe kernel, in which case they use 64-bit-time on
user side (to make applications compiled with _TIME_BITS==64 happy at
least until Y2038 happens) and 32-bit time on kernel side. So I don't
see why these patches should wait for a Y2038-safe kernel per se.
Where the kernel layouts of structures are suitable for use by glibc, we'd
like to avoid translation layers. E.g., we need to know what the kernel's
struct stat64 variant for 64-bit time_t will look like to ensure no
translation layer is needed. (If the answer is that statx is the
interface that should be used for 64-bit times in struct stat so the
kernel doesn't need to define such a stat64 variant, then the translation
layer is needed anyway and we should maybe use the asm-generic 64-bit
struct stat variant of the layout on all 32-bit platforms.)
Understood -- but as soon as 64-bit-time types are frozen on the kernel
side, we could freeze the corresponding GLIBC API types (hopefully
without a translation layer needed) and then if GLIBC gets out there
before the kernel does, it won't be a problem since in any case the
64-bit-time implementation must fall back to 32-bit syscalls if the
64-bit syscalls return an ENOSYS.
I think that's right. Syscalls we can add support for later, types
are much more troublesome.

zw
Albert ARIBAUD
2017-09-08 17:08:32 UTC
Permalink
Hi Joseph,

On Thu, 7 Sep 2017 23:21:16 +0000, Joseph Myers
Post by Joseph Myers
* Nothing should use a GLIBC_Y2038 version. Use GLIBC_2.27 and update as
necessary during rebases if this doesn't get into 2.27.
Understood, will do.
Post by Joseph Myers
* Nothing should go in architecture-specific files such as
sysdeps/unix/sysv/linux/arm/Versions. For OS-independent interfaces
use files such as time/Versions - wherever the existing versions of
those interfaces for existing time_t are.
Will do.
Post by Joseph Myers
* How such a patch series was tested needs to be described in the summary
of the series. For a series like this, full testsuite runs on multiple
32-bit and 64-bit architectures as well as use of build-many-glibcs.py to
do the compilation tests for (almost) all configurations is important (or
if a series is a preliminary version with limited architecture support,
that should be stated explicitly, but the full testsuite should still pass
on at least one 32-bit and one 64-bit architecture).
Will do. Right now, the patches are tested using an ad hoc system (as
stated in the cover letter). I'll run the GLIBC test suite and add
results to the cover letter in the next patcxh series iteration.
Post by Joseph Myers
* I'd expect lots of extra tests using _TIME_BITS=64 to be added in such a
patch series, to make sure that every new ABI is covered by the testsuite.
Indeed.
Post by Joseph Myers
* Documentation of _TIME_BITS is clearly needed.
Where should this documentation go?
Post by Joseph Myers
* You need to make sure that new ABIs are not added / used on platforms
where time_t is already 64-bit.
Will do.
Post by Joseph Myers
* All new files need a descriptive first line before the copyright notice.
Understood.
Post by Joseph Myers
* All copyright ranges in new files should end with 2017.
Will fix.
Post by Joseph Myers
* No "Contributed by" in new files.
Will fix.

Thanks for your feedback!

Cordialement,
Albert ARIBAUD
3ADEV
Joseph Myers
2017-09-08 17:26:26 UTC
Permalink
Post by Albert ARIBAUD
Post by Joseph Myers
* Documentation of _TIME_BITS is clearly needed.
Where should this documentation go?
In manual/creature.texi, alongside the documentation of _FILE_OFFSET_BITS.

(It occurred to me that patches 50-52 don't seem to have reached the
mailing list, so I don't know what was in them.)
--
Joseph S. Myers
***@codesourcery.com
Albert ARIBAUD
2017-09-08 19:19:27 UTC
Permalink
Hi Joseph,

On Fri, 8 Sep 2017 17:26:26 +0000, Joseph Myers
Post by Joseph Myers
Post by Albert ARIBAUD
Post by Joseph Myers
* Documentation of _TIME_BITS is clearly needed.
Where should this documentation go?
In manual/creature.texi, alongside the documentation of _FILE_OFFSET_BITS.
Thanks, will do in 01/52 of v2.
Post by Joseph Myers
(It occurred to me that patches 50-52 don't seem to have reached the
mailing list, so I don't know what was in them.)
You're correct. I did not get any NDR so I cannot tell what happened...
I have sent the rest (threaded properly after 49/52, although missing
"References:" headers to 0/48 and previous).

Cordialement,
Albert ARIBAUD
3ADEV
Albert ARIBAUD
2017-09-08 04:23:02 UTC
Permalink
On Fri, 8 Sep 2017 00:41:27 +0200, "Albert ARIBAUD (3ADEV)"
Post by Albert ARIBAUD (3ADEV)
This series implements Y2038-proof types, implementation, internal
functions, and APIs. For more information, see documentation at
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign
Each patch in this series except the last add one type or function,
with a few exception where several functions are implemented as a whole.
The last patch enables the _TIME_BITS mechanism. Once this patch is
applied, API header files will will use 64-bit time if _TIME_BITS is
defined and equal to 64 prior to their inclusion, and conversively,
will use 32-bit time if _TIME_BITS is different from 64 or does not
exist.
Additional info: this RFC patch series only works on ARM, but it should
be extended to all 32-bit architectures later.

Cordialement,
Albert ARIBAUD
3ADEV
Loading...