summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile9
-rw-r--r--src/Makefile.OSX2
-rw-r--r--src/libfaketime.c254
-rw-r--r--src/libfaketime.map10
4 files changed, 208 insertions, 67 deletions
diff --git a/src/Makefile b/src/Makefile
index d4d5be2..2ae30bd 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -50,9 +50,9 @@ INSTALL ?= install
PREFIX ?= /usr/local
-CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"'
+CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"'
LIB_LDFLAGS += -shared
-LDFLAGS += -lrt
+LDFLAGS += -lrt -Wl,--version-script=libfaketime.map
LDADD += -ldl -lm -lpthread
SRC = libfaketime.c
@@ -69,9 +69,12 @@ faketimeMT.o: EXTRA_FLAGS := -DPTHREAD -DPTHREAD_SINGLETHREADED_TIME
${LIBS_OBJ}: libfaketime.c
${CC} -o $@ -c ${CFLAGS} ${EXTRA_FLAGS} $<
-%.so.${SONAME}: %.o
+%.so.${SONAME}: %.o libfaketime.map
${CC} -o $@ -Wl,-soname,$@ ${LDFLAGS} ${LIB_LDFLAGS} $< ${LDADD}
+${BINS}: faketime.c
+ ${CC} -o $@ -c ${CFLAGS} ${EXTRA_FLAGS} $<
+
clean:
@rm -f ${LIBS_OBJ} ${LIBS} ${BINS}
diff --git a/src/Makefile.OSX b/src/Makefile.OSX
index f3a0ceb..8b414c4 100644
--- a/src/Makefile.OSX
+++ b/src/Makefile.OSX
@@ -48,7 +48,7 @@ PREFIX ?= /usr/local
# 10.5
#CFLAGS = -dynamiclib -arch i386 -arch ppc
# 10.6
-CFLAGS = -dynamiclib -DFAKE_SLEEP -arch i386 -arch x86_64 -DPREFIX='"'$(PREFIX)'"'
+CFLAGS = -dynamiclib -DFAKE_SLEEP -DFAKE_TIMERS -arch i386 -arch x86_64 -DPREFIX='"'$(PREFIX)'"'
LIB_SRC = libfaketime.c
SONAME = 1
diff --git a/src/libfaketime.c b/src/libfaketime.c
index 4cadc64..a26e22f 100644
--- a/src/libfaketime.c
+++ b/src/libfaketime.c
@@ -118,9 +118,15 @@ static int (*real_gettimeofday) (struct timeval *, void *);
static int (*real_clock_gettime) (clockid_t clk_id, struct timespec *tp);
#ifndef __APPLE__
#ifdef FAKE_TIMERS
-static int (*real_timer_settime) (timer_t timerid, int flags, const struct itimerspec *new_value,
- struct itimerspec * old_value);
-static int (*real_timer_gettime) (timer_t timerid, struct itimerspec *curr_value);
+static int (*real_timer_settime_22) (int timerid, int flags, const struct itimerspec *new_value,
+ struct itimerspec * old_value);
+static int (*real_timer_settime_233) (timer_t timerid, int flags,
+ const struct itimerspec *new_value,
+ struct itimerspec * old_value);
+static int (*real_timer_gettime_22) (int timerid,
+ struct itimerspec *curr_value);
+static int (*real_timer_gettime_233) (timer_t timerid,
+ struct itimerspec *curr_value);
#endif
#endif
#ifdef FAKE_SLEEP
@@ -923,21 +929,31 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout)
#ifndef __APPLE__
#ifdef FAKE_TIMERS
+
+/* timer related functions and structures */
+typedef union {
+ int int_member;
+ timer_t timer_t_member;
+} timer_t_or_int;
+
+/*
+ * Faketime's function implementation's compatibility mode
+ */
+typedef enum {FT_COMPAT_GLIBC_2_2, FT_COMPAT_GLIBC_2_3_3} ft_lib_compat;
+
+
/*
* Faked timer_settime()
* Does not affect timer speed when stepping clock with each time() call.
*/
-int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value,
- struct itimerspec *old_value)
+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)
{
int result;
- struct itimerspec new_real, old_real;
- struct itimerspec *new_real_pt = &new_real, *old_real_pt = &old_real;
-
- if (real_timer_settime == NULL)
- {
- return -1;
- }
+ struct itimerspec new_real;
+ struct itimerspec *new_real_pt = &new_real;
if (new_value == NULL)
{
@@ -950,40 +966,63 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value
}
else
{
- // TODO fake
- struct timespec tdiff, timeadj;
- timespecsub(&new_value->it_value, &user_faked_time_timespec, &timeadj);
- if (user_rate_set)
+ /* set it_value */
+ if ((new_value->it_value.tv_sec != 0) ||
+ (new_value->it_value.tv_nsec != 0))
{
- timespecmul(&timeadj, 1.0/user_rate, &tdiff);
+ if (flags & TIMER_ABSTIME)
+ {
+ struct timespec tdiff, timeadj;
+ timespecsub(&new_value->it_value, &user_faked_time_timespec, &timeadj);
+ if (user_rate_set)
+ {
+ timespecmul(&timeadj, 1.0/user_rate, &tdiff);
+ }
+ else
+ {
+ tdiff = timeadj;
+ }
+ /* only CLOCK_REALTIME is handled */
+ timespecadd(&ftpl_starttime.real, &tdiff, &new_real.it_value);
+ }
+ else
+ {
+ if (user_rate_set)
+ {
+ timespecmul(&new_value->it_value, 1.0/user_rate, &new_real.it_value);
+ }
+ else
+ {
+ new_real.it_value = new_value->it_value;
+ }
+ }
}
else
{
- tdiff = timeadj;
+ new_real.it_value = new_value->it_value;
}
- /* only CLOCK_REALTIME is handled */
- timespecadd(&ftpl_starttime.real, &tdiff, &new_real.it_value);
-
- new_real.it_value = new_value->it_value;
- if (user_rate_set)
+ /* set it_interval */
+ if (user_rate_set && ((new_value->it_interval.tv_sec != 0) ||
+ (new_value->it_interval.tv_nsec != 0)))
{
timespecmul(&new_value->it_interval, 1.0/user_rate, &new_real.it_interval);
}
+ else
+ {
+ new_real.it_interval = new_value->it_interval;
+ }
}
- if (old_value == NULL)
- {
- old_real_pt = NULL;
- }
- else if (dont_fake)
- {
- old_real_pt = old_value;
- }
- else
+
+ switch (compat)
{
- old_real = *old_value;
+ case FT_COMPAT_GLIBC_2_2:
+ DONT_FAKE_TIME(result = (*real_timer_settime_22)(timerid.int_member, flags,
+ new_real_pt, old_value));
+ case FT_COMPAT_GLIBC_2_3_3:
+ DONT_FAKE_TIME(result = (*real_timer_settime_233)(timerid.timer_t_member,
+ flags, new_real_pt, old_value));
}
- DONT_FAKE_TIME(result = (*real_timer_settime)(timerid, flags, new_real_pt, old_real_pt));
if (result == -1)
{
return result;
@@ -992,30 +1031,79 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value
/* fake returned parts */
if ((old_value != NULL) && !dont_fake)
{
- result = fake_clock_gettime(CLOCK_REALTIME, &old_real.it_value);
- if (user_rate_set)
+ if ((old_value->it_value.tv_sec != 0) ||
+ (old_value->it_value.tv_nsec != 0))
+ {
+ result = fake_clock_gettime(CLOCK_REALTIME, &old_value->it_value);
+ }
+ if (user_rate_set && ((old_value->it_interval.tv_sec != 0) ||
+ (old_value->it_interval.tv_nsec != 0)))
{
- timespecmul(&old_real.it_interval, user_rate, &old_value->it_interval);
+ timespecmul(&old_value->it_interval, user_rate, &old_value->it_interval);
}
}
+
/* return the result to the caller */
return result;
}
-/**
+/*
+ * Faked timer_settime() compatible with implementation in GLIBC 2.2
+ */
+int timer_settime_22(int timerid, int flags,
+ const struct itimerspec *new_value,
+ struct itimerspec *old_value)
+{
+ if (real_timer_settime_22 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value,
+ FT_COMPAT_GLIBC_2_2));
+ }
+}
+
+/*
+ * Faked timer_settime() compatible with implementation in GLIBC 2.3.3
+ */
+int timer_settime_233(timer_t timerid, int flags,
+ const struct itimerspec *new_value,
+ struct itimerspec *old_value)
+{
+ if (real_timer_settime_233 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value,
+ FT_COMPAT_GLIBC_2_3_3));
+ }
+}
+
+/*
* Faked timer_gettime()
* Does not affect timer speed when stepping clock with each time() call.
*/
-int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
+int timer_gettime_common(timer_t_or_int timerid, struct itimerspec *curr_value, ft_lib_compat compat)
{
int result;
- if (real_timer_gettime == NULL)
+ if (real_timer_gettime_233 == NULL)
{
return -1;
}
- DONT_FAKE_TIME(result = (*real_timer_gettime)(timerid, curr_value));
+ switch (compat)
+ {
+ case FT_COMPAT_GLIBC_2_2:
+ DONT_FAKE_TIME(result = (*real_timer_gettime_22)(timerid.int_member, curr_value));
+ case FT_COMPAT_GLIBC_2_3_3:
+ DONT_FAKE_TIME(result = (*real_timer_gettime_233)(timerid.timer_t_member, curr_value));
+ }
+
if (result == -1)
{
return result;
@@ -1033,6 +1121,44 @@ int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
/* return the result to the caller */
return result;
}
+
+/*
+ * Faked timer_gettime() compatible with implementation in GLIBC 2.2
+ */
+int timer_gettime_22(timer_t timerid, struct itimerspec *curr_value)
+{
+ if (real_timer_gettime_22 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_gettime_common((timer_t_or_int)timerid, curr_value,
+ FT_COMPAT_GLIBC_2_2));
+ }
+}
+
+/*
+ * Faked timer_gettime() compatible with implementation in GLIBC 2.3.3
+ */
+int timer_gettime_233(timer_t timerid, struct itimerspec *curr_value)
+{
+ if (real_timer_gettime_233 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_gettime_common((timer_t_or_int)timerid, curr_value,
+ FT_COMPAT_GLIBC_2_3_3));
+ }
+}
+
+__asm__(".symver timer_gettime_22, timer_gettime@GLIBC_2.2");
+__asm__(".symver timer_gettime_233, timer_gettime@@GLIBC_2.3.3");
+__asm__(".symver timer_settime_22, timer_settime@GLIBC_2.2");
+__asm__(".symver timer_settime_233, timer_settime@@GLIBC_2.3.3");
+
#endif
#endif
@@ -1247,33 +1373,35 @@ void __attribute__ ((constructor)) ftpl_init(void)
char *tmp_env;
/* Look up all real_* functions. NULL will mark missing ones. */
- real_stat = dlsym(RTLD_NEXT, "__xstat");
- real_fstat = dlsym(RTLD_NEXT, "__fxstat");
- real_fstatat = dlsym(RTLD_NEXT, "__fxstatat");
- real_lstat = dlsym(RTLD_NEXT, "__lxstat");
- real_stat64 = dlsym(RTLD_NEXT,"__xstat64");
- real_fstat64 = dlsym(RTLD_NEXT, "__fxstat64");
- real_fstatat64 = dlsym(RTLD_NEXT, "__fxstatat64");
- real_lstat64 = dlsym(RTLD_NEXT, "__lxstat64");
- real_time = dlsym(RTLD_NEXT, "time");
- real_ftime = dlsym(RTLD_NEXT, "ftime");
- real_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");
+ real_stat = dlsym(RTLD_NEXT, "__xstat");
+ real_fstat = dlsym(RTLD_NEXT, "__fxstat");
+ real_fstatat = dlsym(RTLD_NEXT, "__fxstatat");
+ real_lstat = dlsym(RTLD_NEXT, "__lxstat");
+ real_stat64 = dlsym(RTLD_NEXT,"__xstat64");
+ real_fstat64 = dlsym(RTLD_NEXT, "__fxstat64");
+ real_fstatat64 = dlsym(RTLD_NEXT, "__fxstatat64");
+ real_lstat64 = dlsym(RTLD_NEXT, "__lxstat64");
+ real_time = dlsym(RTLD_NEXT, "time");
+ real_ftime = dlsym(RTLD_NEXT, "ftime");
+ real_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");
#ifdef FAKE_SLEEP
- real_nanosleep = dlsym(RTLD_NEXT, "nanosleep");
- real_usleep = dlsym(RTLD_NEXT, "usleep");
- real_sleep = dlsym(RTLD_NEXT, "sleep");
- real_alarm = dlsym(RTLD_NEXT, "alarm");
- real_poll = dlsym(RTLD_NEXT, "poll");
- real_ppoll = dlsym(RTLD_NEXT, "ppoll");
+ real_nanosleep = dlsym(RTLD_NEXT, "nanosleep");
+ real_usleep = dlsym(RTLD_NEXT, "usleep");
+ real_sleep = dlsym(RTLD_NEXT, "sleep");
+ real_alarm = dlsym(RTLD_NEXT, "alarm");
+ real_poll = dlsym(RTLD_NEXT, "poll");
+ real_ppoll = dlsym(RTLD_NEXT, "ppoll");
#endif
#ifdef __APPLE__
- real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time");
- real_clock_gettime = apple_clock_gettime;
+ real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time");
+ real_clock_gettime = apple_clock_gettime;
#else
- real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
+ real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
#ifdef FAKE_TIMERS
- real_timer_settime = dlsym(RTLD_NEXT, "timer_settime");
- real_timer_gettime = dlsym(RTLD_NEXT, "timer_gettime");
+ real_timer_settime_22 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.2");
+ real_timer_settime_233 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.3.3");
+ real_timer_gettime_22 = dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.2");
+ real_timer_gettime_233 = dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.3.3");
#endif
#endif
diff --git a/src/libfaketime.map b/src/libfaketime.map
new file mode 100644
index 0000000..6e008cf
--- /dev/null
+++ b/src/libfaketime.map
@@ -0,0 +1,10 @@
+GLIBC_2.2 {
+ global:
+
+ timer_gettime; timer_settime;
+ local: timer_settime_*; timer_gettime_*;
+};
+GLIBC_2.3.3 {
+ # Changed timer_t.
+ timer_gettime; timer_settime;
+} GLIBC_2.2;