mirror of
https://github.com/wolfcw/libfaketime.git
synced 2026-05-17 00:26:16 +03:00
Added new feature to limit libfaketime activity
These changes add a new feature that can be used to limit libfaketime's activity period, and prepares for the upcoming 0.9 release. Four new environment variables can optionally be set: FAKETIME_START_AFTER_SECONDS, FAKETIME_STOP_AFTER_SECONDS, FAKETIME_START_AFTER_NUMCALLS, and FAKETIME_START_AFTER_NUMCALLS. libfaketime will only return faked timestamps if the program's runtime is between FAKETIME_START_AFTER_SECONDS and FAKETIME_STOP_AFTER_SECONDS seconds. For example, a program may be started with the real current time, and after 60 seconds, it will start to receive faked timestamps, e.g., one year in the future. The other pair of environment variables limits libfaketime's activity based on the number of time-related system calls of the started program, instead of its run-time in seconds. Using this new feature will break applications that cannot handle larger sudden changes in timestamps, so use it with care.
This commit is contained in:
9
NEWS
9
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!
|
||||
|
||||
73
README
73
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
|
||||
----------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user