1 /*
2  *  This file is part of libfaketime, version 0.9.6
3  *
4  *  libfaketime is free software; you can redistribute it and/or modify it
5  *  under the terms of the GNU General Public License v2 as published by the
6  *  Free Software Foundation.
7  *
8  *  libfaketime is distributed in the hope that it will be useful, but WITHOUT
9  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  *  more details.
12  *
13  *  You should have received a copy of the GNU General Public License v2 along
14  *  with the libfaketime; if not, write to the Free Software Foundation,
15  *  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17 
18 /*
19  *      =======================================================================
20  *      Global settings, includes, and macros                          === HEAD
21  *      =======================================================================
22  */
23 
24 #define _GNU_SOURCE             /* required to get RTLD_NEXT defined */
25 
26 /*
27  * libfaketime.c:1246:5: error: conflicting types for 'gettimeofday'
28  * int gettimeofday(struct timeval *tv, void *tz)
29  * vs
30  * int gettimeofday(struct timeval *, struct timezone *);
31  */
32 
33 #define gettimeofday bsd_gettimeofday
34 #include <sys/time.h>
35 #undef gettimeofday
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdint.h>
40 #include <stdbool.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <poll.h>
44 #include <time.h>
45 #include <math.h>
46 #include <errno.h>
47 #include <string.h>
48 #include <semaphore.h>
49 #include <sys/mman.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <netinet/in.h>
53 #include <limits.h>
54 
55 #include "time_ops.h"
56 #include "faketime_common.h"
57 
58 /* pthread-handling contributed by David North, TDI in version 0.7 */
59 #ifdef PTHREAD
60 #include <pthread.h>
61 #endif
62 
63 #include <sys/timeb.h>
64 #include <dlfcn.h>
65 
66 #define BUFFERLEN   256
67 
68 #ifndef __APPLE__
69 extern char *__progname;
70 #ifdef __sun
71 #include "sunos_endian.h"
72 #elif defined(__FreeBSD__) || defined(__DragonFly__)
73 #include <sys/endian.h>
74 #else
75 #include <endian.h>
76 #endif
77 #else
78 /* endianness related macros */
79 #define htobe64(x) OSSwapHostToBigInt64(x)
80 #define htole64(x) OSSwapHostToLittleInt64(x)
81 #define be64toh(x) OSSwapBigToHostInt64(x)
82 #define le64toh(x) OSSwapLittleToHostInt64(x)
83 
84 /* clock_gettime() and related clock definitions are missing on __APPLE__ */
85 #ifndef CLOCK_REALTIME
86 /* from GNU C Library time.h */
87 /* Identifier for system-wide realtime clock. ( == 1) */
88 #define CLOCK_REALTIME               CALENDAR_CLOCK
89 /* Monotonic system-wide clock. (== 0) */
90 #define CLOCK_MONOTONIC              SYSTEM_CLOCK
91 /* High-resolution timer from the CPU.  */
92 #define CLOCK_PROCESS_CPUTIME_ID     2
93 /* Thread-specific CPU-time clock.  */
94 #define CLOCK_THREAD_CPUTIME_ID      3
95 /* Monotonic system-wide clock, not adjusted for frequency scaling.  */
96 #define CLOCK_MONOTONIC_RAW          4
97 typedef int clockid_t;
98 #include <mach/clock.h>
99 #include <mach/mach.h>
100 #endif
101 #endif
102 
103 /* some systems lack raw clock */
104 #ifndef CLOCK_MONOTONIC_RAW
105 #define CLOCK_MONOTONIC_RAW (CLOCK_MONOTONIC + 1)
106 #endif
107 
108 #ifdef __DragonFly__
109 #define stat64 stat
110 #endif
111 
112 /*
113  * Per thread variable, which we turn on inside real_* calls to avoid modifying
114  * time multiple times of for the whole process to prevent faking time
115  */
116 static __thread bool dont_fake = false;
117 
118 /* Wrapper for function calls, which we want to return system time */
119 #define DONT_FAKE_TIME(call)          \
120   {                                   \
121     bool dont_fake_orig = dont_fake;  \
122     if (!dont_fake)                   \
123     {                                 \
124       dont_fake = true;               \
125     }                                 \
126     call;                             \
127     dont_fake = dont_fake_orig;       \
128   } while (0)
129 
130 /* pointers to real (not faked) functions */
131 static int          (*real_stat)            (int, const char *, struct stat *);
132 static int          (*real_fstat)           (int, int, struct stat *);
133 static int          (*real_fstatat)         (int, int, const char *, struct stat *, int);
134 static int          (*real_lstat)           (int, const char *, struct stat *);
135 static int          (*real_stat64)          (int, const char *, struct stat64 *);
136 static int          (*real_fstat64)         (int, int , struct stat64 *);
137 static int          (*real_fstatat64)       (int, int , const char *, struct stat64 *, int);
138 static int          (*real_lstat64)         (int, const char *, struct stat64 *);
139 static time_t       (*real_time)            (time_t *);
140 static int          (*real_ftime)           (struct timeb *);
141 static int          (*real_gettimeofday)    (struct timeval *, void *);
142 static int          (*real_clock_gettime)   (clockid_t clk_id, struct timespec *tp);
143 #ifdef FAKE_INTERNAL_CALLS
144 static int          (*real___ftime)           (struct timeb *);
145 static int          (*real___gettimeofday)    (struct timeval *, void *);
146 static int          (*real___clock_gettime)   (clockid_t clk_id, struct timespec *tp);
147 #endif
148 #ifndef __APPLE__
149 #ifdef FAKE_TIMERS
150 static int          (*real_timer_settime_22)   (int timerid, int flags, const struct itimerspec *new_value,
151                                                 struct itimerspec * old_value);
152 static int          (*real_timer_settime_233)  (timer_t timerid, int flags,
153                                                 const struct itimerspec *new_value,
154                                                 struct itimerspec * old_value);
155 static int          (*real_timer_gettime_22)   (int timerid,
156                                                 struct itimerspec *curr_value);
157 static int          (*real_timer_gettime_233)  (timer_t timerid,
158                                                 struct itimerspec *curr_value);
159 #endif
160 #endif
161 #ifdef FAKE_SLEEP
162 static int          (*real_nanosleep)       (const struct timespec *req, struct timespec *rem);
163 static int          (*real_usleep)          (useconds_t usec);
164 static unsigned int (*real_sleep)           (unsigned int seconds);
165 static unsigned int (*real_alarm)           (unsigned int seconds);
166 static int          (*real_poll)            (struct pollfd *, nfds_t, int);
167 static int          (*real_ppoll)           (struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
168 static int          (*real_sem_timedwait)   (sem_t*, const struct timespec*);
169 #endif
170 #ifdef __APPLE__
171 static int          (*real_clock_get_time)  (clock_serv_t clock_serv, mach_timespec_t *cur_timeclockid_t);
172 static int          apple_clock_gettime     (clockid_t clk_id, struct timespec *tp);
173 static clock_serv_t clock_serv_real;
174 #endif
175 
176 static int initialized = 0;
177 
178 /* prototypes */
179 static int    fake_gettimeofday(struct timeval *tv);
180 static int    fake_clock_gettime(clockid_t clk_id, struct timespec *tp);
181 
182 /** Semaphore protecting shared data */
183 static sem_t *shared_sem = NULL;
184 
185 /** Data shared among faketime-spawned processes */
186 static struct ft_shared_s *ft_shared = NULL;
187 
188 /** Storage format for timestamps written to file. Big endian.*/
189 struct saved_timestamp
190 {
191   int64_t sec;
192   uint64_t nsec;
193 };
194 
timespec_from_saved(struct timespec * tp,struct saved_timestamp * saved)195 static inline void timespec_from_saved (struct timespec *tp,
196   struct saved_timestamp *saved)
197 {
198   /* read as big endian */
199   tp->tv_sec = be64toh(saved->sec);
200   tp->tv_nsec = be64toh(saved->nsec);
201 }
202 
203 /** Saved timestamps */
204 static struct saved_timestamp *stss = NULL;
205 static size_t infile_size;
206 static bool infile_set = false;
207 
208 /** File fd to save timestamps to */
209 static int outfile = -1;
210 
211 static bool limited_faking = false;
212 static long callcounter = 0;
213 static long ft_start_after_secs = -1;
214 static long ft_stop_after_secs = -1;
215 static long ft_start_after_ncalls = -1;
216 static long ft_stop_after_ncalls = -1;
217 
218 static bool spawnsupport = false;
219 static int spawned = 0;
220 static char ft_spawn_target[1024];
221 static long ft_spawn_secs = -1;
222 static long ft_spawn_ncalls = -1;
223 
224 static int fake_monotonic_clock = 1;
225 static int cache_enabled = 1;
226 static int cache_duration = 10;     /* cache fake time input for 10 seconds */
227 
228 /*
229  * Static timespec to store our startup time, followed by a load-time library
230  * initialization declaration.
231  */
232 static struct system_time_s ftpl_starttime = {{0, -1}, {0, -1}, {0, -1}};
233 
234 static char user_faked_time_fmt[BUFSIZ] = {0};
235 
236 /* User supplied base time to fake */
237 static struct timespec user_faked_time_timespec = {0, -1};
238 /* User supplied base time is set */
239 static bool user_faked_time_set = false;
240 static char user_faked_time_saved[BUFFERLEN] = {0};
241 
242 /* Fractional user offset provided through FAKETIME env. var.*/
243 static struct timespec user_offset = {0, -1};
244 /* Speed up or slow down clock */
245 static double user_rate = 1.0;
246 static bool user_rate_set = false;
247 static struct timespec user_per_tick_inc = {0, -1};
248 static bool user_per_tick_inc_set = false;
249 
250 enum ft_mode_t {FT_FREEZE, FT_START_AT, FT_NOOP} ft_mode = FT_FREEZE;
251 
252 /* Time to fake is not provided through FAKETIME env. var. */
253 static bool parse_config_file = true;
254 
255 void ft_cleanup (void) __attribute__ ((destructor));
256 void ftpl_init (void) __attribute__ ((constructor));
257 
258 
259 /*
260  *      =======================================================================
261  *      Shared memory related functions                                 === SHM
262  *      =======================================================================
263  */
264 
ft_shm_init(void)265 static void ft_shm_init (void)
266 {
267   int ticks_shm_fd;
268   char sem_name[256], shm_name[256], *ft_shared_env = getenv("FAKETIME_SHARED");
269 
270   if (ft_shared_env != NULL)
271   {
272     if (sscanf(ft_shared_env, "%255s %255s", sem_name, shm_name) < 2)
273     {
274       printf("Error parsing semaphore name and shared memory id from string: %s", ft_shared_env);
275       exit(1);
276     }
277 
278     if (SEM_FAILED == (shared_sem = sem_open(sem_name, 0)))
279     {
280       perror("sem_open");
281       exit(1);
282     }
283 
284     if (-1 == (ticks_shm_fd = shm_open(shm_name, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)))
285     {
286       perror("shm_open");
287       exit(1);
288     }
289 
290     if (MAP_FAILED == (ft_shared = mmap(NULL, sizeof(struct ft_shared_s), PROT_READ|PROT_WRITE,
291             MAP_SHARED, ticks_shm_fd, 0)))
292     {
293       perror("mmap");
294       exit(1);
295     }
296   }
297 }
298 
ft_cleanup(void)299 void ft_cleanup (void)
300 {
301   /* detach from shared memory */
302   if (ft_shared != NULL)
303   {
304     munmap(ft_shared, sizeof(uint64_t));
305   }
306   if (stss != NULL)
307   {
308     munmap(stss, infile_size);
309   }
310   if (shared_sem != NULL)
311   {
312     sem_close(shared_sem);
313   }
314 }
315 
316 
317 /*
318  *      =======================================================================
319  *      Internal time retrieval                                     === INTTIME
320  *      =======================================================================
321  */
322 
323 /* Get system time from system for all clocks */
system_time_from_system(struct system_time_s * systime)324 static void system_time_from_system (struct system_time_s * systime)
325 {
326 #ifdef __APPLE__
327   /* from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x */
328   clock_serv_t cclock;
329   mach_timespec_t mts;
330   host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clock_serv_real);
331   (*real_clock_get_time)(clock_serv_real, &mts);
332   systime->real.tv_sec = mts.tv_sec;
333   systime->real.tv_nsec = mts.tv_nsec;
334   host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
335   (*real_clock_get_time)(cclock, &mts);
336   mach_port_deallocate(mach_task_self(), cclock);
337   systime->mon.tv_sec = mts.tv_sec;
338   systime->mon.tv_nsec = mts.tv_nsec;
339   systime->mon_raw.tv_sec = mts.tv_sec;
340   systime->mon_raw.tv_nsec = mts.tv_nsec;
341 #else
342   DONT_FAKE_TIME((*real_clock_gettime)(CLOCK_REALTIME, &systime->real));
343   DONT_FAKE_TIME((*real_clock_gettime)(CLOCK_MONOTONIC, &systime->mon));
344   DONT_FAKE_TIME((*real_clock_gettime)(CLOCK_MONOTONIC_RAW, &systime->mon_raw));
345 #endif
346 }
347 
next_time(struct timespec * tp,struct timespec * ticklen)348 static void next_time(struct timespec *tp, struct timespec *ticklen)
349 {
350   if (shared_sem != NULL)
351   {
352     struct timespec inc;
353     /* lock */
354     if (sem_wait(shared_sem) == -1)
355     {
356       perror("sem_wait");
357       exit(1);
358     }
359     /* calculate and update elapsed time */
360     timespecmul(ticklen, ft_shared->ticks, &inc);
361     timespecadd(&user_faked_time_timespec, &inc, tp);
362     (ft_shared->ticks)++;
363     /* unlock */
364     if (sem_post(shared_sem) == -1)
365     {
366       perror("sem_post");
367       exit(1);
368     }
369   }
370 }
371 
372 
373 /*
374  *      =======================================================================
375  *      Saving & loading time                                          === SAVE
376  *      =======================================================================
377  */
378 
save_time(struct timespec * tp)379 static void save_time(struct timespec *tp)
380 {
381   if ((shared_sem != NULL) && (outfile != -1))
382   {
383     struct saved_timestamp time_write;
384     ssize_t written;
385     size_t n = 0;
386 
387     time_write.sec = htobe64(tp->tv_sec);
388     time_write.nsec = htobe64(tp->tv_nsec);
389 
390     /* lock */
391     if (sem_wait(shared_sem) == -1)
392     {
393       perror("sem_wait");
394       exit(1);
395     }
396 
397     lseek(outfile, 0, SEEK_END);
398     do
399     {
400       written = write(outfile, &(((char*)&time_write)[n]), sizeof(time_write) - n);
401     }
402     while (((written == -1) && (errno == EINTR)) ||
403             (sizeof(time_write) < (n += written)));
404 
405     if ((written == -1) || (n < sizeof(time_write)))
406     {
407       perror("Saving timestamp to file failed");
408     }
409 
410     /* unlock */
411     if (sem_post(shared_sem) == -1)
412     {
413       perror("sem_post");
414       exit(1);
415     }
416   }
417 }
418 
419 /*
420  * Provide faked time from file.
421  * @return time is set from filen
422  */
load_time(struct timespec * tp)423 static bool load_time(struct timespec *tp)
424 {
425   bool ret = false;
426   if ((shared_sem != NULL) && (infile_set))
427   {
428     /* lock */
429     if (sem_wait(shared_sem) == -1)
430     {
431       perror("sem_wait");
432       exit(1);
433     }
434 
435     if ((sizeof(stss[0]) * (ft_shared->file_idx + 1)) > infile_size)
436     {
437       /* we are out of timstamps to replay, return to faking time by rules
438        * using last timestamp from file as the user provided timestamp */
439       timespec_from_saved(&user_faked_time_timespec, &stss[(infile_size / sizeof(stss[0])) - 1 ]);
440 
441       if (ft_shared->ticks == 0)
442       {
443         /* we set shared memory to stop using infile */
444         ft_shared->ticks = 1;
445         system_time_from_system(&ftpl_starttime);
446         ft_shared->start_time = ftpl_starttime;
447       }
448       else
449       {
450         ftpl_starttime = ft_shared->start_time;
451       }
452 
453       munmap(stss, infile_size);
454       infile_set = false;
455     }
456     else
457     {
458       timespec_from_saved(tp, &stss[ft_shared->file_idx]);
459       ft_shared->file_idx++;
460       ret = true;
461     }
462 
463     /* unlock */
464     if (sem_post(shared_sem) == -1)
465     {
466       perror("sem_post");
467       exit(1);
468     }
469   }
470   return ret;
471 }
472 
473 
474 /*
475  *      =======================================================================
476  *      Faked system functions: file related                     === FAKE(FILE)
477  *      =======================================================================
478  */
479 
480 #ifdef FAKE_STAT
481 
482 #ifndef NO_ATFILE
483 #ifndef _ATFILE_SOURCE
484 #define _ATFILE_SOURCE
485 #endif
486 #include <fcntl.h> /* Definition of AT_* constants */
487 #endif
488 
489 #include <sys/stat.h>
490 
491 static int fake_stat_disabled = 0;
492 
493 #define FAKE_STRUCT_STAT_TIME(which) {                \
494     struct timespec t = {buf->st_##which##time,       \
495                          buf->st_##which##timensec};  \
496     fake_clock_gettime(CLOCK_REALTIME, &t);           \
497     buf->st_##which##time = t.tv_sec;                 \
498     buf->st_##which##timensec = t.tv_nsec;            \
499   } while (0)
500 
fake_statbuf(struct stat * buf)501 static inline void fake_statbuf (struct stat *buf) {
502 #ifndef st_atime
503   FAKE_STRUCT_STAT_TIME(c);
504   FAKE_STRUCT_STAT_TIME(a);
505   FAKE_STRUCT_STAT_TIME(m);
506 #else
507   fake_clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
508   fake_clock_gettime(CLOCK_REALTIME, &buf->st_atim);
509   fake_clock_gettime(CLOCK_REALTIME, &buf->st_mtim);
510 #endif
511 }
512 
fake_stat64buf(struct stat64 * buf)513 static inline void fake_stat64buf (struct stat64 *buf) {
514 #ifndef st_atime
515   FAKE_STRUCT_STAT_TIME(c);
516   FAKE_STRUCT_STAT_TIME(a);
517   FAKE_STRUCT_STAT_TIME(m);
518 #else
519   fake_clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
520   fake_clock_gettime(CLOCK_REALTIME, &buf->st_atim);
521   fake_clock_gettime(CLOCK_REALTIME, &buf->st_mtim);
522 #endif
523 }
524 
525 /* Contributed by Philipp Hachtmann in version 0.6 */
__xstat(int ver,const char * path,struct stat * buf)526 int __xstat (int ver, const char *path, struct stat *buf)
527 {
528   if (!initialized)
529   {
530     ftpl_init();
531   }
532   if (NULL == real_stat)
533   { /* dlsym() failed */
534 #ifdef DEBUG
535     (void) fprintf(stderr, "faketime problem: original stat() not found.\n");
536 #endif
537     return -1; /* propagate error to caller */
538   }
539 
540   int result;
541   DONT_FAKE_TIME(result = real_stat(ver, path, buf));
542   if (result == -1)
543   {
544     return -1;
545   }
546 
547    if (buf != NULL)
548    {
549      if (!fake_stat_disabled)
550      {
551        fake_statbuf(buf);
552      }
553    }
554 
555   return result;
556 }
557 
558 /* Contributed by Philipp Hachtmann in version 0.6 */
__fxstat(int ver,int fildes,struct stat * buf)559 int __fxstat (int ver, int fildes, struct stat *buf)
560 {
561   if (!initialized)
562   {
563     ftpl_init();
564   }
565   if (NULL == real_fstat)
566   {  /* dlsym() failed */
567 #ifdef DEBUG
568     (void) fprintf(stderr, "faketime problem: original fstat() not found.\n");
569 #endif
570     return -1; /* propagate error to caller */
571   }
572 
573   int result;
574   DONT_FAKE_TIME(result = real_fstat(ver, fildes, buf));
575   if (result == -1)
576   {
577     return -1;
578   }
579 
580   if (buf != NULL)
581   {
582     if (!fake_stat_disabled)
583     {
584       fake_statbuf(buf);
585     }
586   }
587   return result;
588 }
589 
590 /* Added in v0.8 as suggested by Daniel Kahn Gillmor */
591 #ifndef NO_ATFILE
__fxstatat(int ver,int fildes,const char * filename,struct stat * buf,int flag)592 int __fxstatat(int ver, int fildes, const char *filename, struct stat *buf, int flag)
593 {
594   if (!initialized)
595   {
596     ftpl_init();
597   }
598   if (NULL == real_fstatat)
599   { /* dlsym() failed */
600 #ifdef DEBUG
601     (void) fprintf(stderr, "faketime problem: original fstatat() not found.\n");
602 #endif
603     return -1; /* propagate error to caller */
604   }
605 
606   int result;
607   DONT_FAKE_TIME(result = real_fstatat(ver, fildes, filename, buf, flag));
608   if (result == -1)
609   {
610     return -1;
611   }
612 
613   if (buf != NULL)
614   {
615     if (!fake_stat_disabled)
616     {
617       fake_statbuf(buf);
618     }
619   }
620   return result;
621 }
622 #endif
623 
624 /* Contributed by Philipp Hachtmann in version 0.6 */
__lxstat(int ver,const char * path,struct stat * buf)625 int __lxstat (int ver, const char *path, struct stat *buf)
626 {
627   if (!initialized)
628   {
629     ftpl_init();
630   }
631   if (NULL == real_lstat)
632   {  /* dlsym() failed */
633 #ifdef DEBUG
634     (void) fprintf(stderr, "faketime problem: original lstat() not found.\n");
635 #endif
636     return -1; /* propagate error to caller */
637   }
638 
639   int result;
640   DONT_FAKE_TIME(result = real_lstat(ver, path, buf));
641   if (result == -1)
642   {
643     return -1;
644   }
645 
646   if (buf != NULL)
647   {
648     if (!fake_stat_disabled)
649     {
650       fake_statbuf(buf);
651     }
652   }
653   return result;
654 }
655 
656 /* Contributed by Philipp Hachtmann in version 0.6 */
__xstat64(int ver,const char * path,struct stat64 * buf)657 int __xstat64 (int ver, const char *path, struct stat64 *buf)
658 {
659   if (!initialized)
660   {
661     ftpl_init();
662   }
663   if (NULL == real_stat64)
664   { /* dlsym() failed */
665 #ifdef DEBUG
666     (void) fprintf(stderr, "faketime problem: original stat() not found.\n");
667 #endif
668     return -1; /* propagate error to caller */
669   }
670 
671   int result;
672   DONT_FAKE_TIME(result = real_stat64(ver, path, buf));
673   if (result == -1)
674   {
675     return -1;
676   }
677 
678   if (buf != NULL)
679   {
680     if (!fake_stat_disabled)
681     {
682       fake_stat64buf(buf);
683     }
684   }
685   return result;
686 }
687 
688 /* Contributed by Philipp Hachtmann in version 0.6 */
__fxstat64(int ver,int fildes,struct stat64 * buf)689 int __fxstat64 (int ver, int fildes, struct stat64 *buf)
690 {
691   if (!initialized)
692   {
693     ftpl_init();
694   }
695   if (NULL == real_fstat64)
696   {  /* dlsym() failed */
697 #ifdef DEBUG
698     (void) fprintf(stderr, "faketime problem: original fstat() not found.\n");
699 #endif
700     return -1; /* propagate error to caller */
701   }
702 
703   int result;
704   DONT_FAKE_TIME(result = real_fstat64(ver, fildes, buf));
705   if (result == -1)
706   {
707     return -1;
708   }
709 
710   if (buf != NULL)
711   {
712     if (!fake_stat_disabled)
713     {
714       fake_stat64buf(buf);
715     }
716   }
717   return result;
718 }
719 
720 /* Added in v0.8 as suggested by Daniel Kahn Gillmor */
721 #ifndef NO_ATFILE
__fxstatat64(int ver,int fildes,const char * filename,struct stat64 * buf,int flag)722 int __fxstatat64 (int ver, int fildes, const char *filename, struct stat64 *buf, int flag)
723 {
724   if (!initialized)
725   {
726     ftpl_init();
727   }
728   if (NULL == real_fstatat64)
729   {  /* dlsym() failed */
730 #ifdef DEBUG
731     (void) fprintf(stderr, "faketime problem: original fstatat64() not found.\n");
732 #endif
733     return -1; /* propagate error to caller */
734   }
735 
736   int result;
737   DONT_FAKE_TIME(result = real_fstatat64(ver, fildes, filename, buf, flag));
738   if (result == -1)
739   {
740     return -1;
741   }
742 
743   if (buf != NULL)
744   {
745     if (!fake_stat_disabled)
746     {
747       fake_stat64buf(buf);
748     }
749   }
750   return result;
751 }
752 #endif
753 
754 /* Contributed by Philipp Hachtmann in version 0.6 */
__lxstat64(int ver,const char * path,struct stat64 * buf)755 int __lxstat64 (int ver, const char *path, struct stat64 *buf)
756 {
757   if (!initialized)
758   {
759     ftpl_init();
760   }
761   if (NULL == real_lstat64)
762   {  /* dlsym() failed */
763 #ifdef DEBUG
764     (void) fprintf(stderr, "faketime problem: original lstat() not found.\n");
765 #endif
766     return -1; /* propagate error to caller */
767   }
768 
769   int result;
770   DONT_FAKE_TIME(result = real_lstat64(ver, path, buf));
771   if (result == -1)
772   {
773     return -1;
774   }
775 
776   if (buf != NULL)
777   {
778     if (!fake_stat_disabled)
779     {
780       fake_stat64buf(buf);
781     }
782   }
783   return result;
784 }
785 #endif
786 
787 /*
788  *      =======================================================================
789  *      Faked system functions: sleep/alarm/poll/timer related  === FAKE(SLEEP)
790  *      =======================================================================
791  *      Contributed by Balint Reczey in v0.9.5
792  */
793 
794 #ifdef FAKE_SLEEP
795 /*
796  * Faked nanosleep()
797  */
nanosleep(const struct timespec * req,struct timespec * rem)798 int nanosleep(const struct timespec *req, struct timespec *rem)
799 {
800   int result;
801   struct timespec real_req;
802 
803   if (!initialized)
804   {
805     ftpl_init();
806   }
807   if (real_nanosleep == NULL)
808   {
809     return -1;
810   }
811   if (req != NULL)
812   {
813     if (user_rate_set && !dont_fake)
814     {
815       timespecmul(req, 1.0 / user_rate, &real_req);
816     }
817     else
818     {
819       real_req = *req;
820     }
821   }
822   else
823   {
824     return -1;
825   }
826 
827   DONT_FAKE_TIME(result = (*real_nanosleep)(&real_req, rem));
828   if (result == -1)
829   {
830     return result;
831   }
832 
833   /* fake returned parts */
834   if ((rem != NULL) && ((rem->tv_sec != 0) || (rem->tv_nsec != 0)))
835   {
836     if (user_rate_set && !dont_fake)
837     {
838       timespecmul(rem, user_rate, rem);
839     }
840   }
841   /* return the result to the caller */
842   return result;
843 }
844 
845 /*
846  * Faked usleep()
847  */
usleep(useconds_t usec)848 int usleep(useconds_t usec)
849 {
850   int result;
851 
852   if (!initialized)
853   {
854     ftpl_init();
855   }
856   if (user_rate_set && !dont_fake)
857   {
858     struct timespec real_req;
859 
860     if (real_nanosleep == NULL)
861     {
862       /* fall back to usleep() */
863       if (real_usleep == NULL)
864       {
865         return -1;
866       }
867       DONT_FAKE_TIME(result = (*real_usleep)((1.0 / user_rate) * usec));
868       return result;
869     }
870 
871     real_req.tv_sec = usec / 1000000;
872     real_req.tv_nsec = (usec % 1000000) * 1000;
873     timespecmul(&real_req, 1.0 / user_rate, &real_req);
874     DONT_FAKE_TIME(result = (*real_nanosleep)(&real_req, NULL));
875   }
876   else
877   {
878     DONT_FAKE_TIME(result = (*real_usleep)(usec));
879   }
880   return result;
881 }
882 
883 /*
884  * Faked sleep()
885  */
sleep(unsigned int seconds)886 unsigned int sleep(unsigned int seconds)
887 {
888   if (!initialized)
889   {
890     ftpl_init();
891   }
892   if (user_rate_set && !dont_fake)
893   {
894     if (real_nanosleep == NULL)
895     {
896       /* fall back to sleep */
897       unsigned int ret;
898       if (real_sleep == NULL)
899       {
900         return 0;
901       }
902       DONT_FAKE_TIME(ret = (*real_sleep)((1.0 / user_rate) * seconds));
903       return (user_rate_set && !dont_fake)?(user_rate * ret):ret;
904     }
905     else
906     {
907       int result;
908       struct timespec real_req = {seconds, 0}, rem;
909       timespecmul(&real_req, 1.0 / user_rate, &real_req);
910       DONT_FAKE_TIME(result = (*real_nanosleep)(&real_req, &rem));
911       if (result == -1)
912       {
913         return 0;
914       }
915 
916       /* fake returned parts */
917       if ((rem.tv_sec != 0) || (rem.tv_nsec != 0))
918       {
919         timespecmul(&rem, user_rate, &rem);
920       }
921       /* return the result to the caller */
922       return rem.tv_sec;
923     }
924   }
925   else
926   {
927     /* no need to fake anything */
928     unsigned int ret;
929     DONT_FAKE_TIME(ret = (*real_sleep)(seconds));
930     return ret;
931   }
932 }
933 
934 /*
935  * Faked alarm()
936  * @note due to rounding alarm(2) with faketime -f '+0 x7' won't wait 2/7
937  * wall clock seconds but 0 seconds
938  */
alarm(unsigned int seconds)939 unsigned int alarm(unsigned int seconds)
940 {
941   unsigned int ret;
942   unsigned int seconds_real = (user_rate_set && !dont_fake)?((1.0 / user_rate) * seconds):seconds;
943 
944   if (!initialized)
945   {
946     ftpl_init();
947   }
948   if (real_alarm == NULL)
949   {
950     return -1;
951   }
952 
953   DONT_FAKE_TIME(ret = (*real_alarm)(seconds_real));
954   return (user_rate_set && !dont_fake)?(user_rate * ret):ret;
955 }
956 
957 /*
958  * Faked ppoll()
959  */
ppoll(struct pollfd * fds,nfds_t nfds,const struct timespec * timeout_ts,const sigset_t * sigmask)960 int ppoll(struct pollfd *fds, nfds_t nfds,
961     const struct timespec *timeout_ts, const sigset_t *sigmask)
962 {
963   struct timespec real_timeout, *real_timeout_pt;
964   int ret;
965 
966   if (!initialized)
967   {
968     ftpl_init();
969   }
970   if (real_ppoll == NULL)
971   {
972     return -1;
973   }
974   if (timeout_ts != NULL)
975   {
976     if (user_rate_set && !dont_fake && (timeout_ts->tv_sec > 0))
977     {
978       timespecmul(timeout_ts, 1.0 / user_rate, &real_timeout);
979       real_timeout_pt = &real_timeout;
980     }
981     else
982     {
983       /* cast away constness */
984       real_timeout_pt = (struct timespec *)timeout_ts;
985     }
986   }
987   else
988   {
989     real_timeout_pt = NULL;
990   }
991 
992   DONT_FAKE_TIME(ret = (*real_ppoll)(fds, nfds, real_timeout_pt, sigmask));
993   return ret;
994 }
995 
996 /*
997  * Faked poll()
998  */
poll(struct pollfd * fds,nfds_t nfds,int timeout)999 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
1000 {
1001   int ret, timeout_real = (user_rate_set && !dont_fake && (timeout > 0))?(timeout / user_rate):timeout;
1002 
1003   if (!initialized)
1004   {
1005     ftpl_init();
1006   }
1007   if (real_poll == NULL)
1008   {
1009     return -1;
1010   }
1011 
1012   DONT_FAKE_TIME(ret = (*real_poll)(fds, nfds, timeout_real));
1013   return ret;
1014 }
1015 
sem_timedwait(sem_t * sem,const struct timespec * abs_timeout)1016 int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
1017 {
1018   int result;
1019   struct timespec real_abs_timeout, *real_abs_timeout_pt;
1020 
1021   /* sanity check */
1022   if (abs_timeout == NULL)
1023   {
1024     return -1;
1025   }
1026 
1027   if (NULL == real_sem_timedwait)
1028   {  /* dlsym() failed */
1029 #ifdef DEBUG
1030     (void) fprintf(stderr, "faketime problem: original sem_timedwait() not found.\n");
1031 #endif
1032     return -1; /* propagate error to caller */
1033   }
1034 
1035   if (!dont_fake)
1036   {
1037     struct timespec tdiff, timeadj;
1038 
1039     timespecsub(abs_timeout, &ftpl_starttime.real, &tdiff);
1040 
1041     if (user_rate_set)
1042     {
1043       timespecmul(&tdiff, user_rate, &timeadj);
1044     }
1045     else
1046     {
1047         timeadj = tdiff;
1048     }
1049     timespecadd(&user_faked_time_timespec, &timeadj, &real_abs_timeout);
1050     real_abs_timeout_pt = &real_abs_timeout;
1051   }
1052   else
1053   {
1054     /* cast away constness */
1055     real_abs_timeout_pt = (struct timespec *)abs_timeout;
1056   }
1057 
1058   DONT_FAKE_TIME(result = (*real_sem_timedwait)(sem, real_abs_timeout_pt));
1059   return result;
1060 }
1061 #endif
1062 
1063 #ifndef __APPLE__
1064 #ifdef FAKE_TIMERS
1065 
1066 /* timer related functions and structures */
1067 typedef union {
1068   int int_member;
1069   timer_t timer_t_member;
1070 } timer_t_or_int;
1071 
1072 /*
1073  * Faketime's function implementation's compatibility mode
1074  */
1075 typedef enum {FT_COMPAT_GLIBC_2_2, FT_COMPAT_GLIBC_2_3_3} ft_lib_compat;
1076 
1077 
1078 /*
1079  * Faked timer_settime()
1080  * Does not affect timer speed when stepping clock with each time() call.
1081  */
1082 static int
timer_settime_common(timer_t_or_int timerid,int flags,const struct itimerspec * new_value,struct itimerspec * old_value,ft_lib_compat compat)1083 timer_settime_common(timer_t_or_int timerid, int flags,
1084          const struct itimerspec *new_value,
1085          struct itimerspec *old_value, ft_lib_compat compat)
1086 {
1087   int result;
1088   struct itimerspec new_real;
1089   struct itimerspec *new_real_pt = &new_real;
1090 
1091   if (!initialized)
1092   {
1093     ftpl_init();
1094   }
1095   if (new_value == NULL)
1096   {
1097     new_real_pt = NULL;
1098   }
1099   else if (dont_fake)
1100   {
1101     /* cast away constness*/
1102     new_real_pt = (struct itimerspec *)new_value;
1103   }
1104   else
1105   {
1106     /* set it_value */
1107     if ((new_value->it_value.tv_sec != 0) ||
1108         (new_value->it_value.tv_nsec != 0))
1109     {
1110       if (flags & TIMER_ABSTIME)
1111       {
1112         struct timespec tdiff, timeadj;
1113         timespecsub(&new_value->it_value, &user_faked_time_timespec, &timeadj);
1114         if (user_rate_set)
1115         {
1116           timespecmul(&timeadj, 1.0/user_rate, &tdiff);
1117         }
1118         else
1119         {
1120           tdiff = timeadj;
1121         }
1122         /* only CLOCK_REALTIME is handled */
1123         timespecadd(&ftpl_starttime.real, &tdiff, &new_real.it_value);
1124       }
1125       else
1126       {
1127         if (user_rate_set)
1128         {
1129           timespecmul(&new_value->it_value, 1.0/user_rate, &new_real.it_value);
1130         }
1131         else
1132         {
1133           new_real.it_value = new_value->it_value;
1134         }
1135       }
1136     }
1137     else
1138     {
1139       new_real.it_value = new_value->it_value;
1140     }
1141     /* set it_interval */
1142     if (user_rate_set && ((new_value->it_interval.tv_sec != 0) ||
1143        (new_value->it_interval.tv_nsec != 0)))
1144     {
1145       timespecmul(&new_value->it_interval, 1.0/user_rate, &new_real.it_interval);
1146     }
1147     else
1148     {
1149       new_real.it_interval = new_value->it_interval;
1150     }
1151   }
1152 
1153   switch (compat)
1154   {
1155     case FT_COMPAT_GLIBC_2_2:
1156       DONT_FAKE_TIME(result = (*real_timer_settime_22)(timerid.int_member, flags,
1157                     new_real_pt, old_value));
1158       break;
1159     case FT_COMPAT_GLIBC_2_3_3:
1160        DONT_FAKE_TIME(result = (*real_timer_settime_233)(timerid.timer_t_member,
1161                     flags, new_real_pt, old_value));
1162        break;
1163     default:
1164       result = -1;
1165       break;
1166   }
1167 
1168   if (result == -1)
1169   {
1170     return result;
1171   }
1172 
1173   /* fake returned parts */
1174   if ((old_value != NULL) && !dont_fake)
1175   {
1176     if ((old_value->it_value.tv_sec != 0) ||
1177         (old_value->it_value.tv_nsec != 0))
1178     {
1179       result = fake_clock_gettime(CLOCK_REALTIME, &old_value->it_value);
1180     }
1181     if (user_rate_set && ((old_value->it_interval.tv_sec != 0) ||
1182        (old_value->it_interval.tv_nsec != 0)))
1183     {
1184       timespecmul(&old_value->it_interval, user_rate, &old_value->it_interval);
1185     }
1186   }
1187 
1188   /* return the result to the caller */
1189   return result;
1190 }
1191 
1192 /*
1193  * Faked timer_settime() compatible with implementation in GLIBC 2.2
1194  */
timer_settime_22(int timerid,int flags,const struct itimerspec * new_value,struct itimerspec * old_value)1195 int timer_settime_22(int timerid, int flags,
1196          const struct itimerspec *new_value,
1197          struct itimerspec *old_value)
1198 {
1199   if (!initialized)
1200   {
1201     ftpl_init();
1202   }
1203   if (real_timer_settime_22 == NULL)
1204   {
1205     return -1;
1206   }
1207   else
1208   {
1209     return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value,
1210             FT_COMPAT_GLIBC_2_2));
1211   }
1212 }
1213 
1214 /*
1215  * Faked timer_settime() compatible with implementation in GLIBC 2.3.3
1216  */
timer_settime_233(timer_t timerid,int flags,const struct itimerspec * new_value,struct itimerspec * old_value)1217 int timer_settime_233(timer_t timerid, int flags,
1218       const struct itimerspec *new_value,
1219       struct itimerspec *old_value)
1220 {
1221   if (!initialized)
1222   {
1223     ftpl_init();
1224   }
1225   if (real_timer_settime_233 == NULL)
1226   {
1227     return -1;
1228   }
1229   else
1230   {
1231     return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value,
1232             FT_COMPAT_GLIBC_2_3_3));
1233   }
1234 }
1235 
1236 /*
1237  * Faked timer_gettime()
1238  * Does not affect timer speed when stepping clock with each time() call.
1239  */
timer_gettime_common(timer_t_or_int timerid,struct itimerspec * curr_value,ft_lib_compat compat)1240 int timer_gettime_common(timer_t_or_int timerid, struct itimerspec *curr_value, ft_lib_compat compat)
1241 {
1242   int result;
1243 
1244   if (!initialized)
1245   {
1246     ftpl_init();
1247   }
1248   if (real_timer_gettime_233 == NULL)
1249   {
1250     return -1;
1251   }
1252 
1253   switch (compat)
1254   {
1255     case FT_COMPAT_GLIBC_2_2:
1256       DONT_FAKE_TIME(result = (*real_timer_gettime_22)(timerid.int_member, curr_value));
1257       break;
1258     case FT_COMPAT_GLIBC_2_3_3:
1259       DONT_FAKE_TIME(result = (*real_timer_gettime_233)(timerid.timer_t_member, curr_value));
1260       break;
1261     default:
1262       result = -1;
1263       break;
1264   }
1265 
1266   if (result == -1)
1267   {
1268     return result;
1269   }
1270 
1271   /* fake returned parts */
1272   if (curr_value != NULL)
1273   {
1274     if (user_rate_set && !dont_fake)
1275     {
1276       timespecmul(&curr_value->it_interval, user_rate, &curr_value->it_interval);
1277       timespecmul(&curr_value->it_value, user_rate, &curr_value->it_value);
1278     }
1279   }
1280   /* return the result to the caller */
1281   return result;
1282 }
1283 
1284 /*
1285  * Faked timer_gettime() compatible with implementation in GLIBC 2.2
1286  */
timer_gettime_22(timer_t timerid,struct itimerspec * curr_value)1287 int timer_gettime_22(timer_t timerid, struct itimerspec *curr_value)
1288 {
1289   if (!initialized)
1290   {
1291     ftpl_init();
1292   }
1293   if (real_timer_gettime_22 == NULL)
1294   {
1295     return -1;
1296   }
1297   else
1298   {
1299     return (timer_gettime_common((timer_t_or_int)timerid, curr_value,
1300          FT_COMPAT_GLIBC_2_2));
1301   }
1302 }
1303 
1304 /*
1305  * Faked timer_gettime() compatible with implementation in GLIBC 2.3.3
1306  */
timer_gettime_233(timer_t timerid,struct itimerspec * curr_value)1307 int timer_gettime_233(timer_t timerid, struct itimerspec *curr_value)
1308 {
1309   if (!initialized)
1310   {
1311     ftpl_init();
1312   }
1313   if (real_timer_gettime_233 == NULL)
1314   {
1315     return -1;
1316   }
1317   else
1318   {
1319     return (timer_gettime_common((timer_t_or_int)timerid, curr_value,
1320             FT_COMPAT_GLIBC_2_3_3));
1321   }
1322 }
1323 
1324 __asm__(".symver timer_gettime_22, timer_gettime@GLIBC_2.2");
1325 __asm__(".symver timer_gettime_233, timer_gettime@@GLIBC_2.3.3");
1326 __asm__(".symver timer_settime_22, timer_settime@GLIBC_2.2");
1327 __asm__(".symver timer_settime_233, timer_settime@@GLIBC_2.3.3");
1328 
1329 #endif
1330 #endif
1331 
1332 
1333 /*
1334  *      =======================================================================
1335  *      Faked system functions: basic time functions             === FAKE(TIME)
1336  *      =======================================================================
1337  */
1338 
1339 /*
1340  * time() implementation using clock_gettime()
1341  * @note Does not check for EFAULT, see man 2 time
1342  */
time(time_t * time_tptr)1343 time_t time(time_t *time_tptr)
1344 {
1345   struct timespec tp;
1346   time_t result;
1347 
1348   if (!initialized)
1349   {
1350     ftpl_init();
1351   }
1352   DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
1353   if (result == -1) return -1;
1354 
1355   /* pass the real current time to our faking version, overwriting it */
1356   (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
1357 
1358   if (time_tptr != NULL)
1359   {
1360     *time_tptr = tp.tv_sec;
1361   }
1362   return tp.tv_sec;
1363 }
1364 
ftime(struct timeb * tb)1365 int ftime(struct timeb *tb)
1366 {
1367   struct timespec tp;
1368   int result;
1369 
1370   if (!initialized)
1371   {
1372     ftpl_init();
1373   }
1374   /* sanity check */
1375   if (tb == NULL)
1376     return 0;               /* ftime() always returns 0, see manpage */
1377 
1378   /* Check whether we've got a pointer to the real ftime() function yet */
1379   if (NULL == real_ftime)
1380   {  /* dlsym() failed */
1381 #ifdef DEBUG
1382     (void) fprintf(stderr, "faketime problem: original ftime() not found.\n");
1383 #endif
1384     return 0; /* propagate error to caller */
1385   }
1386 
1387   /* initialize our TZ result with the real current time */
1388   DONT_FAKE_TIME(result = (*real_ftime)(tb));
1389   if (result == -1)
1390   {
1391     return result;
1392   }
1393 
1394   DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
1395   if (result == -1) return -1;
1396 
1397   /* pass the real current time to our faking version, overwriting it */
1398   (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
1399 
1400   tb->time = tp.tv_sec;
1401   tb->millitm = tp.tv_nsec / 1000000;
1402 
1403   /* return the result to the caller */
1404   return result; /* will always be 0 (see manpage) */
1405 }
1406 
gettimeofday(struct timeval * tv,void * tz)1407 int gettimeofday(struct timeval *tv, void *tz)
1408 {
1409   int result;
1410 
1411   if (!initialized)
1412   {
1413     ftpl_init();
1414   }
1415   /* sanity check */
1416   if (tv == NULL)
1417   {
1418     return -1;
1419   }
1420 
1421   /* Check whether we've got a pointer to the real ftime() function yet */
1422   if (NULL == real_gettimeofday)
1423   {  /* dlsym() failed */
1424 #ifdef DEBUG
1425     (void) fprintf(stderr, "faketime problem: original gettimeofday() not found.\n");
1426 #endif
1427     return -1; /* propagate error to caller */
1428   }
1429 
1430   /* initialize our result with the real current time */
1431   DONT_FAKE_TIME(result = (*real_gettimeofday)(tv, tz));
1432   if (result == -1) return result; /* original function failed */
1433 
1434   /* pass the real current time to our faking version, overwriting it */
1435   result = fake_gettimeofday(tv);
1436 
1437   /* return the result to the caller */
1438   return result;
1439 }
1440 
clock_gettime(clockid_t clk_id,struct timespec * tp)1441 int clock_gettime(clockid_t clk_id, struct timespec *tp)
1442 {
1443   int result;
1444 
1445   if (!initialized)
1446   {
1447     ftpl_init();
1448   }
1449   /* sanity check */
1450   if (tp == NULL)
1451   {
1452     return -1;
1453   }
1454 
1455   if (NULL == real_clock_gettime)
1456   {  /* dlsym() failed */
1457 #ifdef DEBUG
1458     (void) fprintf(stderr, "faketime problem: original clock_gettime() not found.\n");
1459 #endif
1460     return -1; /* propagate error to caller */
1461   }
1462 
1463   /* initialize our result with the real current time */
1464   DONT_FAKE_TIME(result = (*real_clock_gettime)(clk_id, tp));
1465   if (result == -1) return result; /* original function failed */
1466 
1467   /* pass the real current time to our faking version, overwriting it */
1468   if (fake_monotonic_clock || clk_id != CLOCK_MONOTONIC)
1469   {
1470     result = fake_clock_gettime(clk_id, tp);
1471   }
1472 
1473   /* return the result to the caller */
1474   return result;
1475 }
1476 
1477 
1478 /*
1479  *      =======================================================================
1480  *      Parsing the user's faketime requests                          === PARSE
1481  *      =======================================================================
1482  */
1483 
parse_ft_string(const char * user_faked_time)1484 static void parse_ft_string(const char *user_faked_time)
1485 {
1486   struct tm user_faked_time_tm;
1487   char * tmp_time_fmt;
1488 
1489   if (!strncmp(user_faked_time, user_faked_time_saved, BUFFERLEN))
1490   {
1491       /* No change */
1492       return;
1493   }
1494 
1495   /* check whether the user gave us an absolute time to fake */
1496   switch (user_faked_time[0])
1497   {
1498 
1499     default:  /* Try and interpret this as a specified time */
1500       if (ft_mode != FT_NOOP) ft_mode = FT_FREEZE;
1501       user_faked_time_tm.tm_isdst = -1;
1502       if (NULL != strptime(user_faked_time, user_faked_time_fmt, &user_faked_time_tm))
1503       {
1504         user_faked_time_timespec.tv_sec = mktime(&user_faked_time_tm);
1505         user_faked_time_timespec.tv_nsec = 0;
1506         user_faked_time_set = true;
1507       }
1508       else
1509       {
1510         perror("Failed to parse FAKETIME timestamp");
1511         exit(EXIT_FAILURE);
1512       }
1513       break;
1514 
1515     case '+':
1516     case '-': /* User-specified offset */
1517       if (ft_mode != FT_NOOP) ft_mode = FT_START_AT;
1518       /* fractional time offsets contributed by Karl Chen in v0.8 */
1519       double frac_offset = atof(user_faked_time);
1520 
1521       /* offset is in seconds by default, but the string may contain
1522        * multipliers...
1523        */
1524       if (strchr(user_faked_time, 'm') != NULL) frac_offset *= 60;
1525       else if (strchr(user_faked_time, 'h') != NULL) frac_offset *= 60 * 60;
1526       else if (strchr(user_faked_time, 'd') != NULL) frac_offset *= 60 * 60 * 24;
1527       else if (strchr(user_faked_time, 'y') != NULL) frac_offset *= 60 * 60 * 24 * 365;
1528 
1529       user_offset.tv_sec = floor(frac_offset);
1530       user_offset.tv_nsec = (frac_offset - user_offset.tv_sec) * SEC_TO_nSEC;
1531       timespecadd(&ftpl_starttime.real, &user_offset, &user_faked_time_timespec);
1532       goto parse_modifiers;
1533       break;
1534 
1535       /* Contributed by David North, TDI in version 0.7 */
1536     case '@': /* Specific time, but clock along relative to that starttime */
1537       ft_mode = FT_START_AT;
1538       user_faked_time_tm.tm_isdst = -1;
1539       (void) strptime(&user_faked_time[1], user_faked_time_fmt, &user_faked_time_tm);
1540 
1541       user_faked_time_timespec.tv_sec = mktime(&user_faked_time_tm);
1542       user_faked_time_timespec.tv_nsec = 0;
1543 
1544       /* Reset starttime */
1545       system_time_from_system(&ftpl_starttime);
1546       goto parse_modifiers;
1547       break;
1548 
1549     case 'i':
1550     case 'x': /* Only modifiers are passed, don't fall back to strptime */
1551 parse_modifiers:
1552       /* Speed-up / slow-down contributed by Karl Chen in v0.8 */
1553       if (strchr(user_faked_time, 'x') != NULL)
1554       {
1555         user_rate = atof(strchr(user_faked_time, 'x')+1);
1556         user_rate_set = true;
1557       }
1558       else if (NULL != (tmp_time_fmt = strchr(user_faked_time, 'i')))
1559       {
1560         double tick_inc = atof(tmp_time_fmt + 1);
1561         /* increment time with every time() call*/
1562         user_per_tick_inc.tv_sec = floor(tick_inc);
1563         user_per_tick_inc.tv_nsec = (tick_inc - user_per_tick_inc.tv_sec) * SEC_TO_nSEC ;
1564         user_per_tick_inc_set = true;
1565       }
1566       break;
1567   } // end of switch
1568 
1569   strncpy(user_faked_time_saved, user_faked_time, BUFFERLEN-1);
1570   user_faked_time_saved[BUFFERLEN-1] = 0;
1571 #ifdef DEBUG
1572   fprintf(stderr, "new FAKETIME: %s\n", user_faked_time_saved);
1573 #endif
1574 }
1575 
1576 
1577 /*
1578  *      =======================================================================
1579  *      Initialization                                                 === INIT
1580  *      =======================================================================
1581  */
1582 
ftpl_init(void)1583 void ftpl_init(void)
1584 {
1585   char *tmp_env;
1586   bool dont_fake_final;
1587 
1588 #ifdef __APPLE__
1589   const char *progname = getprogname();
1590 #else
1591   const char *progname = __progname;
1592 #endif
1593 
1594   /* Look up all real_* functions. NULL will mark missing ones. */
1595   real_stat =               dlsym(RTLD_NEXT, "__xstat");
1596   real_fstat =              dlsym(RTLD_NEXT, "__fxstat");
1597   real_fstatat =            dlsym(RTLD_NEXT, "__fxstatat");
1598   real_lstat =              dlsym(RTLD_NEXT, "__lxstat");
1599   real_stat64 =             dlsym(RTLD_NEXT,"__xstat64");
1600   real_fstat64 =            dlsym(RTLD_NEXT, "__fxstat64");
1601   real_fstatat64 =          dlsym(RTLD_NEXT, "__fxstatat64");
1602   real_lstat64 =            dlsym(RTLD_NEXT, "__lxstat64");
1603   real_time =               dlsym(RTLD_NEXT, "time");
1604   real_ftime =              dlsym(RTLD_NEXT, "ftime");
1605   real_gettimeofday =       dlsym(RTLD_NEXT, "gettimeofday");
1606 #ifdef FAKE_SLEEP
1607   real_nanosleep =          dlsym(RTLD_NEXT, "nanosleep");
1608   real_usleep =             dlsym(RTLD_NEXT, "usleep");
1609   real_sleep =              dlsym(RTLD_NEXT, "sleep");
1610   real_alarm =              dlsym(RTLD_NEXT, "alarm");
1611   real_poll =               dlsym(RTLD_NEXT, "poll");
1612   real_ppoll =              dlsym(RTLD_NEXT, "ppoll");
1613   real_sem_timedwait =      dlsym(RTLD_NEXT, "sem_timedwait");
1614 #endif
1615 #ifdef FAKE_INTERNAL_CALLS
1616   real___ftime =              dlsym(RTLD_NEXT, "__ftime");
1617   real___gettimeofday =       dlsym(RTLD_NEXT, "__gettimeofday");
1618   real___clock_gettime  =     dlsym(RTLD_NEXT, "__clock_gettime");
1619 #endif
1620 #ifdef __APPLE__
1621   real_clock_get_time =     dlsym(RTLD_NEXT, "clock_get_time");
1622   real_clock_gettime  =     apple_clock_gettime;
1623 #else
1624   real_clock_gettime  =     dlsym(RTLD_NEXT, "__clock_gettime");
1625   if (NULL == real_clock_gettime)
1626   {
1627     real_clock_gettime  =   dlsym(RTLD_NEXT, "clock_gettime");
1628   }
1629 #ifdef FAKE_TIMERS
1630 #if defined(__sun)
1631     real_timer_gettime_233 =  dlsym(RTLD_NEXT, "timer_gettime");
1632     real_timer_settime_233 =  dlsym(RTLD_NEXT, "timer_settime");
1633 #else
1634   real_timer_settime_22 =   dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.2");
1635   real_timer_settime_233 =  dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.3.3");
1636   if (NULL == real_timer_settime_233)
1637   {
1638     real_timer_settime_233 =  dlsym(RTLD_NEXT, "timer_settime");
1639   }
1640   real_timer_gettime_22 =   dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.2");
1641   real_timer_gettime_233 =  dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.3.3");
1642   if (NULL == real_timer_gettime_233)
1643   {
1644     real_timer_gettime_233 =  dlsym(RTLD_NEXT, "timer_gettime");
1645   }
1646 #endif
1647 #endif
1648 #endif
1649 
1650   dont_fake = true; // Do not fake times during initialization
1651   dont_fake_final = false;
1652   initialized = 1;
1653 
1654   ft_shm_init();
1655 #ifdef FAKE_STAT
1656   if (getenv("NO_FAKE_STAT")!=NULL)
1657   {
1658     fake_stat_disabled = 1;  //Note that this is NOT re-checked
1659   }
1660 #endif
1661 
1662   if ((tmp_env = getenv("FAKETIME_CACHE_DURATION")) != NULL)
1663   {
1664     cache_duration = atoi(tmp_env);
1665   }
1666   if ((tmp_env = getenv("FAKETIME_NO_CACHE")) != NULL)
1667   {
1668     if (0 == strcmp(tmp_env, "1"))
1669     {
1670       cache_enabled = 0;
1671     }
1672   }
1673   if ((tmp_env = getenv("DONT_FAKE_MONOTONIC")) != NULL)
1674   {
1675     if (0 == strcmp(tmp_env, "1"))
1676     {
1677       fake_monotonic_clock = 0;
1678     }
1679   }
1680   /* Check whether we actually should be faking the returned timestamp. */
1681 
1682   /* We can prevent faking time for specified commands */
1683   if ((tmp_env = getenv("FAKETIME_SKIP_CMDS")) != NULL)
1684   {
1685     char *skip_cmd, *saveptr, *tmpvar;
1686     /* Don't mess with the env variable directly. */
1687     tmpvar = strdup(tmp_env);
1688     if (tmpvar != NULL)
1689     {
1690       skip_cmd = strtok_r(tmpvar, ",", &saveptr);
1691       while (skip_cmd != NULL)
1692       {
1693         if (0 == strcmp(progname, skip_cmd))
1694         {
1695           ft_mode = FT_NOOP;
1696           dont_fake_final = true;
1697           break;
1698         }
1699         skip_cmd = strtok_r(NULL, ",", &saveptr);
1700       }
1701       free(tmpvar);
1702       tmpvar = NULL;
1703     }
1704     else
1705     {
1706       fprintf(stderr, "Error: Could not copy the environment variable value.\n");
1707       exit(EXIT_FAILURE);
1708     }
1709   }
1710 
1711   /* We can limit faking time to specified commands */
1712   if ((tmp_env = getenv("FAKETIME_ONLY_CMDS")) != NULL)
1713   {
1714     char *only_cmd, *saveptr, *tmpvar;
1715     bool cmd_matched = false;
1716 
1717     if (getenv("FAKETIME_SKIP_CMDS") != NULL)
1718     {
1719       fprintf(stderr, "Error: Both FAKETIME_SKIP_CMDS and FAKETIME_ONLY_CMDS can't be set.\n");
1720       exit(EXIT_FAILURE);
1721     }
1722 
1723     /* Don't mess with the env variable directly. */
1724     tmpvar = strdup(tmp_env);
1725     if (tmpvar != NULL) {
1726       only_cmd = strtok_r(tmpvar, ",", &saveptr);
1727       while (only_cmd != NULL)
1728       {
1729         if (0 == strcmp(progname, only_cmd))
1730         {
1731           cmd_matched = true;
1732           break;
1733         }
1734         only_cmd = strtok_r(NULL, ",", &saveptr);
1735       }
1736 
1737       if (!cmd_matched)
1738       {
1739         ft_mode = FT_NOOP;
1740         dont_fake_final = true;
1741       }
1742       free(tmpvar);
1743     } else {
1744       fprintf(stderr, "Error: Could not copy the environment variable value.\n");
1745       exit(EXIT_FAILURE);
1746     }
1747   }
1748 
1749   if ((tmp_env = getenv("FAKETIME_START_AFTER_SECONDS")) != NULL)
1750   {
1751     ft_start_after_secs = atol(tmp_env);
1752     limited_faking = true;
1753   }
1754   if ((tmp_env = getenv("FAKETIME_STOP_AFTER_SECONDS")) != NULL)
1755   {
1756     ft_stop_after_secs = atol(tmp_env);
1757     limited_faking = true;
1758   }
1759   if ((tmp_env = getenv("FAKETIME_START_AFTER_NUMCALLS")) != NULL)
1760   {
1761     ft_start_after_ncalls = atol(tmp_env);
1762     limited_faking = true;
1763   }
1764   if ((tmp_env = getenv("FAKETIME_STOP_AFTER_NUMCALLS")) != NULL)
1765   {
1766     ft_stop_after_ncalls = atol(tmp_env);
1767     limited_faking = true;
1768   }
1769 
1770   /* check whether we should spawn an external command */
1771   if ((tmp_env = getenv("FAKETIME_SPAWN_TARGET")) != NULL)
1772   {
1773     spawnsupport = true;
1774     (void) strncpy(ft_spawn_target, getenv("FAKETIME_SPAWN_TARGET"), 1024);
1775     if ((tmp_env = getenv("FAKETIME_SPAWN_SECONDS")) != NULL)
1776     {
1777       ft_spawn_secs = atol(tmp_env);
1778     }
1779     if ((tmp_env = getenv("FAKETIME_SPAWN_NUMCALLS")) != NULL)
1780     {
1781       ft_spawn_ncalls = atol(tmp_env);
1782     }
1783   }
1784 
1785   if ((tmp_env = getenv("FAKETIME_SAVE_FILE")) != NULL)
1786   {
1787     if (-1 == (outfile = open(tmp_env, O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT,
1788                               S_IWUSR | S_IRUSR)))
1789     {
1790       perror("Opening file for saving timestamps failed");
1791       exit(EXIT_FAILURE);
1792     }
1793   }
1794 
1795   /* load file only if reading timstamps from it is not finished yet */
1796   if ((tmp_env = getenv("FAKETIME_LOAD_FILE")) != NULL)
1797   {
1798     int infile = -1;
1799     struct stat sb;
1800     if (-1 == (infile = open(tmp_env, O_RDONLY|O_CLOEXEC)))
1801     {
1802       perror("Opening file for loading timestamps failed");
1803       exit(EXIT_FAILURE);
1804     }
1805 
1806     fstat(infile, &sb);
1807     if (sizeof(stss[0]) > (infile_size = sb.st_size))
1808     {
1809       printf("There are no timestamps in the provided file to load timestamps from");
1810       exit(EXIT_FAILURE);
1811     }
1812 
1813     if ((infile_size % sizeof(stss[0])) != 0)
1814     {
1815       printf("File size is not multiple of timestamp size. It is probably damaged.");
1816       exit(EXIT_FAILURE);
1817     }
1818 
1819     stss = mmap(NULL, infile_size, PROT_READ, MAP_SHARED, infile, 0);
1820     if (stss == MAP_FAILED)
1821     {
1822       perror("Mapping file for loading timestamps failed");
1823       exit(EXIT_FAILURE);
1824     }
1825     infile_set = true;
1826   }
1827 
1828   tmp_env = getenv("FAKETIME_FMT");
1829   if (tmp_env == NULL)
1830   {
1831     strcpy(user_faked_time_fmt, "%Y-%m-%d %T");
1832   }
1833   else
1834   {
1835     strncpy(user_faked_time_fmt, tmp_env, BUFSIZ);
1836   }
1837 
1838   if (shared_sem != 0)
1839   {
1840     if (sem_wait(shared_sem) == -1)
1841     {
1842       perror("sem_wait");
1843       exit(1);
1844     }
1845     if (ft_shared->start_time.real.tv_nsec == -1)
1846     {
1847       /* set up global start time */
1848       system_time_from_system(&ftpl_starttime);
1849       ft_shared->start_time = ftpl_starttime;
1850     }
1851     else
1852     {
1853       /** get preset start time */
1854       ftpl_starttime = ft_shared->start_time;
1855     }
1856     if (sem_post(shared_sem) == -1)
1857     {
1858       perror("sem_post");
1859       exit(1);
1860     }
1861   }
1862   else
1863   {
1864     system_time_from_system(&ftpl_starttime);
1865   }
1866   /* fake time supplied as environment variable? */
1867   if (NULL != (tmp_env = getenv("FAKETIME")))
1868   {
1869     parse_config_file = false;
1870     parse_ft_string(tmp_env);
1871   }
1872 
1873   dont_fake = dont_fake_final;
1874 }
1875 
1876 
1877 /*
1878  *      =======================================================================
1879  *      Helper functions                                             === HELPER
1880  *      =======================================================================
1881  */
1882 
remove_trailing_eols(char * line)1883 static void remove_trailing_eols(char *line)
1884 {
1885   char *endp = line + strlen(line);
1886   /*
1887    * erase the last char if it's a newline
1888    * or carriage return, and back up.
1889    * keep doing this, but don't back up
1890    * past the beginning of the string.
1891    */
1892 # define is_eolchar(c) ((c) == '\n' || (c) == '\r')
1893   while (endp > line && is_eolchar(endp[-1]))
1894   {
1895     *--endp = '\0';
1896   }
1897 }
1898 
1899 
1900 /*
1901  *      =======================================================================
1902  *      Implementation of faked functions                        === FAKE(FAKE)
1903  *      =======================================================================
1904  */
1905 
fake_clock_gettime(clockid_t clk_id,struct timespec * tp)1906 int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
1907 {
1908   /* variables used for caching, introduced in version 0.6 */
1909   static time_t last_data_fetch = 0;  /* not fetched previously at first call */
1910   static int cache_expired = 1;       /* considered expired at first call */
1911 
1912   if (dont_fake) return 0;
1913   /* Per process timers are only sped up or slowed down */
1914   if ((clk_id == CLOCK_PROCESS_CPUTIME_ID ) || (clk_id == CLOCK_THREAD_CPUTIME_ID))
1915   {
1916     if (user_rate_set)
1917     {
1918       timespecmul(tp, user_rate, tp);
1919     }
1920     return 0;
1921   }
1922 
1923   /* Sanity check by Karl Chan since v0.8 */
1924   if (tp == NULL) return -1;
1925 
1926 #ifdef PTHREAD_SINGLETHREADED_TIME
1927   static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
1928   pthread_mutex_lock(&time_mutex);
1929   pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, (void *)&time_mutex);
1930 #endif
1931 
1932   if ((limited_faking &&
1933      ((ft_start_after_ncalls != -1) || (ft_stop_after_ncalls != -1))) ||
1934      (spawnsupport && ft_spawn_ncalls))
1935   {
1936     if (callcounter < LONG_MAX) callcounter++;
1937   }
1938 
1939   if (limited_faking || spawnsupport)
1940   {
1941     struct timespec tmp_ts;
1942     /* For debugging, output #seconds and #calls */
1943     switch (clk_id)
1944     {
1945       case CLOCK_REALTIME:
1946 #ifdef CLOCK_REALTIME_COARSE
1947       case CLOCK_REALTIME_COARSE:
1948 #endif
1949         timespecsub(tp, &ftpl_starttime.real, &tmp_ts);
1950         break;
1951       case CLOCK_MONOTONIC:
1952 #ifdef CLOCK_MONOTONIC_COARSE
1953       case CLOCK_MONOTONIC_COARSE:
1954 #endif
1955         timespecsub(tp, &ftpl_starttime.mon, &tmp_ts);
1956         break;
1957       case CLOCK_MONOTONIC_RAW:
1958         timespecsub(tp, &ftpl_starttime.mon_raw, &tmp_ts);
1959         break;
1960       default:
1961         printf("Invalid clock_id for clock_gettime: %d", clk_id);
1962         exit(EXIT_FAILURE);
1963     }
1964 
1965     if (limited_faking)
1966     {
1967       /* Check whether we actually should be faking the returned timestamp. */
1968       /* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu\n", (*time_tptr - ftpl_starttime), callcounter); */
1969       if ((ft_start_after_secs != -1)   && (tmp_ts.tv_sec < ft_start_after_secs)) return 0;
1970       if ((ft_stop_after_secs != -1)    && (tmp_ts.tv_sec >= ft_stop_after_secs)) return 0;
1971       if ((ft_start_after_ncalls != -1) && (callcounter < ft_start_after_ncalls)) return 0;
1972       if ((ft_stop_after_ncalls != -1)  && (callcounter >= ft_stop_after_ncalls)) return 0;
1973       /* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu continues\n", (*time_tptr - ftpl_starttime), callcounter); */
1974     }
1975 
1976     if (spawnsupport)
1977     {
1978       /* check whether we should spawn an external command */
1979       if (spawned == 0)
1980       { /* exec external command once only */
1981         if (((tmp_ts.tv_sec == ft_spawn_secs) || (callcounter == ft_spawn_ncalls)) && (spawned == 0))
1982         {
1983           spawned = 1;
1984           (void) (system(ft_spawn_target) + 1);
1985         }
1986       }
1987     }
1988   }
1989 
1990   if (last_data_fetch > 0)
1991   {
1992     if ((tp->tv_sec - last_data_fetch) > cache_duration)
1993     {
1994       cache_expired = 1;
1995     }
1996     else
1997     {
1998       cache_expired = 0;
1999     }
2000   }
2001 
2002   if (cache_enabled == 0)
2003   {
2004     cache_expired = 1;
2005   }
2006 
2007   if (cache_expired == 1)
2008   {
2009     static char user_faked_time[BUFFERLEN]; /* changed to static for caching in v0.6 */
2010     /* initialize with default or env. variable */
2011     char *tmp_env;
2012 
2013     /* Can be enabled for testing ...
2014       fprintf(stderr, "***************++ Cache expired ++**************\n");
2015     */
2016 
2017     if (NULL != (tmp_env = getenv("FAKETIME")))
2018     {
2019       strncpy(user_faked_time, tmp_env, BUFFERLEN);
2020     }
2021     else
2022     {
2023       snprintf(user_faked_time, BUFFERLEN, "+0");
2024     }
2025 
2026     last_data_fetch = tp->tv_sec;
2027     /* fake time supplied as environment variable? */
2028     if (parse_config_file)
2029     {
2030       char custom_filename[BUFSIZ];
2031       char filename[BUFSIZ];
2032       FILE *faketimerc;
2033       /* check whether there's a .faketimerc in the user's home directory, or
2034        * a system-wide /etc/faketimerc present.
2035        * The /etc/faketimerc handling has been contributed by David Burley,
2036        * Jacob Moorman, and Wayne Davison of SourceForge, Inc. in version 0.6 */
2037       (void) snprintf(custom_filename, BUFSIZ, "%s", getenv("FAKETIME_TIMESTAMP_FILE"));
2038       (void) snprintf(filename, BUFSIZ, "%s/.faketimerc", getenv("HOME"));
2039       if ((faketimerc = fopen(custom_filename, "rt")) != NULL ||
2040           (faketimerc = fopen(filename, "rt")) != NULL ||
2041           (faketimerc = fopen("/etc/faketimerc", "rt")) != NULL)
2042       {
2043         char line[BUFFERLEN];
2044         while(fgets(line, BUFFERLEN, faketimerc) != NULL)
2045         {
2046           if ((strlen(line) > 1) && (line[0] != ' ') &&
2047               (line[0] != '#') && (line[0] != ';'))
2048           {
2049             remove_trailing_eols(line);
2050             strncpy(user_faked_time, line, BUFFERLEN-1);
2051             user_faked_time[BUFFERLEN-1] = 0;
2052             break;
2053           }
2054         }
2055         fclose(faketimerc);
2056       }
2057     } /* read fake time from file */
2058     parse_ft_string(user_faked_time);
2059   } /* cache had expired */
2060 
2061   if (infile_set)
2062   {
2063     if (load_time(tp))
2064     {
2065       return 0;
2066     }
2067   }
2068 
2069   /* check whether the user gave us an absolute time to fake */
2070   switch (ft_mode)
2071   {
2072     case FT_FREEZE:  /* a specified time */
2073       if (user_faked_time_set)
2074       {
2075         *tp = user_faked_time_timespec;
2076       }
2077       break;
2078 
2079     case FT_START_AT: /* User-specified offset */
2080       if (user_per_tick_inc_set)
2081       {
2082         /* increment time with every time() call*/
2083         next_time(tp, &user_per_tick_inc);
2084       }
2085       else
2086       {
2087         /* Speed-up / slow-down contributed by Karl Chen in v0.8 */
2088         struct timespec tdiff, timeadj;
2089         switch (clk_id)
2090         {
2091           case CLOCK_REALTIME:
2092 #ifdef CLOCK_REALTIME_COARSE
2093           case CLOCK_REALTIME_COARSE:
2094 #endif
2095             timespecsub(tp, &ftpl_starttime.real, &tdiff);
2096             break;
2097           case CLOCK_MONOTONIC:
2098 #ifdef CLOCK_MONOTONIC_COARSE
2099           case CLOCK_MONOTONIC_COARSE:
2100 #endif
2101             timespecsub(tp, &ftpl_starttime.mon, &tdiff);
2102             break;
2103           case CLOCK_MONOTONIC_RAW:
2104             timespecsub(tp, &ftpl_starttime.mon_raw, &tdiff);
2105             break;
2106           default:
2107             printf("Invalid clock_id for clock_gettime: %d", clk_id);
2108             exit(EXIT_FAILURE);
2109         } // end of switch (clk_id)
2110         if (user_rate_set)
2111         {
2112           timespecmul(&tdiff, user_rate, &timeadj);
2113         }
2114         else
2115         {
2116           timeadj = tdiff;
2117         }
2118         timespecadd(&user_faked_time_timespec, &timeadj, tp);
2119       }
2120       break;
2121 
2122     default:
2123       return -1;
2124   } // end of switch(ft_mode)
2125 
2126 #ifdef PTHREAD_SINGLETHREADED_TIME
2127   pthread_cleanup_pop(1);
2128 #endif
2129   save_time(tp);
2130   return 0;
2131 }
2132 
fake_gettimeofday(struct timeval * tv)2133 int fake_gettimeofday(struct timeval *tv)
2134 {
2135   struct timespec ts;
2136   int ret;
2137   ts.tv_sec = tv->tv_sec;
2138   ts.tv_nsec = tv->tv_usec * 1000  + ftpl_starttime.real.tv_nsec % 1000;
2139 
2140   ret = fake_clock_gettime(CLOCK_REALTIME, &ts);
2141   tv->tv_sec = ts.tv_sec;
2142   tv->tv_usec =ts.tv_nsec / 1000;
2143 
2144   return ret;
2145 }
2146 
2147 
2148 /*
2149  *      =======================================================================
2150  *      Faked system functions: Apple Mac OS X specific           === FAKE(OSX)
2151  *      =======================================================================
2152  */
2153 
2154 #ifdef __APPLE__
2155 /*
2156  * clock_gettime implementation for __APPLE__
2157  * @note It always behave like being called with CLOCK_REALTIME.
2158  */
apple_clock_gettime(clockid_t clk_id,struct timespec * tp)2159 static int apple_clock_gettime(clockid_t clk_id, struct timespec *tp)
2160 {
2161   int result;
2162   mach_timespec_t cur_timeclockid_t;
2163   (void) clk_id; /* unused */
2164 
2165   if (NULL == real_clock_get_time)
2166   {  /* dlsym() failed */
2167 #ifdef DEBUG
2168     (void) fprintf(stderr, "faketime problem: original clock_get_time() not found.\n");
2169 #endif
2170     return -1; /* propagate error to caller */
2171   }
2172 
2173   DONT_FAKE_TIME(result = (*real_clock_get_time)(clock_serv_real, &cur_timeclockid_t));
2174   tp->tv_sec =  cur_timeclockid_t.tv_sec;
2175   tp->tv_nsec = cur_timeclockid_t.tv_nsec;
2176   return result;
2177 }
2178 
clock_get_time(clock_serv_t clock_serv,mach_timespec_t * cur_timeclockid_t)2179 int clock_get_time(clock_serv_t clock_serv, mach_timespec_t *cur_timeclockid_t)
2180 {
2181   int result;
2182   struct timespec ts;
2183 
2184   /*
2185    * Initialize our result with the real current time from CALENDAR_CLOCK.
2186    * This is a bit of cheating, but we don't keep track of obtained clock
2187    * services.
2188    */
2189   DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &ts));
2190   if (result == -1) return result; /* original function failed */
2191 
2192   /* pass the real current time to our faking version, overwriting it */
2193   result = fake_clock_gettime(CLOCK_REALTIME, &ts);
2194   cur_timeclockid_t->tv_sec = ts.tv_sec;
2195   cur_timeclockid_t->tv_nsec = ts.tv_nsec;
2196 
2197   /* return the result to the caller */
2198   return result;
2199 }
2200 #endif
2201 
2202 
2203 /*
2204  *      =======================================================================
2205  *      Faked system-internal functions                           === FAKE(INT)
2206  *      =======================================================================
2207  */
2208 
2209 #ifdef FAKE_INTERNAL_CALLS
__gettimeofday(struct timeval * tv,void * tz)2210 int __gettimeofday(struct timeval *tv, void *tz)
2211 {
2212   int result;
2213 
2214   /* sanity check */
2215   if (tv == NULL)
2216   {
2217     return -1;
2218   }
2219 
2220   /* Check whether we've got a pointer to the real ftime() function yet */
2221   if (NULL == real___gettimeofday)
2222   {  /* dlsym() failed */
2223 #ifdef DEBUG
2224     (void) fprintf(stderr, "faketime problem: original __gettimeofday() not found.\n");
2225 #endif
2226     return -1; /* propagate error to caller */
2227   }
2228 
2229   /* initialize our result with the real current time */
2230   DONT_FAKE_TIME(result = (*real___gettimeofday)(tv, tz));
2231   if (result == -1) return result; /* original function failed */
2232 
2233   /* pass the real current time to our faking version, overwriting it */
2234   result = fake_gettimeofday(tv);
2235 
2236   /* return the result to the caller */
2237   return result;
2238 }
2239 
__clock_gettime(clockid_t clk_id,struct timespec * tp)2240 int __clock_gettime(clockid_t clk_id, struct timespec *tp)
2241 {
2242   int result;
2243 
2244   /* sanity check */
2245   if (tp == NULL)
2246   {
2247     return -1;
2248   }
2249 
2250   if (NULL == real___clock_gettime)
2251   {  /* dlsym() failed */
2252 #ifdef DEBUG
2253     (void) fprintf(stderr, "faketime problem: original __clock_gettime() not found.\n");
2254 #endif
2255     return -1; /* propagate error to caller */
2256   }
2257 
2258   /* initialize our result with the real current time */
2259   DONT_FAKE_TIME(result = (*real___clock_gettime)(clk_id, tp));
2260   if (result == -1) return result; /* original function failed */
2261 
2262   /* pass the real current time to our faking version, overwriting it */
2263   if (fake_monotonic_clock || clk_id != CLOCK_MONOTONIC)
2264   {
2265     result = fake_clock_gettime(clk_id, tp);
2266   }
2267 
2268   /* return the result to the caller */
2269   return result;
2270 }
2271 
__time(time_t * time_tptr)2272 time_t __time(time_t *time_tptr)
2273 {
2274   struct timespec tp;
2275   time_t result;
2276 
2277   DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
2278   if (result == -1) return -1;
2279 
2280   /* pass the real current time to our faking version, overwriting it */
2281   (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
2282 
2283   if (time_tptr != NULL)
2284   {
2285     *time_tptr = tp.tv_sec;
2286   }
2287   return tp.tv_sec;
2288 }
2289 
__ftime(struct timeb * tb)2290 int __ftime(struct timeb *tb)
2291 {
2292   struct timespec tp;
2293   int result;
2294 
2295   /* sanity check */
2296   if (tb == NULL)
2297     return 0;               /* ftime() always returns 0, see manpage */
2298 
2299   /* Check whether we've got a pointer to the real ftime() function yet */
2300   if (NULL == real___ftime)
2301   {  /* dlsym() failed */
2302 #ifdef DEBUG
2303     (void) fprintf(stderr, "faketime problem: original ftime() not found.\n");
2304 #endif
2305     return 0; /* propagate error to caller */
2306   }
2307 
2308   /* initialize our TZ result with the real current time */
2309   DONT_FAKE_TIME(result = (*real___ftime)(tb));
2310   if (result == -1)
2311   {
2312     return result;
2313   }
2314 
2315   DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
2316   if (result == -1) return -1;
2317 
2318   /* pass the real current time to our faking version, overwriting it */
2319   (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
2320 
2321   tb->time = tp.tv_sec;
2322   tb->millitm = tp.tv_nsec / 1000000;
2323 
2324   /* return the result to the caller */
2325   return result; /* will always be 0 (see manpage) */
2326 }
2327 
2328 #endif
2329 
2330 /*
2331  * Editor modelines
2332  *
2333  * Local variables:
2334  * c-basic-offset: 2
2335  * tab-width: 2
2336  * indent-tabs-mode: nil
2337  * End:
2338  *
2339  * vi: set shiftwidth=2 tabstop=2 expandtab:
2340  * :indentSize=2:tabSize=2:noTabs=true:
2341  */
2342 
2343 /* eof */
2344