bootstrap
[wayback.git] / libvmtime.c
1 #include <sys/time.h>
2 #include <dlfcn.h>
3 #include <sys/timeb.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <pthread.h>
8
9
10 typedef int (*gettimeofday_func_t)(struct timeval *tv, struct timezone *tz);
11 static gettimeofday_func_t gettimeofday_orig;
12
13 typedef time_t (*time_func_t)(time_t *t);
14 static time_func_t time_orig;
15
16 typedef int (*ftime_func_t)(struct timeb *tp);
17 static ftime_func_t ftime_orig;
18
19 static time_t wayback=0;
20
21
22 static int inside=0;
23 static pthread_mutex_t inside_mutex=PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
24
25 static void enter(void)
26 {
27 static int done=0;
28 void *libc_handle;
29 char *wayback_s;
30
31         if (pthread_mutex_lock(&inside_mutex)) {
32                 fprintf(stderr,"libwayback: 'inside_mutex' lock fail!\n");
33                 _exit(1);
34                 }
35         if (inside<0) {
36                 fprintf(stderr,"libwayback: 'inside' sanity fail!\n");
37                 _exit(1);
38                 }
39         if (inside) {
40                 fprintf(stderr,"libwayback: looping!\n");
41                 _exit(1);
42                 }
43         inside++;
44
45         if (done)
46                 return;
47         done=1;
48
49         if ((wayback_s=getenv("WAYBACK")))
50                 wayback=atol(wayback_s);
51
52         libc_handle=dlopen("/lib/libc.so.6",RTLD_LAZY); /* RTLD_LAZY is mandatory */
53         gettimeofday_orig=(gettimeofday_func_t)dlsym(libc_handle,"gettimeofday");
54         time_orig=(time_func_t)dlsym(libc_handle,"time");
55         ftime_orig=(ftime_func_t)dlsym(libc_handle,"ftime");
56 }
57
58 static void leave(void)
59 {
60         if (inside!=1) {
61                 fprintf(stderr,"libwayback: 'inside' sanity fail!\n");
62                 _exit(1);
63                 }
64         inside--;
65         if (pthread_mutex_unlock(&inside_mutex)) {
66                 fprintf(stderr,"libwayback: 'inside_mutex' unlock fail!\n");
67                 _exit(1);
68                 }
69 }
70
71
72 int gettimeofday(struct timeval *tv, struct timezone *tz)
73 {
74 int r;
75
76         enter();
77
78         r=(*gettimeofday_orig)(tv,tz);
79         if (tv)
80                 tv->tv_sec-=wayback;
81
82         leave();
83
84         return r;
85 }
86
87
88 time_t time(time_t *t)
89 {
90 time_t r;
91
92         enter();
93         r=(*time_orig)(t);
94
95         if (t)
96                 *t-=wayback;
97         r-=wayback;
98
99         leave();
100         return r;
101 }
102
103
104 int ftime(struct timeb *tp)
105 {
106 int r;
107
108         enter();
109         r=(*ftime_orig)(tp);
110         
111         if (tp)
112                 tp->time-=wayback;
113
114         leave();
115         return r;
116 }