summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS9
-rw-r--r--README73
-rw-r--r--src/Makefile5
-rw-r--r--src/Makefile.MacOS6
-rw-r--r--src/faketime.c58
5 files changed, 141 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index a6ede55..e849385 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+Since 0.8.2:
+ - Added support for "limited faking".
+ You can optionally specify when libfaketime starts to fake the
+ returned timestamps and when it shall stop doing so. For example,
+ a program can be started regularly, and after 5 minutes run-time
+ it will be sent two years into the future. Those limiting
+ start and stop times can be specified in seconds or as the
+ number of any time-related function calls within the program.
+
Since 0.8.1:
- Added a MacOS port.
Thanks to Derrick Brashear!
diff --git a/README b/README
index 36c57be..0b32cf6 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
- ==================================================
- FakeTime Preload Library, version 0.8.1 (May 2011)
- ==================================================
+ =====================================================
+ FakeTime Preload Library, version 0.9 (Fabruary 2011)
+ =====================================================
Content of this file:
@@ -17,6 +17,7 @@ Content of this file:
e) Advanced features and caveats
f) Faking the date and time system-wide
g) Using the "faketime" wrapper script
+ h) "Limiting" libfaketime
5. License
6. Contact
@@ -318,6 +319,72 @@ faketime '2008-12-24 08:15:42' /bin/date
Thanks to Daniel Kahn Gillmor for providing these suggestions!
+4h) "Limiting" libfaketime
+--------------------------
+
+Starting with version 0.9, libfaketime can be configured to not be continuously
+active, but only during a certain time interval.
+
+For example, you might want to start a program with the real current time, but
+after 5 minutes of usage, you might want it to see a faked time, e.g., a year
+in the future.
+
+Dynamic changes to the faked time are alternatively possible by
+
+- changing the FAKETIME environment variable at run-time; this is the preferred
+ way if you use libfaketime for debugging and testing as a programmer, as it
+ gives you the most direct control of libfaketime without any performance
+ penalities.
+
+- not using the FAKETIME environment variable, but specifying the fake time in a
+ file (such as ~/.faketimerc). You can change the content of this file at
+ run-time. This works best with caching disabled (see Makefile), but comes at a
+ performance cost because this file has to be read and evaluated each time.
+
+The feature described here works based on two pairs of environment variables,
+
+ FAKETIME_START_AFTER_SECONDS and FAKETIME_STOP_AFTER_SECONDS, and
+ FAKETIME_START_AFTER_NUMCALLS and FAKETIME_STOP_AFTER_NUMCALLS
+
+The default value for each of these environment variables is -1, which means
+"ignore this value".
+
+If you want libfaketime to be only active during the run-time minutes 2 to 5
+of your application, you would set
+
+ FAKETIME_START_AFTER_SECONDS=60
+ FAKETIME_STOP_AFTER_SECONDS=300
+
+This means that your application will work with the real time from start (second
+0) up to second 60. It will then see a faked time from run-time seconds 60 to
+300 (minutes 2, 3, 4, and 5). After run-time second 600, it will again see the
+real (not-faked) time.
+
+This approach is not as flexible as changing the FAKETIME environment variable
+during runtime, but may be easier to use, works on a per-program (and not a
+per-user or system-wide) scope, and has only a minor performance overhead.
+
+Using the other pair of environment variables, you can limit the activity time
+of libfaketime not based on wall-clock seconds, but on the number of
+time-related function calls the started program performs. This alternative is
+probably only suitable for programmers who either know the code of the program
+in order to determine useful start/stop values or want to perform fuzzing
+tests.
+
+Both pairs of environment variables can be combined to further restrict
+libfaketime activity, although this is only useful in very few scenarios.
+
+Limiting libfaketime activity in this way is not recommended in general. Many
+programs will break when they are subject to sudden changes in time, especially
+if they are started using the current (real) time and are then sent back into
+the past after, e.g., 5 minutes. For example, they may appear to be frozen or
+stuck because they are waiting until a certain point in time that, however, is
+never reached due to the delayed libfaketime activity. Avoid using this
+functionality unless you are sure you really need it and know what you are
+doing.
+
+
+
5. License
----------
diff --git a/src/Makefile b/src/Makefile
index c48832e..32ab293 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -30,6 +30,9 @@
# frequently. Disabling the cache may negatively influence the
# performance.
#
+# LIMITEDFAKING
+# - Support environment variables that limit time faking to certain
+# time intervals or number of function calls.
#
# * Compilation addition: second libMT target added for building the pthread-
# enabled library as a separate library
@@ -45,7 +48,7 @@ INSTALL = install
PREFIX = /usr/local
-CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -DFAKE_INTERNAL_CALLS -fPIC -DPOSIX_REALTIME
+CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -DFAKE_INTERNAL_CALLS -fPIC -DPOSIX_REALTIME -DLIMITEDFAKING
LDFLAGS += -shared -ldl -lm -lpthread
SRC = faketime.c
diff --git a/src/Makefile.MacOS b/src/Makefile.MacOS
index 3c3a8b5..f15ea74 100644
--- a/src/Makefile.MacOS
+++ b/src/Makefile.MacOS
@@ -30,6 +30,10 @@
# frequently. Disabling the cache may negatively influence the
# performance.
#
+# LIMITEDFAKING
+# - Support environment variables that limit time faking to certain
+# time intervals or number of function calls.
+#
#
# * Compilation addition: second libMT target added for building the pthread-
# enabled library as a separate library
@@ -51,7 +55,7 @@ PREFIX = /usr/local
# 10.5
#CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS -arch i386 -arch ppc
# 10.6
-CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS -arch i386 -arch x86_64
+CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS -arch i386 -arch x86_64 -DLIMITEDFAKING
SRC = faketime.c
diff --git a/src/faketime.c b/src/faketime.c
index 3b6e69a..1745380 100644
--- a/src/faketime.c
+++ b/src/faketime.c
@@ -457,6 +457,7 @@ static time_t _ftpl_time(time_t *time_tptr) {
/* initialize our result with the real current time */
result = (*real_time)(time_tptr);
#endif
+
return result;
}
@@ -628,6 +629,17 @@ time_t fake_time(time_t *time_tptr) {
static time_t last_data_fetch = 0; /* not fetched previously at first call */
static int cache_expired = 1; /* considered expired at first call */
static int cache_duration = 10; /* cache fake time input for 10 seconds */
+
+#ifdef LIMITEDFAKING
+ static long callcounter = 0;
+ static int limited_initialized = 0;
+ char envvarbuf[32];
+ static long FAKETIME_START_AFTER_SECONDS = -1;
+ static long FAKETIME_STOP_AFTER_SECONDS = -1;
+ static long FAKETIME_START_AFTER_NUMCALLS = -1;
+ static long FAKETIME_STOP_AFTER_NUMCALLS = -1;
+#endif
+
/*
* This no longer appears to be necessary in Mac OS X 10.7 Lion
*/
@@ -644,13 +656,49 @@ static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
/* Sanity check by Karl Chan since v0.8 */
if (time_tptr == NULL) return -1;
+#ifdef LIMITEDFAKING
+ /* Check whether we actually should be faking the returned timestamp. */
+
+ if (ftpl_starttime > 0) {
+ if (limited_initialized == 0) {
+ if (getenv("FAKETIME_START_AFTER_SECONDS") != NULL) {
+ (void) strncpy(envvarbuf, getenv("FAKETIME_START_AFTER_SECONDS"), 30);
+ FAKETIME_START_AFTER_SECONDS = atol(envvarbuf);
+ }
+ if (getenv("FAKETIME_STOP_AFTER_SECONDS") != NULL) {
+ (void) strncpy(envvarbuf, getenv("FAKETIME_STOP_AFTER_SECONDS"), 30);
+ FAKETIME_STOP_AFTER_SECONDS = atol(envvarbuf);
+ }
+ if (getenv("FAKETIME_START_AFTER_NUMCALLS") != NULL) {
+ (void) strncpy(envvarbuf, getenv("FAKETIME_START_AFTER_NUMCALLS"), 30);
+ FAKETIME_START_AFTER_NUMCALLS = atol(envvarbuf);
+ }
+ if (getenv("FAKETIME_STOP_AFTER_NUMCALLS") != NULL) {
+ (void) strncpy(envvarbuf, getenv("FAKETIME_STOP_AFTER_NUMCALLS"), 30);
+ FAKETIME_STOP_AFTER_NUMCALLS = atol(envvarbuf);
+ }
+ limited_initialized = 1;
+ }
+ if ((callcounter + 1) >= callcounter) callcounter++;
+
+ /* For debugging, output #seconds and #calls */
+ /* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu\n", (*time_tptr - ftpl_starttime), callcounter); */
+ if ((FAKETIME_START_AFTER_SECONDS != -1) && ((*time_tptr - ftpl_starttime) < FAKETIME_START_AFTER_SECONDS)) return *time_tptr;
+ if ((FAKETIME_STOP_AFTER_SECONDS != -1) && ((*time_tptr - ftpl_starttime) >= FAKETIME_STOP_AFTER_SECONDS)) return *time_tptr;
+ if ((FAKETIME_START_AFTER_NUMCALLS != -1) && (callcounter < FAKETIME_START_AFTER_NUMCALLS)) return *time_tptr;
+ if ((FAKETIME_STOP_AFTER_NUMCALLS != -1) && (callcounter >= FAKETIME_STOP_AFTER_NUMCALLS)) return *time_tptr;
+ /* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu continues\n", (*time_tptr - ftpl_starttime), callcounter); */
+
+ }
+#endif
+
if (last_data_fetch > 0) {
- if ((*time_tptr - last_data_fetch) > cache_duration) {
- cache_expired = 1;
- }
+ if ((*time_tptr - last_data_fetch) > cache_duration) {
+ cache_expired = 1;
+ }
else {
- cache_expired = 0;
- }
+ cache_expired = 0;
+ }
}
#ifdef NO_CACHING