From 57917c4d5a4c64f3db6424c266c33e7a5314b092 Mon Sep 17 00:00:00 2001 From: Wolfgang Hommel Date: Tue, 20 Aug 2019 19:43:15 +0200 Subject: Added follow-file-timestamp mode via FAKETIME='%' and FAKETIME_FOLLOW_FILE (#156) --- README | 40 ++++++++++++++++++++++++++++++++++++++++ src/libfaketime.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/README b/README index 664f1a4..8d52e90 100644 --- a/README +++ b/README @@ -205,6 +205,22 @@ specified absolute time. The 'start at' format allows a 'relative' clock operation as described below in section 4d), but using a 'start at' time instead of an offset time. +If the started process itself starts other (child) processes, they by default +will start with the specified start-at-date again. If this is not what you need, +set the environment variable FAKETIME_DONT_RESET=1. Try these examples to see +the difference: + +LD_PRELOAD=src/libfaketime.so.1 FAKETIME="@2000-01-01 11:12:13" \ + FAKETIME_DONT_RESET=1 \ + /bin/bash -c 'while [ $SECONDS -lt 5 ]; do date; sleep 1; done' + +LD_PRELOAD=src/libfaketime.so.1 FAKETIME="@2000-01-01 11:12:13" \ + /bin/bash -c 'while [ $SECONDS -lt 5 ]; do date; sleep 1; done' + +In the second example, the "date" command will always print the same time, +while in the first example, with FAKETIME_DONT_RESET set, time will increment +even though all the "date" commands are new processes. + 4d) Using offsets for relative dates ------------------------------------ @@ -336,6 +352,30 @@ with FAKETIME_NO_CACHE=1. Remember that disabling the cache may negatively influence the performance. +Setting FAKETIME by means of a file timestamp +--------------------------------------------- + +Based on a proposal by Hitoshi Harada (umitanuki), the "start at" time can now be +set through any file in the file system by setting the FAKETIME environment variable +to "%" (a percent sign) and FAKETIME_FOLLOW_FILE to the name of the file whose +modification timestamp shall be used as source for the "start at" time. + +Usage example: + +# create any file with December 24th, 2009, 12:34:56 as timestamp +touch -t 0912241234.56 /tmp/my-demo-file.tmp + +# run a bash shell with an endless loop printing the current time +LD_PRELOAD=/path/to/libfaketime.so.1 \ + FAKETIME='%' FAKETIME_FOLLOW_FILE=/tmp/my-demo-file.tmp \ + FAKETIME_DONT_RESET=1 \ + bash -c 'while true ; do date ; sleep 1 ; done' + +# now, while the above is running, change the file's timestamp +# (in a different terminal window or whatever) +touch -t 2002290123.45 /tmp/my-demo-file.tmp + + 4f) Faking the date and time system-wide ---------------------------------------- diff --git a/src/libfaketime.c b/src/libfaketime.c index 59ffd7f..f5a4ea2 100644 --- a/src/libfaketime.c +++ b/src/libfaketime.c @@ -1794,6 +1794,34 @@ static void parse_ft_string(const char *user_faked_time) goto parse_modifiers; break; + case '%': /* follow file timestamp as suggested by Hitoshi Harada (umitanuki) */ + ft_mode = FT_START_AT; + struct stat master_file_stats; + int ret; + if (NULL == getenv("FAKETIME_FOLLOW_FILE")) + { + fprintf(stderr, "libfaketime: %% operator in FAKETIME setting requires environment variable FAKETIME_FOLLOW_FILE set.\n"); + exit(1); + } + else + { + DONT_FAKE_TIME(ret = stat(getenv("FAKETIME_FOLLOW_FILE"), &master_file_stats)); + if (ret == -1) + { + fprintf(stderr, "libfaketime: Cannot get timestamp of file %s as requested by %% operator.\n", getenv("FAKETIME_FOLLOW_FILE")); + exit(1); + } + else + { + user_faked_time_timespec.tv_sec = master_file_stats.st_mtime; + user_faked_time_timespec.tv_nsec = 0; + } + } + if (NULL == getenv("FAKETIME_DONT_RESET")) + system_time_from_system(&ftpl_starttime); + goto parse_modifiers; + break; + case 'i': case 'x': /* Only modifiers are passed, don't fall back to strptime */ parse_modifiers: -- cgit v1.2.1