--- Begin Message ---
Package: faketime
X-Debbugs-Cc: [email protected]
Version: 0.9.10+2024-06-05+gba9ed5b2-0.6
Severity: normal
I have prepared an NMU for faketime.
This upload updates the package to upstream 0.9.12, drops obsolete
Debian patches that are now included upstream, and includes two upstream
cherry-picks for the utimensat(2)/futimens(2) fix and its regression
test. The proposed version is 0.9.12-0.1, and a debdiff is attached.
This NMU is being done under the maintainer's LowThresholdNmu
preference.
I verified that the source package builds successfully, a clean sbuild
on unstable/amd64 succeeds, lintian passes with no issues beyond info
tags, and the smoketest and upstream autopkgtests pass. The
simple-cprogs autopkgtest failed once locally, but it appears to be a
pre-existing 1-second wrapper timing flake, and a CI rerun passed.
I am sending this notice and proceeding with the upload without delay.
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/debian/changelog
faketime-0.9.12/debian/changelog
--- faketime-0.9.10+2024-06-05+gba9ed5b2/debian/changelog 2025-01-27
08:14:40.000000000 -0500
+++ faketime-0.9.12/debian/changelog 2026-03-28 13:53:05.000000000 -0400
@@ -1,3 +1,14 @@
+faketime (0.9.12-0.1) unstable; urgency=medium
+
+ * Non-maintainer upload.
+ * New upstream version 0.9.12
+ * Add salsa-ci.yml
+ * d/patches:
+ - Remove outdated patches.
+ - Add upstream fix for utimens now handling
+
+ -- Aquila Macedo Costa <[email protected]> Sat, 28 Mar 2026 13:53:05
-0400
+
faketime (0.9.10+2024-06-05+gba9ed5b2-0.6) unstable; urgency=medium
* Non-maintainer upload.
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0002-Fix-interposition-of-clock_gettime64.patch
faketime-0.9.12/debian/patches/0002-Fix-interposition-of-clock_gettime64.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0002-Fix-interposition-of-clock_gettime64.patch
2025-01-27 08:14:40.000000000 -0500
+++
faketime-0.9.12/debian/patches/0002-Fix-interposition-of-clock_gettime64.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Fri, 17 Jan 2025 12:05:09 +0000
-Subject: Fix interposition of clock_gettime64
-
-timespec.tv_nsec is 32-bit, even though timeval.tv_usec is
-64-bit (weirdly). This doesn't matter very much in practice because
- * on little endian architectures (which is all our 32-bit release
- arches) writing to a too big integer ends up writing the
- desired value in the desired location, and
- * it doesn't affect the overall struct size on any of our actual
- architectures (which align the uint64_t to 8 so must make the
- whole struct 16 not 12), so the write overflow is harmless.
-
-> #include <time.h>
-> #include <sys/time.h>
-> #include <stdio.h>
-> struct timeval tv;
-> struct timespec ts;
-> int main(void) {
-> printf("time_t %lld\n", (unsigned long long) sizeof(time_t));
-> printf("timeval %lld %lld %lld\n",
-> (unsigned long long) sizeof(tv),
-> (unsigned long long) sizeof(tv.tv_sec),
-> (unsigned long long) sizeof(tv.tv_usec)
-> );
-> printf("timespec %lld %lld %lld\n",
-> (unsigned long long) sizeof(ts),
-> (unsigned long long) sizeof(ts.tv_sec),
-> (unsigned long long) sizeof(ts.tv_nsec)
-> );
-> }
-> (sid_armhf-dchroot)iwj@amdahl:~/Faketime/test$ gcc t.c
-> (sid_armhf-dchroot)iwj@amdahl:~/Faketime/test$ ./a.out
-> time_t 8
-> timeval 16 8 8
-> timespec 16 8 4
-> (sid_armhf-dchroot)iwj@amdahl:~/Faketime/test$
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/487
----
- src/libfaketime.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index cb37bcf..d93bfa1 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -168,7 +168,7 @@ struct utimbuf {
- struct __timespec64
- {
- uint64_t tv_sec; /* Seconds */
-- uint64_t tv_nsec; /* Nanoseconds */
-+ uint32_t tv_nsec; /* this is 32-bit, apparently! */
- };
-
- /*
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0003-Interpose-__time64.patch
faketime-0.9.12/debian/patches/0003-Interpose-__time64.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0003-Interpose-__time64.patch
2025-01-27 08:14:40.000000000 -0500
+++ faketime-0.9.12/debian/patches/0003-Interpose-__time64.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Fri, 17 Jan 2025 09:03:21 +0000
-Subject: Interpose __time64
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/487
----
- src/libfaketime.c | 21 +++++++++++++++++++++
- 1 file changed, 21 insertions(+)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index d93bfa1..aa78c33 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -2437,6 +2437,27 @@ int __clock_gettime64(clockid_t clk_id, struct
__timespec64 *tp64)
- return result;
- }
-
-+/* this is used by 32-bit architectures only */
-+uint64_t __time64(uint64_t *write_out)
-+{
-+ struct timespec tp;
-+ uint64_t output;
-+ int error;
-+
-+ error = clock_gettime(CLOCK_REALTIME, &tp);
-+ if (error == -1)
-+ {
-+ return (uint64_t)error;
-+ }
-+ output = tp.tv_sec;
-+
-+ if (write_out)
-+ {
-+ *write_out = output;
-+ }
-+ return output;
-+}
-+
- #ifdef TIME_UTC
- #ifdef MACOS_DYLD_INTERPOSE
- int macos_timespec_get(struct timespec *ts, int base)
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0004-Interpose-gettimeofday64.patch
faketime-0.9.12/debian/patches/0004-Interpose-gettimeofday64.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0004-Interpose-gettimeofday64.patch
2025-01-27 08:14:40.000000000 -0500
+++ faketime-0.9.12/debian/patches/0004-Interpose-gettimeofday64.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Fri, 17 Jan 2025 12:08:23 +0000
-Subject: Interpose gettimeofday64
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/487
----
- src/libfaketime.c | 19 +++++++++++++++++++
- 1 file changed, 19 insertions(+)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index aa78c33..2123d83 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -171,6 +171,13 @@ struct __timespec64
- uint32_t tv_nsec; /* this is 32-bit, apparently! */
- };
-
-+/* __timespec64 is needed for clock_gettime64 on 32-bit architectures */
-+struct __timeval64
-+{
-+ uint64_t tv_sec; /* Seconds */
-+ uint64_t tv_usec; /* this is 64-bit, apparently! */
-+};
-+
- /*
- * Per thread variable, which we turn on inside real_* calls to avoid
modifying
- * time multiple times of for the whole process to prevent faking time
-@@ -2437,6 +2444,18 @@ int __clock_gettime64(clockid_t clk_id, struct
__timespec64 *tp64)
- return result;
- }
-
-+/* this is used by 32-bit architectures only */
-+int __gettimeofday64(struct __timeval64 *tv64, void *tz)
-+{
-+ struct timeval tv;
-+ int result;
-+
-+ result = gettimeofday(&tv, tz);
-+ tv64->tv_sec = tv.tv_sec;
-+ tv64->tv_usec = tv.tv_usec;
-+ return result;
-+}
-+
- /* this is used by 32-bit architectures only */
- uint64_t __time64(uint64_t *write_out)
- {
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0005-Re-disable-faking-utime-by-default.patch
faketime-0.9.12/debian/patches/0005-Re-disable-faking-utime-by-default.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0005-Re-disable-faking-utime-by-default.patch
2025-01-27 08:14:40.000000000 -0500
+++
faketime-0.9.12/debian/patches/0005-Re-disable-faking-utime-by-default.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Sun, 19 Jan 2025 22:17:08 +0000
-Subject: Re-disable faking utime by default
-
-Fixes
- https://github.com/wolfcw/libfaketime/issues/483
-
-See also
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1093412#35
-Hopefully this will fix Debian #1093412.
-
-This patch is now upstream MR
- https://github.com/wolfcw/libfaketime/pull/486
----
- src/libfaketime.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index 2123d83..c0e793a 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -891,7 +891,7 @@ static bool load_time(struct timespec *tp)
- *
=======================================================================
- */
- #ifdef FAKE_UTIME
--static int fake_utime_disabled = 0;
-+static int fake_utime_disabled = 1;
- #endif
-
-
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0006-Replace-data-race-with-use-of-pthread_once-ftpl_init.patch
faketime-0.9.12/debian/patches/0006-Replace-data-race-with-use-of-pthread_once-ftpl_init.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0006-Replace-data-race-with-use-of-pthread_once-ftpl_init.patch
2025-01-27 08:14:40.000000000 -0500
+++
faketime-0.9.12/debian/patches/0006-Replace-data-race-with-use-of-pthread_once-ftpl_init.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Tue, 21 Jan 2025 18:44:42 +0000
-Subject: Replace data race with use of pthread_once (ftpl_init)
-
-At the cost of no longer nicely detecting recursive initialisation
-problems.
-
-Closes: #1093599
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/488
----
- src/libfaketime.c | 16 ++++++++++------
- 1 file changed, 10 insertions(+), 6 deletions(-)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index c0e793a..0cbdbf9 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -319,7 +319,7 @@ static bool check_missing_real(const char *name, bool
missing)
- #define CHECK_MISSING_REAL(name) \
- check_missing_real(#name, (NULL == real_##name))
-
--static int initialized = 0;
-+static pthread_once_t initialized_once_control = PTHREAD_ONCE_INIT;
-
- /* prototypes */
- static int fake_gettimeofday(struct timeval *tv);
-@@ -2361,6 +2361,13 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp)
- #endif
- {
- int result;
-+ ftpl_init();
-+ // If ftpl_init ends up recursing, pthread_once will deadlock.
-+ // So the remaining recursion code is now unreachable.
-+ // Hopefully this doesn't happen in practice.
-+
-+/*
-+
- static int recursion_depth = 0;
-
- if (!initialized)
-@@ -2399,6 +2406,7 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp)
- #endif
- recursion_depth--;
- }
-+ */
- /* sanity check */
- if (tp == NULL)
- {
-@@ -2859,7 +2867,6 @@ static void ftpl_really_init(void)
-
- #undef dlsym
- #undef dlvsym
-- initialized = 1;
-
- #ifdef FAKE_STATELESS
- if (0) ft_shm_init();
-@@ -3110,10 +3117,7 @@ static void ftpl_really_init(void)
- }
-
- inline static void ftpl_init(void) {
-- if (!initialized)
-- {
-- ftpl_really_init();
-- }
-+ pthread_once(&initialized_once_control, ftpl_really_init);
- }
-
- void *ft_dlvsym(void *handle, const char *symbol, const char *version,
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0007-Replace-data-race-with-use-of-pthread_once-ft_shm_in.patch
faketime-0.9.12/debian/patches/0007-Replace-data-race-with-use-of-pthread_once-ft_shm_in.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0007-Replace-data-race-with-use-of-pthread_once-ft_shm_in.patch
2025-01-27 08:14:40.000000000 -0500
+++
faketime-0.9.12/debian/patches/0007-Replace-data-race-with-use-of-pthread_once-ft_shm_in.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Tue, 21 Jan 2025 18:50:07 +0000
-Subject: Replace data race with use of pthread_once (ft_shm_init)
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/488
----
- src/libfaketime.c | 14 ++++++++------
- 1 file changed, 8 insertions(+), 6 deletions(-)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index 0cbdbf9..611f4db 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -536,16 +536,20 @@ static void ft_shm_destroy(void)
- }
- }
-
-+static pthread_once_t ft_shm_initialized_once_control = PTHREAD_ONCE_INIT;
-+
-+static void ft_shm_really_init (void);
- static void ft_shm_init (void)
-+{
-+ pthread_once(&ft_shm_initialized_once_control, ft_shm_really_init);
-+}
-+
-+static void ft_shm_really_init (void)
- {
- int ticks_shm_fd;
- char sem_name[256], shm_name[256], *ft_shared_env =
getenv("FAKETIME_SHARED");
- sem_t *shared_semR = NULL;
- static int nt=1;
-- static int ft_shm_initialized = 0;
--
-- /* do all of this once only */
-- if (ft_shm_initialized > 0) return;
-
- /* create semaphore and shared memory locally unless it has been passed
along */
- if (ft_shared_env == NULL)
-@@ -625,8 +629,6 @@ static void ft_shm_init (void)
- { /* force the deletion of the shm sync env variable */
- unsetenv("FAKETIME_SHARED");
- }
--
-- ft_shm_initialized = 1;
- }
-
- static void ft_cleanup (void)
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0008-Call-ftpl_init-before-using-monotonic_conds_lock.patch
faketime-0.9.12/debian/patches/0008-Call-ftpl_init-before-using-monotonic_conds_lock.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0008-Call-ftpl_init-before-using-monotonic_conds_lock.patch
2025-01-27 08:14:40.000000000 -0500
+++
faketime-0.9.12/debian/patches/0008-Call-ftpl_init-before-using-monotonic_conds_lock.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Wed, 22 Jan 2025 09:11:46 +0000
-Subject: Call ftpl_init before using monotonic_conds_lock
-
-Otherwise we can use this in an uninitialised state, which is not
-allowed.
-
-We call ftpl_init in pthread_cond_init_232, but the application might
-not have called that. For example, it might have a static condition
-variable set up with PTHREAD_COND_INITIALIZER.
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/488
----
- src/libfaketime.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index 611f4db..cc3a5b5 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -3809,6 +3809,8 @@ int pthread_cond_destroy_232(pthread_cond_t *cond)
- {
- struct pthread_cond_monotonic* e;
-
-+ ftpl_init();
-+
- if (pthread_rwlock_trywrlock(&monotonic_conds_lock) != 0) {
- sched_yield();
- return EBUSY;
-@@ -3891,6 +3893,8 @@ int pthread_cond_timedwait_common(pthread_cond_t *cond,
pthread_mutex_t *mutex,
- clockid_t clk_id;
- int result = 0;
-
-+ ftpl_init();
-+
- if (abstime != NULL)
- {
- if (pthread_rwlock_tryrdlock(&monotonic_conds_lock) != 0) {
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0009-Don-t-use-_try_-locking-calls-for-monotonic_conds_lo.patch
faketime-0.9.12/debian/patches/0009-Don-t-use-_try_-locking-calls-for-monotonic_conds_lo.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0009-Don-t-use-_try_-locking-calls-for-monotonic_conds_lo.patch
2025-01-27 08:14:40.000000000 -0500
+++
faketime-0.9.12/debian/patches/0009-Don-t-use-_try_-locking-calls-for-monotonic_conds_lo.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-From: Ian Jackson <[email protected]>
-Date: Wed, 22 Jan 2025 09:29:58 +0000
-Subject: Don't use _try_ locking calls for monotonic_conds_lock
-
-This reverts commit 8ef74e33b636a53a757a945d8ebc51d0986f0d81
- "Swapped out pthread_rwlock_xxlock() ..."
-
-This could result in concurrent uses of pthread_cond_* erroneously
-returning EAGAIN, which is not permitted by the spec and which the
-application way well treat as a bug. This seems to be happening in
-gem2deb in ci.Debian.net.
-
-The commit message in 8ef74e33b636 says (rewrapped)
-
- Swapped out pthread_rwlock_xxlock(), which doesn't return if it
- can't obtain the lock, with pthread_rwlock_xxtrylock() followed by
- sched yield and error code return. The issue is sometimes a thread
- calling pthread_cond_init() or pthread_cond_destroy() can't
- acquire the lock when another thread is waiting on a condition
- variable notification via pthread_cond_timedwait(), and thus the
- thread calling pthread_cond_init() or pthread_cond_destroy() end
- up hanging indefinitely.
-
-I don't think this is true. The things that are done with
-monotonic_conds_lock held are HASH_ADD_PTR HASH_FIND_PTR etc. on
-monotonic_conds, which should all be fast and AFAICT don't in turn
-take any locks. So it shouldn't deadlock.
-
-I conjecture that the underlying bug being experienced by the author
-of "Swapped out pthread_rwlock_xxlock" was the lack of ftpl_init - ie,
-access to an uninitialised pthread_rwlock_t. That might result in a
-hang.
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/488
----
- src/libfaketime.c | 18 +++++++++---------
- 1 file changed, 9 insertions(+), 9 deletions(-)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index cc3a5b5..e03dec7 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -3794,9 +3794,9 @@ int pthread_cond_init_232(pthread_cond_t *restrict cond,
const pthread_condattr_
- struct pthread_cond_monotonic *e = (struct
pthread_cond_monotonic*)malloc(sizeof(struct pthread_cond_monotonic));
- e->ptr = cond;
-
-- if (pthread_rwlock_trywrlock(&monotonic_conds_lock) != 0) {
-- sched_yield();
-- return EAGAIN;
-+ if (pthread_rwlock_wrlock(&monotonic_conds_lock) != 0) {
-+ fprintf(stderr,"can't acquire write monotonic_conds_lock\n");
-+ exit(-1);
- }
- HASH_ADD_PTR(monotonic_conds, ptr, e);
- pthread_rwlock_unlock(&monotonic_conds_lock);
-@@ -3811,9 +3811,9 @@ int pthread_cond_destroy_232(pthread_cond_t *cond)
-
- ftpl_init();
-
-- if (pthread_rwlock_trywrlock(&monotonic_conds_lock) != 0) {
-- sched_yield();
-- return EBUSY;
-+ if (pthread_rwlock_wrlock(&monotonic_conds_lock) != 0) {
-+ fprintf(stderr,"can't acquire write monotonic_conds_lock\n");
-+ exit(-1);
- }
- HASH_FIND_PTR(monotonic_conds, &cond, e);
- if (e) {
-@@ -3897,9 +3897,9 @@ int pthread_cond_timedwait_common(pthread_cond_t *cond,
pthread_mutex_t *mutex,
-
- if (abstime != NULL)
- {
-- if (pthread_rwlock_tryrdlock(&monotonic_conds_lock) != 0) {
-- sched_yield();
-- return EAGAIN;
-+ if (pthread_rwlock_rdlock(&monotonic_conds_lock) != 0) {
-+ fprintf(stderr,"can't acquire read monotonic_conds_lock\n");
-+ exit(-1);
- }
- HASH_FIND_PTR(monotonic_conds, &cond, e);
- pthread_rwlock_unlock(&monotonic_conds_lock);
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0010-485.patch
faketime-0.9.12/debian/patches/0010-485.patch
--- faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/0010-485.patch
2025-01-27 08:14:40.000000000 -0500
+++ faketime-0.9.12/debian/patches/0010-485.patch 1969-12-31
19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-From: Gianfranco Costamagna <[email protected]>
-Date: Wed, 22 Jan 2025 12:22:37 +0100
-Subject: [PATCH] test/libmallocintercept.c: fix write function unused return
- value
-MIME-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: 8bit
-
-We should ignore the return value for logging function, to fix a new gcc ftbfs
-libmallocintercept.c: In function ‘print_msg’:
-libmallocintercept.c:27:9: error: ignoring return value of ‘write’ declared
with attribute ‘warn_unused_result’ [-Werror=unused-result]
- 27 | write(0, msg, strlen(msg));
- | ^~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
-This was merged upstream in this MR:
- https://github.com/wolfcw/libfaketime/pull/485
----
- test/libmallocintercept.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/test/libmallocintercept.c b/test/libmallocintercept.c
-index e789d34..61edbb8 100644
---- a/test/libmallocintercept.c
-+++ b/test/libmallocintercept.c
-@@ -24,7 +24,9 @@
- #include <unistd.h>
-
- static void print_msg(const char *msg) {
-- write(0, msg, strlen(msg));
-+ size_t out;
-+ out = write(0, msg, strlen(msg));
-+ (void) out; /* unused */
- }
-
- static void* actual_malloc(size_t size) {
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/add-regression-test-for-utimens-now.patch
faketime-0.9.12/debian/patches/add-regression-test-for-utimens-now.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/add-regression-test-for-utimens-now.patch
1969-12-31 19:00:00.000000000 -0500
+++ faketime-0.9.12/debian/patches/add-regression-test-for-utimens-now.patch
2026-03-28 13:53:05.000000000 -0400
@@ -0,0 +1,101 @@
+From: Aquila Macedo <[email protected]>
+Date: Fri, 27 Mar 2026 16:09:02 -0300
+Subject: Add regression test for utimensat/futimens now handling
+Origin: upstream, 483a7a703cd614452e096aa6a483cbf834c8b069
+
+Exercise the NULL and UTIME_NOW timestamp paths in timetest so the
+file-timestamp "set to now" case is covered by the test suite.
+---
+ test/timetest.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 65 insertions(+)
+
+diff --git a/test/timetest.c b/test/timetest.c
+index 18c0546..cd52cdd 100644
+--- a/test/timetest.c
++++ b/test/timetest.c
+@@ -19,6 +19,7 @@
+ */
+
+ #define _GNU_SOURCE
++#include <fcntl.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <time.h>
+@@ -44,6 +45,69 @@
+
+ #define SIG SIGUSR1
+
++static void test_utimens_now(void)
++{
++ char path[] = "/tmp/libfaketime-utimensat-XXXXXX";
++ struct timespec now_times[2];
++ int fd;
++
++ fd = mkstemp(path);
++ if (fd == -1)
++ {
++ perror("mkstemp");
++ exit(EXIT_FAILURE);
++ }
++
++ if (utimensat(AT_FDCWD, path, NULL, 0) == -1)
++ {
++ perror("utimensat(NULL)");
++ unlink(path);
++ exit(EXIT_FAILURE);
++ }
++
++ if (futimens(fd, NULL) == -1)
++ {
++ perror("futimens(NULL)");
++ close(fd);
++ unlink(path);
++ exit(EXIT_FAILURE);
++ }
++
++ now_times[0].tv_sec = now_times[1].tv_sec = 0;
++ now_times[0].tv_nsec = now_times[1].tv_nsec = UTIME_NOW;
++
++ if (utimensat(AT_FDCWD, path, now_times, 0) == -1)
++ {
++ perror("utimensat(UTIME_NOW)");
++ close(fd);
++ unlink(path);
++ exit(EXIT_FAILURE);
++ }
++
++ if (futimens(fd, now_times) == -1)
++ {
++ perror("futimens(UTIME_NOW)");
++ close(fd);
++ unlink(path);
++ exit(EXIT_FAILURE);
++ }
++
++ if (close(fd) == -1)
++ {
++ perror("close");
++ unlink(path);
++ exit(EXIT_FAILURE);
++ }
++
++ if (unlink(path) == -1)
++ {
++ perror("unlink");
++ exit(EXIT_FAILURE);
++ }
++
++ printf("utimensat()/futimens(): NOW handling passed\n");
++}
++
+ static void
+ handler(int sig, siginfo_t *si, void *uc)
+ {
+@@ -237,6 +301,7 @@ printf("%s", 0 == 1 ? argv[0] : "");
+ printf("gettimeofday() : Current date and time: %s", ctime(&tv.tv_sec));
+
+ #ifndef __APPLE__
++ test_utimens_now();
+ if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
+ {
+ perror("sigprocmask");
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/fix-utimensat-futimens-fake-now-handling.patch
faketime-0.9.12/debian/patches/fix-utimensat-futimens-fake-now-handling.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/fix-utimensat-futimens-fake-now-handling.patch
1969-12-31 19:00:00.000000000 -0500
+++
faketime-0.9.12/debian/patches/fix-utimensat-futimens-fake-now-handling.patch
2026-03-28 13:53:05.000000000 -0400
@@ -0,0 +1,103 @@
+From: Aquila Macedo <[email protected]>
+Date: Fri, 27 Mar 2026 16:04:18 -0300
+Subject: Fix utimensat/futimens handling of fake "now"
+Origin: upstream, e8a1c1fd3b265db7071823398591dc592ec8e65d
+
+Use fake_clock_gettime(CLOCK_REALTIME) to resolve NULL/UTIME_NOW
+timestamps instead of reconstructing them from user_offset. This
+avoids invalid timestamp handling in start-at faketime mode, where
+"now" is derived from the configured base time plus elapsed real time.
+
+Closes: #535
+---
+ src/libfaketime.c | 38 +++++++++++++++++++++++++++++++-------
+ 1 file changed, 31 insertions(+), 7 deletions(-)
+
+diff --git a/src/libfaketime.c b/src/libfaketime.c
+index 6d1a575..0e3d1ce 100644
+--- a/src/libfaketime.c
++++ b/src/libfaketime.c
+@@ -1243,9 +1243,22 @@ int utimes(const char *filename, const struct timeval
times[2])
+ return result;
+ }
+
++static int fake_current_realtime(struct timespec *tp)
++{
++ int result;
++
++ DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, tp));
++ if (result == -1)
++ {
++ return -1;
++ }
++
++ return fake_clock_gettime(CLOCK_REALTIME, tp);
++}
++
+ /* This conditionally offsets 2 timespec values. The caller's out_times array
+ * always contains valid translated values, even if in_times was NULL. */
+-static void fake_two_timespec(const struct timespec in_times[2], struct
timespec out_times[2])
++static int fake_two_timespec(const struct timespec in_times[2], struct
timespec out_times[2])
+ {
+ if (in_times == NULL) /* Translate NULL into 2 UTIME_NOW values */
+ {
+@@ -1254,7 +1267,7 @@ static void fake_two_timespec(const struct timespec
in_times[2], struct timespec
+ in_times = out_times;
+ }
+ struct timespec now;
+- now.tv_nsec = UTIME_OMIT; /* Wait to grab the current time to see if it's
actually needed */
++ int have_fake_now = 0;
+ int j;
+ for (j = 0; j <= 1; j++)
+ {
+@@ -1263,11 +1276,15 @@ static void fake_two_timespec(const struct timespec
in_times[2], struct timespec
+ {
+ if (fake_utime_disabled && in_times[j].tv_nsec == UTIME_NOW)
+ { /* The user wants their given fake times left alone but they
requested NOW, so turn it into fake NOW */
+- if (now.tv_nsec == UTIME_OMIT) /* did we grab "now" yet? */
++ if (!have_fake_now)
+ {
+- DONT_FAKE_TIME(real_clock_gettime(CLOCK_REALTIME, &now));
++ if (fake_current_realtime(&now) == -1)
++ {
++ return -1;
++ }
++ have_fake_now = 1;
+ }
+- timeradd2(&now, &user_offset, &out_times[j], n);
++ out_times[j] = now;
+ }
+ else if (out_times != in_times)
+ { /* Just preserve the input value */
+@@ -1279,6 +1296,7 @@ static void fake_two_timespec(const struct timespec
in_times[2], struct timespec
+ timersub2(&in_times[j], &user_offset, &out_times[j], n);
+ }
+ }
++ return 0;
+ }
+
+ #ifdef MACOS_DYLD_INTERPOSE
+@@ -1292,7 +1310,10 @@ int utimensat(int dirfd, const char *filename, const
struct timespec times[2], i
+
+ int result;
+ struct timespec tn[2];
+- fake_two_timespec(times, tn);
++ if (fake_two_timespec(times, tn) == -1)
++ {
++ return -1;
++ }
+ #ifdef MACOS_DYLD_INTERPOSE
+ DONT_FAKE_TIME(result = utimensat(dirfd, filename, tn, flags));
+ #else
+@@ -1312,7 +1333,10 @@ int futimens(int fd, const struct timespec times[2])
+
+ int result;
+ struct timespec tn[2];
+- fake_two_timespec(times, tn);
++ if (fake_two_timespec(times, tn) == -1)
++ {
++ return -1;
++ }
+ #ifdef MACOS_DYLD_INTERPOSE
+ DONT_FAKE_TIME(result = futimens(fd, tn));
+ #else
diff -Nru
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/interpose-clock_gettime64.patch
faketime-0.9.12/debian/patches/interpose-clock_gettime64.patch
---
faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/interpose-clock_gettime64.patch
2025-01-27 08:14:40.000000000 -0500
+++ faketime-0.9.12/debian/patches/interpose-clock_gettime64.patch
1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-From: Helge Deller <[email protected]>
-Date: Sun, 12 Jan 2025 22:23:16 +0000
-Subject: Interpose clock_gettime64
-
-Since debian generally added 64-bit time support on 32-bit
-arches, now glibc sometimes calls the clock_gettime64 syscall
-(and library wrapper). This function was missing, and is added here.
-
-Closes: #1064555
-
-
-This patch is part of an upstream MR:
- https://github.com/wolfcw/libfaketime/pull/487
----
- src/libfaketime.c | 24 ++++++++++++++++++++++++
- test/Makefile | 2 +-
- 2 files changed, 25 insertions(+), 1 deletion(-)
-
-diff --git a/src/libfaketime.c b/src/libfaketime.c
-index c59c122..cb37bcf 100644
---- a/src/libfaketime.c
-+++ b/src/libfaketime.c
-@@ -164,6 +164,13 @@ struct utimbuf {
- #include <sys/random.h>
- #endif
-
-+/* __timespec64 is needed for clock_gettime64 on 32-bit architectures */
-+struct __timespec64
-+{
-+ uint64_t tv_sec; /* Seconds */
-+ uint64_t tv_nsec; /* Nanoseconds */
-+};
-+
- /*
- * Per thread variable, which we turn on inside real_* calls to avoid
modifying
- * time multiple times of for the whole process to prevent faking time
-@@ -201,6 +208,7 @@ static time_t (*real_time) (time_t *);
- static int (*real_ftime) (struct timeb *);
- static int (*real_gettimeofday) (struct timeval *, void *);
- static int (*real_clock_gettime) (clockid_t clk_id, struct
timespec *tp);
-+static int (*real_clock_gettime64) (clockid_t clk_id, struct
__timespec64 *tp);
- #ifdef TIME_UTC
- static int (*real_timespec_get) (struct timespec *ts, int base);
- #endif
-@@ -2417,6 +2425,17 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp)
- return result;
- }
-
-+/* this is used by 32-bit architectures only */
-+int __clock_gettime64(clockid_t clk_id, struct __timespec64 *tp64)
-+{
-+ struct timespec tp;
-+ int result;
-+
-+ result = clock_gettime(clk_id, &tp);
-+ tp64->tv_sec = tp.tv_sec;
-+ tp64->tv_nsec = tp.tv_nsec;
-+ return result;
-+}
-
- #ifdef TIME_UTC
- #ifdef MACOS_DYLD_INTERPOSE
-@@ -2760,6 +2779,11 @@ static void ftpl_really_init(void)
- {
- real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
- }
-+ real_clock_gettime64 = dlsym(RTLD_NEXT, "clock_gettime64");
-+ if (NULL == real_clock_gettime64)
-+ {
-+ real_clock_gettime64 = dlsym(RTLD_NEXT, "__clock_gettime64");
-+ }
- #ifdef FAKE_TIMERS
- #if defined(__sun)
- real_timer_gettime_233 = dlsym(RTLD_NEXT, "timer_gettime");
-diff --git a/test/Makefile b/test/Makefile
-index 763ebc4..01cbd9f 100644
---- a/test/Makefile
-+++ b/test/Makefile
-@@ -1,6 +1,6 @@
- CC = gcc
-
--CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra
$(FAKETIME_COMPILE_CFLAGS)
-+CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra
$(FAKETIME_COMPILE_CFLAGS) -U_FILE_OFFSET_BITS -U_TIME_BITS
- LDFLAGS += -lrt -lpthread
-
- SRC = timetest.c
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/series
faketime-0.9.12/debian/patches/series
--- faketime-0.9.10+2024-06-05+gba9ed5b2/debian/patches/series 2025-01-27
08:14:40.000000000 -0500
+++ faketime-0.9.12/debian/patches/series 2026-03-28 13:53:05.000000000
-0400
@@ -1,10 +1,2 @@
-interpose-clock_gettime64.patch
-0002-Fix-interposition-of-clock_gettime64.patch
-0003-Interpose-__time64.patch
-0004-Interpose-gettimeofday64.patch
-0005-Re-disable-faking-utime-by-default.patch
-0006-Replace-data-race-with-use-of-pthread_once-ftpl_init.patch
-0007-Replace-data-race-with-use-of-pthread_once-ft_shm_in.patch
-0008-Call-ftpl_init-before-using-monotonic_conds_lock.patch
-0009-Don-t-use-_try_-locking-calls-for-monotonic_conds_lo.patch
-0010-485.patch
+fix-utimensat-futimens-fake-now-handling.patch
+add-regression-test-for-utimens-now.patch
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/debian/salsa-ci.yml
faketime-0.9.12/debian/salsa-ci.yml
--- faketime-0.9.10+2024-06-05+gba9ed5b2/debian/salsa-ci.yml 1969-12-31
19:00:00.000000000 -0500
+++ faketime-0.9.12/debian/salsa-ci.yml 2026-03-28 13:53:05.000000000 -0400
@@ -0,0 +1,3 @@
+---
+include:
+ -
https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/.github/workflows/make-test.yml
faketime-0.9.12/.github/workflows/make-test.yml
--- faketime-0.9.10+2024-06-05+gba9ed5b2/.github/workflows/make-test.yml
2024-06-05 13:52:44.000000000 -0400
+++ faketime-0.9.12/.github/workflows/make-test.yml 2025-06-09
08:31:15.000000000 -0400
@@ -12,7 +12,7 @@
build:
strategy:
matrix:
- os: [ubuntu-latest, macOS-latest]
+ os: [ubuntu-latest, ubuntu-22.04]
runs-on: ${{ matrix.os }}
steps:
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/Makefile faketime-0.9.12/Makefile
--- faketime-0.9.10+2024-06-05+gba9ed5b2/Makefile 2024-06-05
13:52:44.000000000 -0400
+++ faketime-0.9.12/Makefile 2025-06-09 08:31:15.000000000 -0400
@@ -33,23 +33,4 @@
$(MAKE) $(SELECTOR) -C src distclean
$(MAKE) $(SELECTOR) -C test distclean
-macarm64:
- $(MAKE) $(SELECTOR) -C src clean
- $(MAKE) $(SELECTOR) -C src distclean
- $(MAKE) $(SELECTOR) -C src all
-# $(MAKE) $(SELECTOR) -C test all
-# $(MAKE) $(SELECTOR) -C test distclean
- $(MAKE) $(SELECTOR) -C src install
- $(MAKE) $(SELECTOR) -C man install
- $(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/share/doc/faketime/"
- $(INSTALL) -m0644 README "${DESTDIR}${PREFIX}/share/doc/faketime/README"
- $(INSTALL) -m0644 NEWS "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
-
-macarm64full:
- $(MAKE) $(SELECTOR) -C src clean
- $(MAKE) $(SELECTOR) -C src distclean
- $(MAKE) $(SELECTOR) -C src all
- $(MAKE) $(SELECTOR) -C test all
-# $(MAKE) $(SELECTOR) -C test distclean
-
.PHONY: all test install uninstall clean distclean
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/man/faketime.1
faketime-0.9.12/man/faketime.1
--- faketime-0.9.10+2024-06-05+gba9ed5b2/man/faketime.1 2024-06-05
13:52:44.000000000 -0400
+++ faketime-0.9.12/man/faketime.1 2025-06-09 08:31:15.000000000 -0400
@@ -1,4 +1,4 @@
-.TH FAKETIME "1" "March 2022" "faketime 0.9.10" wolfcw
+.TH FAKETIME "1" "June 2025" "faketime 0.9.12" wolfcw
.SH NAME
faketime \- manipulate the system time for a given command
.SH SYNOPSIS
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/NEWS faketime-0.9.12/NEWS
--- faketime-0.9.10+2024-06-05+gba9ed5b2/NEWS 2024-06-05 13:52:44.000000000
-0400
+++ faketime-0.9.12/NEWS 2025-06-09 08:31:15.000000000 -0400
@@ -1,3 +1,20 @@
+List of changes for v0.9.12
+===========================
+
+Since 0.9.11:
+ - Improved macOS compatibility (@usertam)
+
+Since 0.9.10:
+ - Fixed various cross-platform compile-time issues
+ - Honor nanosecond parameters/fields in relevant system calls
+ - Limited improvements to enhance compatibility with other
+ LD_PRELOAD libraries
+ - Added selected more intercepted system calls
+ - Unset FAKETIME_SHARED automatically for child processes
+ when enabling FAKETIME_FLSHM=1
+ - Disable shared memory for child processes through
+ FAKETIME_DISABLE_SHM=1
+
Since 0.9.9:
- automatically try to decide about FORCE_MONOTONIC_FIX
at run-time when not set as a compile-time flag
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/README faketime-0.9.12/README
--- faketime-0.9.10+2024-06-05+gba9ed5b2/README 2024-06-05 13:52:44.000000000
-0400
+++ faketime-0.9.12/README 2025-06-09 08:31:15.000000000 -0400
@@ -1,5 +1,5 @@
-libfaketime, version 0.9.10 (March 2022)
-========================================
+libfaketime, version 0.9.12 (June 2025)
+=======================================
Content of this file:
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/README.OSX
faketime-0.9.12/README.OSX
--- faketime-0.9.10+2024-06-05+gba9ed5b2/README.OSX 2024-06-05
13:52:44.000000000 -0400
+++ faketime-0.9.12/README.OSX 2025-06-09 08:31:15.000000000 -0400
@@ -166,3 +166,50 @@
and always takes precedence over other user-controlled settings. It can
be re-set to 0 (zero) to work around potential incompatibilities or if
you do not want libfaketime applied to your software.
+
+5) Working with the new arm64e system binaries in Apple Silicon
+---------------------------------------------------------------
+
+Since Apple Silicon, Apple started shipping system binaries compiled against
+the `arm64e` ABI. This new ABI enforces Pointer Authentication Codes (PACs),
+and enforces assembly instructions to sign and check pointer signatures to
+prevent malicious control flow altering.
+
+ $ file /bin/date
+ /bin/date: Mach-O universal binary with 2 architectures: [x86_64:Mach-O
64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
+ /bin/date (for architecture x86_64): Mach-O 64-bit executable x86_64
+ /bin/date (for architecture arm64e): Mach-O 64-bit executable arm64e
+
+Most importantly, the new `arm64e` ABI is incompatible with the normal `arm64`
+ABI we are used to; this is done so that everything `arm64e` is PAC-enforced.
+
+As a result, this will happen when we try to hook naive `arm64` libfaketime on
+system binaries (and vice versa with `arm64e` libfaketime on `arm64` binaries):
+
+ $ DYLD_INSERT_LIBRARIES=libfaketime.1.dylib /bin/date
+ dyld[5788]: terminating because inserted dylib 'libfaketime.1.dylib' could
not be loaded:
+ tried: 'libfaketime.1.dylib' (mach-o file, but is an incompatible
architecture (have 'arm64', need 'arm64e'))
+
+Since PR #497, we now compile libfaketime with a fat library/binary setup, so
+that we support both ABIs at the same time:
+
+ $ file libfaketime.1.dylib
+ libfaketime.1.dylib: Mach-O universal binary with 2 architectures:
[arm64:Mach-O 64-bit dynamically linked shared library arm64] [arm64e:Mach-O
64-bit dynamically linked shared library arm64e]
+ libfaketime.1.dylib (for architecture arm64): Mach-O 64-bit dynamically
linked shared library arm64
+ libfaketime.1.dylib (for architecture arm64e): Mach-O 64-bit dynamically
linked shared library arm64e
+
+Unfortunately, Apple does not support running third-party `arm64e` code yet,
+since the ABI is still unstable. This means that you cannot use libfaketime
+on system `arm64e` binaries out of the box, at the time of writing.
+
+If you really need to, you may disable SIP in the recovery terminal:
+
+ (in recovery) # csrutil disable
+
+And enable the experimental ABI after boot:
+
+ (in regular boot) $ sudo nvram boot-args=-arm64e_preview_abi
+
+Then `arm64e` should work as-is. This use case is rather uncommon since most
+userspace binaries will remain `arm64` for the time being, until Apple really
+doubles down on `arm64e`. Regardless, we should be prepared for that.
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/src/faketime.c
faketime-0.9.12/src/faketime.c
--- faketime-0.9.10+2024-06-05+gba9ed5b2/src/faketime.c 2024-06-05
13:52:44.000000000 -0400
+++ faketime-0.9.12/src/faketime.c 2025-06-09 08:31:15.000000000 -0400
@@ -1,7 +1,7 @@
/*
* libfaketime wrapper command
*
- * This file is part of libfaketime, version 0.9.10
+ * This file is part of libfaketime, version 0.9.12
*
* libfaketime is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License v2 as published by the
@@ -48,7 +48,7 @@
#include "faketime_common.h"
-const char version[] = "0.9.10";
+const char version[] = "0.9.12";
#if (defined __APPLE__) || (defined __sun)
static const char *date_cmd = "gdate";
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/src/libfaketime.c
faketime-0.9.12/src/libfaketime.c
--- faketime-0.9.10+2024-06-05+gba9ed5b2/src/libfaketime.c 2024-06-05
13:52:44.000000000 -0400
+++ faketime-0.9.12/src/libfaketime.c 2025-06-09 08:31:15.000000000 -0400
@@ -1,5 +1,5 @@
/*
- * This file is part of libfaketime, version 0.9.10
+ * This file is part of libfaketime, version 0.9.12
*
* libfaketime is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License v2 as published by the
@@ -42,6 +42,7 @@
#endif
#include <time.h>
#ifdef MACOS_DYLD_INTERPOSE
+#include <pthread.h>
#include <sys/time.h>
#include <utime.h>
#endif
@@ -58,6 +59,9 @@
#ifdef __linux__
#include <stdarg.h>
#include <sys/syscall.h>
+#ifdef INTERCEPT_FUTEX
+#include <linux/futex.h>
+#endif
#else
#error INTERCEPT_SYSCALL should only be defined on GNU/Linux systems.
#endif
@@ -164,6 +168,20 @@
#include <sys/random.h>
#endif
+/* __timespec64 is needed for clock_gettime64 on 32-bit architectures */
+struct __timespec64
+{
+ uint64_t tv_sec; /* Seconds */
+ uint32_t tv_nsec; /* this is 32-bit, apparently! */
+};
+
+/* __timespec64 is needed for clock_gettime64 on 32-bit architectures */
+struct __timeval64
+{
+ uint64_t tv_sec; /* Seconds */
+ uint64_t tv_usec; /* this is 64-bit, apparently! */
+};
+
/*
* Per thread variable, which we turn on inside real_* calls to avoid modifying
* time multiple times of for the whole process to prevent faking time
@@ -190,10 +208,12 @@
static int (*real_fxstat) (int, int, struct stat *);
static int (*real_fxstatat) (int, int, const char *, struct
stat *, int);
static int (*real_lxstat) (int, const char *, struct stat *);
+#if !defined(__APPLE__) || !__DARWIN_ONLY_64_BIT_INO_T
static int (*real_xstat64) (int, const char *, struct stat64
*);
static int (*real_fxstat64) (int, int , struct stat64 *);
static int (*real_fxstatat64) (int, int , const char *, struct
stat64 *, int);
static int (*real_lxstat64) (int, const char *, struct stat64
*);
+#endif
#ifdef STATX_TYPE
static int (*real_statx) (int dirfd, const char *pathname,
int flags, unsigned int mask, struct statx *statxbuf);
#endif
@@ -201,6 +221,7 @@
static int (*real_ftime) (struct timeb *);
static int (*real_gettimeofday) (struct timeval *, void *);
static int (*real_clock_gettime) (clockid_t clk_id, struct timespec
*tp);
+static int (*real_clock_gettime64) (clockid_t clk_id, struct
__timespec64 *tp);
#ifdef TIME_UTC
static int (*real_timespec_get) (struct timespec *ts, int base);
#endif
@@ -217,7 +238,7 @@
static pthread_rwlock_t monotonic_conds_lock;
#endif
-#ifndef __APPLEOSX__
+#ifndef __APPLE__
#ifdef FAKE_TIMERS
static int (*real_timer_settime_22) (int timerid, int flags, const
struct itimerspec *new_value,
struct itimerspec * old_value);
@@ -263,7 +284,7 @@
static int (*real_sem_timedwait) (sem_t*, const struct timespec*);
static int (*real_sem_clockwait) (sem_t *sem, clockid_t clockid,
const struct timespec *abstime);
#endif
-#ifdef __APPLEOSX__
+#ifdef __APPLE__
static int (*real_clock_get_time) (clock_serv_t clock_serv,
mach_timespec_t *cur_timeclockid_t);
static int apple_clock_gettime (clockid_t clk_id, struct timespec
*tp);
static clock_serv_t clock_serv_real;
@@ -304,7 +325,7 @@
#define CHECK_MISSING_REAL(name) \
check_missing_real(#name, (NULL == real_##name))
-static int initialized = 0;
+static pthread_once_t initialized_once_control = PTHREAD_ONCE_INIT;
/* prototypes */
static int fake_gettimeofday(struct timeval *tv);
@@ -521,16 +542,20 @@
}
}
+static pthread_once_t ft_shm_initialized_once_control = PTHREAD_ONCE_INIT;
+
+static void ft_shm_really_init (void);
static void ft_shm_init (void)
{
+ pthread_once(&ft_shm_initialized_once_control, ft_shm_really_init);
+}
+
+static void ft_shm_really_init (void)
+{
int ticks_shm_fd;
char sem_name[256], shm_name[256], *ft_shared_env =
getenv("FAKETIME_SHARED");
sem_t *shared_semR = NULL;
static int nt=1;
- static int ft_shm_initialized = 0;
-
- /* do all of this once only */
- if (ft_shm_initialized > 0) return;
/* create semaphore and shared memory locally unless it has been passed
along */
if (ft_shared_env == NULL)
@@ -610,8 +635,6 @@
{ /* force the deletion of the shm sync env variable */
unsetenv("FAKETIME_SHARED");
}
-
- ft_shm_initialized = 1;
}
static void ft_cleanup (void)
@@ -673,7 +696,7 @@
/* Get system time from system for all clocks */
static void system_time_from_system (struct system_time_s * systime)
{
-#ifdef __APPLEOSX__
+#ifdef __APPLE__
/* from
https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
*/
clock_serv_t cclock;
mach_timespec_t mts;
@@ -876,7 +899,7 @@
* =======================================================================
*/
#ifdef FAKE_UTIME
-static int fake_utime_disabled = 0;
+static int fake_utime_disabled = 1;
#endif
@@ -962,6 +985,7 @@
#endif
}
+#ifndef __APPLE__
static inline void fake_stat64buf (struct stat64 *buf) {
#ifndef st_atime
lock_for_stat();
@@ -971,18 +995,13 @@
unlock_for_stat();
#else
lock_for_stat();
-#ifndef __APPLE__
fake_clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
fake_clock_gettime(CLOCK_REALTIME, &buf->st_atim);
fake_clock_gettime(CLOCK_REALTIME, &buf->st_mtim);
-#else
- fake_clock_gettime(CLOCK_REALTIME, &buf->st_ctimespec);
- fake_clock_gettime(CLOCK_REALTIME, &buf->st_atimespec);
- fake_clock_gettime(CLOCK_REALTIME, &buf->st_mtimespec);
-#endif
unlock_for_stat();
#endif
}
+#endif
/* macOS dyld interposing uses the function's real name instead of real_name */
#ifdef MACOS_DYLD_INTERPOSE
@@ -1092,25 +1111,19 @@
{
STAT_HANDLER(lxstat, buf, ver, path, buf);
}
-#endif
-#ifndef __APPLE__
/* Contributed by Philipp Hachtmann in version 0.6 */
int __xstat64 (int ver, const char *path, struct stat64 *buf)
{
STAT64_HANDLER(xstat64, buf, ver, path, buf);
}
-#endif
-#ifndef __APPLE__
/* Contributed by Philipp Hachtmann in version 0.6 */
int __fxstat64 (int ver, int fildes, struct stat64 *buf)
{
STAT64_HANDLER(fxstat64, buf, ver, fildes, buf);
}
-#endif
-#ifndef __APPLE__
/* Added in v0.8 as suggested by Daniel Kahn Gillmor */
#ifndef NO_ATFILE
int __fxstatat64 (int ver, int fildes, const char *filename, struct stat64
*buf, int flag)
@@ -1118,16 +1131,14 @@
STAT64_HANDLER(fxstatat64, buf, ver, fildes, filename, buf, flag);
}
#endif
-#endif
-#ifndef __APPLE__
/* Contributed by Philipp Hachtmann in version 0.6 */
int __lxstat64 (int ver, const char *path, struct stat64 *buf)
{
STAT64_HANDLER(lxstat64, buf, ver, path, buf);
}
-#endif
-#endif
+#endif /* ifndef __APPLE__ */
+#endif /* ifdef FAKE_STAT */
#ifdef STATX_TYPE
static inline void fake_statx_timestamp(struct statx_timestamp* p)
@@ -2346,44 +2357,12 @@
#endif
{
int result;
- static int recursion_depth = 0;
- if (!initialized)
- {
- recursion_depth++;
-#ifdef FAIL_PRE_INIT_CALLS
- fprintf(stderr, "libfaketime: clock_gettime() was called before
initialization.\n");
- fprintf(stderr, "libfaketime: Returning -1 on clock_gettime().\n");
- if (tp != NULL)
- {
- tp->tv_sec = 0;
- tp->tv_nsec = 0;
- }
- return -1;
-#else
- if (recursion_depth == 2)
- {
- fprintf(stderr, "libfaketime: Unexpected recursive calls to
clock_gettime() without proper initialization. Trying alternative.\n");
- DONT_FAKE_TIME(ftpl_init()) ;
- }
- else if (recursion_depth == 3)
- {
- fprintf(stderr, "libfaketime: Cannot recover from unexpected recursive
calls to clock_gettime().\n");
- fprintf(stderr, "libfaketime: Please check whether any other libraries
are in use that clash with libfaketime.\n");
- fprintf(stderr, "libfaketime: Returning -1 on clock_gettime() to break
recursion now... if that does not work, please check other libraries' error
handling.\n");
- if (tp != NULL)
- {
- tp->tv_sec = 0;
- tp->tv_nsec = 0;
- }
- return -1;
- }
- else {
- ftpl_init();
- }
-#endif
- recursion_depth--;
- }
+ ftpl_init();
+ // If ftpl_init ends up recursing, pthread_once will deadlock.
+ // (Previously we attempted to detect this situation, and bomb out,
+ // but the approach taken wasn't thread-safe and broke in practice.)
+
/* sanity check */
if (tp == NULL)
{
@@ -2417,6 +2396,50 @@
return result;
}
+/* this is used by 32-bit architectures only */
+int __clock_gettime64(clockid_t clk_id, struct __timespec64 *tp64)
+{
+ struct timespec tp;
+ int result;
+
+ result = clock_gettime(clk_id, &tp);
+ tp64->tv_sec = tp.tv_sec;
+ tp64->tv_nsec = tp.tv_nsec;
+ return result;
+}
+
+/* this is used by 32-bit architectures only */
+int __gettimeofday64(struct __timeval64 *tv64, void *tz)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, tz);
+ tv64->tv_sec = tv.tv_sec;
+ tv64->tv_usec = tv.tv_usec;
+ return result;
+}
+
+/* this is used by 32-bit architectures only */
+uint64_t __time64(uint64_t *write_out)
+{
+ struct timespec tp;
+ uint64_t output;
+ int error;
+
+ error = clock_gettime(CLOCK_REALTIME, &tp);
+ if (error == -1)
+ {
+ return (uint64_t)error;
+ }
+ output = tp.tv_sec;
+
+ if (write_out)
+ {
+ *write_out = output;
+ }
+ return output;
+}
#ifdef TIME_UTC
#ifdef MACOS_DYLD_INTERPOSE
@@ -2656,10 +2679,12 @@
real_fxstat = dlsym(RTLD_NEXT, "__fxstat");
real_fxstatat = dlsym(RTLD_NEXT, "__fxstatat");
real_lxstat = dlsym(RTLD_NEXT, "__lxstat");
+#if !defined(__APPLE__) || !__DARWIN_ONLY_64_BIT_INO_T
real_xstat64 = dlsym(RTLD_NEXT,"__xstat64");
real_fxstat64 = dlsym(RTLD_NEXT, "__fxstat64");
real_fxstatat64 = dlsym(RTLD_NEXT, "__fxstatat64");
real_lxstat64 = dlsym(RTLD_NEXT, "__lxstat64");
+#endif
#ifdef STATX_TYPE
real_statx = dlsym(RTLD_NEXT, "statx");
#endif
@@ -2751,7 +2776,7 @@
exit(-1);
}
#endif
-#ifdef __APPLEOSX__
+#ifdef __APPLE__
real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time");
real_clock_gettime = apple_clock_gettime;
#else
@@ -2760,6 +2785,11 @@
{
real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
}
+ real_clock_gettime64 = dlsym(RTLD_NEXT, "clock_gettime64");
+ if (NULL == real_clock_gettime64)
+ {
+ real_clock_gettime64 = dlsym(RTLD_NEXT, "__clock_gettime64");
+ }
#ifdef FAKE_TIMERS
#if defined(__sun)
real_timer_gettime_233 = dlsym(RTLD_NEXT, "timer_gettime");
@@ -2795,7 +2825,6 @@
#undef dlsym
#undef dlvsym
- initialized = 1;
#ifdef FAKE_STATELESS
if (0) ft_shm_init();
@@ -3046,10 +3075,7 @@
}
inline static void ftpl_init(void) {
- if (!initialized)
- {
- ftpl_really_init();
- }
+ pthread_once(&initialized_once_control, ftpl_really_init);
}
void *ft_dlvsym(void *handle, const char *symbol, const char *version,
@@ -3511,7 +3537,7 @@
* =======================================================================
*/
-#ifdef __APPLEOSX__
+#ifdef __APPLE__
/*
* clock_gettime implementation for __APPLE__
* @note It always behave like being called with CLOCK_REALTIME.
@@ -3724,9 +3750,9 @@
struct pthread_cond_monotonic *e = (struct
pthread_cond_monotonic*)malloc(sizeof(struct pthread_cond_monotonic));
e->ptr = cond;
- if (pthread_rwlock_trywrlock(&monotonic_conds_lock) != 0) {
- sched_yield();
- return EAGAIN;
+ if (pthread_rwlock_wrlock(&monotonic_conds_lock) != 0) {
+ fprintf(stderr,"can't acquire write monotonic_conds_lock\n");
+ exit(-1);
}
HASH_ADD_PTR(monotonic_conds, ptr, e);
pthread_rwlock_unlock(&monotonic_conds_lock);
@@ -3739,9 +3765,11 @@
{
struct pthread_cond_monotonic* e;
- if (pthread_rwlock_trywrlock(&monotonic_conds_lock) != 0) {
- sched_yield();
- return EBUSY;
+ ftpl_init();
+
+ if (pthread_rwlock_wrlock(&monotonic_conds_lock) != 0) {
+ fprintf(stderr,"can't acquire write monotonic_conds_lock\n");
+ exit(-1);
}
HASH_FIND_PTR(monotonic_conds, &cond, e);
if (e) {
@@ -3821,11 +3849,13 @@
clockid_t clk_id;
int result = 0;
+ ftpl_init();
+
if (abstime != NULL)
{
- if (pthread_rwlock_tryrdlock(&monotonic_conds_lock) != 0) {
- sched_yield();
- return EAGAIN;
+ if (pthread_rwlock_rdlock(&monotonic_conds_lock) != 0) {
+ fprintf(stderr,"can't acquire read monotonic_conds_lock\n");
+ exit(-1);
}
HASH_FIND_PTR(monotonic_conds, &cond, e);
pthread_rwlock_unlock(&monotonic_conds_lock);
@@ -4151,6 +4181,90 @@
#endif
#ifdef INTERCEPT_SYSCALL
+#ifdef INTERCEPT_FUTEX
+long handle_futex_syscall(long number, uint32_t* uaddr, int futex_op, uint32_t
val, struct timespec* timeout, uint32_t* uaddr2, uint32_t val3) {
+ if (timeout == NULL) {
+ // not timeout related, just call the real syscall
+ goto futex_fallback;
+ }
+
+ // if ((futex_op & FUTEX_CMD_MASK) == FUTEX_WAIT_BITSET) {
+ if (1) {
+ clockid_t clk_id = CLOCK_MONOTONIC;
+ if (futex_op & FUTEX_CLOCK_REALTIME)
+ clk_id = CLOCK_REALTIME;
+
+ struct timespec real_tp, fake_tp;
+
+ DONT_FAKE_TIME((*real_clock_gettime)(clk_id, &real_tp));
+ fake_tp = real_tp;
+ if (fake_clock_gettime(clk_id, &fake_tp) == -1) {
+ goto futex_fallback;
+ }
+ // Create a corrected timeout by adjusting with the difference between
+ // real and fake timestamps
+ struct timespec adjusted_timeout, time_diff;
+ timespecsub(&fake_tp, &real_tp, &time_diff);
+ timespecsub(timeout, &time_diff, &adjusted_timeout);
+ // fprintf(stdout, "libfaketime: adjusted timeout: %ld.%09ld\n",
adjusted_timeout.tv_sec, adjusted_timeout.tv_nsec);
+ long result;
+ result = real_syscall(number, uaddr, futex_op, val, &adjusted_timeout,
uaddr2, val3);
+ if (result != 0) {
+ return result;
+ }
+
+ // Check if the futex timeout has already passed according to fake time
+ struct timespec now_fake;
+ if (fake_clock_gettime(clk_id, &now_fake) != 0) {
+ return result;
+ }
+
+ // If the timeout is already passed in fake time, return 0.
+ while (!timespeccmp(&now_fake, timeout, >=)) {
+ // Calculate how much real time we need to wait
+ struct timespec real_now, fake_now, wait_time;
+ DONT_FAKE_TIME((*real_clock_gettime)(clk_id, &real_now));
+ fake_clock_gettime(clk_id, &fake_now);
+
+ // Calculate how much fake time is left until the timeout
+ struct timespec fake_time_left;
+ timespecsub(timeout, &fake_now, &fake_time_left);
+
+ // Scale the fake time left by the user rate if set
+ if (user_rate_set && !dont_fake) {
+ timespecmul(&fake_time_left, 1.0 / user_rate, &wait_time);
+ } else {
+ wait_time = fake_time_left;
+ }
+
+ // Calculate the real timeout by adding the wait time to the current
real time
+ struct timespec real_timeout;
+ timespecadd(&real_now, &wait_time, &real_timeout);
+
+ // fprintf(stdout, "libfaketime: recalculated real timeout: %ld.%09ld\n",
+ // real_timeout.tv_sec, real_timeout.tv_nsec);
+
+ // Call the real syscall with the recalculated timeout
+ result = real_syscall(number, uaddr, futex_op, val, &real_timeout,
uaddr2, val3);
+ if (result != 0) {
+ return result;
+ }
+
+ // Check if the futex timeout has already passed according to fake time
+ if (fake_clock_gettime(clk_id, &now_fake) != 0) {
+ return result;
+ }
+ }
+ return 0;
+ } else {
+ return real_syscall(number, uaddr, futex_op, val, timeout, uaddr2, val3);
+ }
+
+ futex_fallback:
+ return real_syscall(number, uaddr, futex_op, val, timeout, uaddr2, val3);
+}
+#endif
+
/* see https://github.com/wolfcw/libfaketime/issues/301 */
long syscall(long number, ...) {
va_list ap;
@@ -4177,6 +4291,27 @@
return clock_gettime(clk_id, tp);
}
+#ifdef INTERCEPT_FUTEX
+ if (number == __NR_futex) {
+ uint32_t *uaddr;
+ int futex_op;
+ uint32_t val;
+ struct timespec *timeout; /* or: uint32_t val2 */
+ uint32_t* uaddr2;
+ uint32_t val3;
+
+ uaddr = va_arg(ap, uint32_t*);
+ futex_op = va_arg(ap, int);
+ val = va_arg(ap, uint32_t);
+ timeout = va_arg(ap, struct timespec*);
+ uaddr2 = va_arg(ap, uint32_t*);
+ val3 = va_arg(ap, uint32_t);
+ va_end(ap);
+
+ return handle_futex_syscall(number, uaddr, futex_op, val, timeout, uaddr2,
val3);
+ }
+#endif
+
variadic_promotion_t a[syscall_max_args];
for (int i = 0; i < syscall_max_args; i++)
a[i] = va_arg(ap, variadic_promotion_t);
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/src/Makefile.OSX
faketime-0.9.12/src/Makefile.OSX
--- faketime-0.9.10+2024-06-05+gba9ed5b2/src/Makefile.OSX 2024-06-05
13:52:44.000000000 -0400
+++ faketime-0.9.12/src/Makefile.OSX 2025-06-09 08:31:15.000000000 -0400
@@ -56,21 +56,24 @@
PREFIX ?= /usr/local
CFLAGS += -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -DPREFIX='"'${PREFIX}'"'
$(FAKETIME_COMPILE_CFLAGS) -DMACOS_DYLD_INTERPOSE -DFAKE_SETTIME
-LIB_LDFLAGS += -dynamiclib -current_version 0.9.10 -compatibility_version 0.7
+LIB_LDFLAGS += -dynamiclib -current_version 0.9.12 -compatibility_version 0.7
-# ARM64 MacOS (M1/M2/M3/Apple Silicon/etc) processors require a target set as
their current version, or they
-# will receive the following error:
-# dyld[6675]: terminating because inserted dylib
'/usr/local/lib/faketime/libfaketime.1.dylib' could not be loaded: tried:
'/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o file, but is an
incompatible architecture (have 'arm64', need 'arm64e')),
'/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/faketime/libfaketime.1.dylib'
(no such file), '/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o file,
but is an incompatible architecture (have 'arm64', need 'arm64e'))
-# dyld[6675]: tried: '/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o
file, but is an incompatible architecture (have 'arm64', need 'arm64e')),
'/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/faketime/libfaketime.1.dylib'
(no such file), '/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o file,
but is an incompatible architecture (have 'arm64', need 'arm64e'))
-# Outputs `arm64` on ARM64
-OS := $(shell uname -m)
-# Outputs a number, eg 14.4 for MacOS Sonoma 14.4
-MACOS_PRODUCT_VERSION := $(shell sw_vers --productVersion | cut -d. -f1,2)
-
-# Check if arm64 is in OS, if so, add the target
-ifeq ($(OS),arm64)
- CFLAGS += -target arm64e-apple-macos$(MACOS_PRODUCT_VERSION)
- LIB_LDFLAGS += -target arm64e-apple-macos$(MACOS_PRODUCT_VERSION)
+# From macOS 13 onwards, system binaries are compiled against the new arm64e
ABI on Apple Silicon.
+# These arm64e binaries enforce Pointer Authentication Code (PAC), and will
refuse to run with
+# "unprotected" arm64 libraries. Meanwhile, older platforms might not
recognize the new arm64e ABI.
+
+# Therefore, we now compile for two ABIs at the same time, producing a fat
library of arm64e and arm64,
+# so in the end the OS gets to pick which architecture it wants at runtime.
+
+# In addition, we need to enable signing and authentication of indirect calls
(-fptrauth-calls);
+# otherwise in ftpl_init, pthread_once will indirectly call ftpl_really_init,
which then fail PAC.
+# Ideally this should be a compiler default for the arm64e ABI, but apparently
not.
+
+ARCH := $(shell uname -m)
+
+ifeq ($(ARCH),arm64)
+ CFLAGS += -arch arm64e -arch arm64
+ CFLAGS += -fptrauth-calls -fptrauth-returns
endif
SONAME = 1
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/test/libmallocintercept.c
faketime-0.9.12/test/libmallocintercept.c
--- faketime-0.9.10+2024-06-05+gba9ed5b2/test/libmallocintercept.c
2024-06-05 13:52:44.000000000 -0400
+++ faketime-0.9.12/test/libmallocintercept.c 2025-06-09 08:31:15.000000000
-0400
@@ -24,7 +24,9 @@
#include <unistd.h>
static void print_msg(const char *msg) {
- write(0, msg, strlen(msg));
+ size_t out;
+ out = write(0, msg, strlen(msg));
+ (void) out; /* unused */
}
static void* actual_malloc(size_t size) {
diff -Nru faketime-0.9.10+2024-06-05+gba9ed5b2/test/Makefile
faketime-0.9.12/test/Makefile
--- faketime-0.9.10+2024-06-05+gba9ed5b2/test/Makefile 2024-06-05
13:52:44.000000000 -0400
+++ faketime-0.9.12/test/Makefile 2025-06-09 08:31:15.000000000 -0400
@@ -1,6 +1,6 @@
CC = gcc
-CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra
$(FAKETIME_COMPILE_CFLAGS)
+CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra
$(FAKETIME_COMPILE_CFLAGS) -U_FILE_OFFSET_BITS -U_TIME_BITS
LDFLAGS += -lrt -lpthread
SRC = timetest.c
--- End Message ---