/* * faketime.c - Main part of libfaketime.so * * Michal Ludvig , (c) 2003 * http://www.logix.cz/michal/devel/faketime * * Preload to a program calling time(2) or gettimeofday(2) * functions if you need to make it think that it's not * the current date but something different. * * Run ./libfaketime.so to get a more detailed help or * check __faketime_main() function below. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include "ld-so.h" /* On ELF systems the library can print a short help * is invoked directly. */ #define HAVE_ELF /* Here we store pointers to orginal time() and gettimeofday() * functions. */ time_t (*orig_time) (time_t *t); int (*orig_gettimeofday) (struct timeval *tv, struct timezone *tz); int (*orig_clock_gettime) (clockid_t clk_id, struct timespec *tp); time_t correction = 0; int need_parse_env = 1; /* Look for and store pointers to orginal time() and gettimeofday() * functions. */ static int open_shlib (void) { orig_time = dlsym (RTLD_NEXT, "time"); if (dlerror() != NULL) return -1; orig_gettimeofday = dlsym (RTLD_NEXT, "gettimeofday"); if (dlerror() != NULL) return -1; orig_clock_gettime = dlsym (RTLD_NEXT, "clock_gettime"); if (dlerror() != NULL) return -1; return 0; } /* Look for FAKE_TIME_OFFSET or FAKE_TIME_START environment * variables. */ static void parse_env (time_t curr_time) { char *fake_env = NULL; time_t fake_long = 0; need_parse_env = 0; fake_env = getenv ("FAKE_TIME_OFFSET"); if (fake_env) { correction = -atoll (fake_env); return; } fake_env = getenv ("FAKE_TIME_START"); if (fake_env) fake_long = atoll (fake_env); if (fake_long) correction = curr_time - fake_long; } /* Here we go - wrapper for time(2). */ extern time_t time (time_t *t) { time_t curr_time; if (! orig_time && open_shlib () != 0) return -1; curr_time = (*orig_time) (t); if (need_parse_env) parse_env (curr_time); if (t) *t -= correction; return (curr_time - correction); } /* Wrapper for gettimeofday (2). */ extern int gettimeofday (struct timeval *tv, struct timezone *tz) { int ret; if (! orig_gettimeofday && open_shlib () != 0) return -1; ret = (*orig_gettimeofday) (tv, tz); if (ret == 0 && tv) { if (need_parse_env) parse_env (tv->tv_sec); tv->tv_sec -= correction; } return ret; } /* Wrapper for clock_gettime(3). */ extern int clock_gettime(clockid_t clk_id, struct timespec *tp) { int ret; if (! orig_clock_gettime && open_shlib () != 0) return -1; ret = (*orig_clock_gettime) (clk_id, tp); if (ret == 0 && tp) { if (need_parse_env) parse_env (tp->tv_sec); tp->tv_sec -= correction; } return ret; } #ifdef HAVE_ELF /* This is an entrypoint if the library is invoked as a program, i.e. * $ ./libfaketime.so * In this case it prints a short help. * NOTE: This is only usable on ELF systems! */ extern void __faketime_main (void) __attribute__ ((noreturn)); void __faketime_main (void) { char *banner = "" " libfaketime.so - Library for subverting current time.\n" "\n" " Michal Ludvig , (c) 2003\n" " http://www.logix.cz/michal/devel/faketime\n" " \n" " Preload to a program calling time(2), gettimeofday(2) \n" " or clock_gettime(3) functions if you need to make it think \n" " that it's not the current date but a different one.\n" "\n" " Usage:\n" " \n" " Set one of these environment variables:\n" " \n" " FAKE_TIME_START=\n" " First call to time() or gettimeofday() will return\n" " the given . Subsequent calls will\n" " return a time with appropriate correction, i.e. if\n" " the second call to time() occurs five seconds after\n" " the first one, it will return +5.\n" " \n" " FAKE_TIME_OFFSET=\n" " Each call to time() or gettimeofday() returns \n" " current time + . \n" "\n" " If both variables are set, FAKE_TIME_OFFSET has a precedence.\n" "\n" " To convert a given time to use:\n" " $ date -d \"2000-01-01 12:13:14\" +%s\n" " 946725194\n" "\n" " Example:\n" "\n" " $ date\n" " Wed Sep 24 14:41:20 CEST 2003\n" " \n" " $ FAKE_TIME_OFFSET=-86400 LD_PRELOAD=./libfaketime.so date\n" " Tue Sep 23 14:41:20 CEST 2003\n" " \n" " $ FAKE_TIME_START=946725194 LD_PRELOAD=./libfaketime.so date\n" " Sat Jan 1 12:13:14 CET 2000\n" "\n"; printf ("%s", banner); _exit (0); } const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp"))) = LD_SO; #endif /* HAVE_ELF */