diff options
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | README | 73 | ||||
-rw-r--r-- | src/Makefile | 5 | ||||
-rw-r--r-- | src/Makefile.MacOS | 6 | ||||
-rw-r--r-- | src/faketime.c | 58 |
5 files changed, 141 insertions, 10 deletions
@@ -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! @@ -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 |