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