summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerrick Brashear <shadow@dementia.org>2011-07-05 09:05:38 -0400
committerDerrick Brashear <shadow@dementia.org>2011-07-05 09:05:38 -0400
commiteb59447a6d41f03f9f3bd97876a766f9164c5993 (patch)
treead02fe9a74f014f57411fc1f6b8c9499630ab59a
parented250849700b77d01b579fcbf58be6f129f4988b (diff)
downloadfaketime-ng-eb59447a6d41f03f9f3bd97876a766f9164c5993.tar.gz
libfaketime macos port
port libfaketime to macos and dyld. 1) _ftpl_time calls gettimeofday since real time() does so. needed to avoid double adjustment. 2) reduce call stack: use time tptr and call fake_time instead of calling time for faking other time calls. 3) provide MacOS makefile and README notes. 4) make posix realtime calls under ifdef; define for base port but not MacOS.
-rw-r--r--README6
-rw-r--r--src/Makefile2
-rw-r--r--src/Makefile.MacOS78
-rw-r--r--src/faketime.c77
4 files changed, 148 insertions, 15 deletions
diff --git a/README b/README
index d4e273a..36c57be 100644
--- a/README
+++ b/README
@@ -96,6 +96,12 @@ not need this feature or if it confuses the application you want to use FTPL
with, define the environment variable NO_FAKE_STAT, and the intercepted stat
calls will be passed through unaltered.
+On MacOS, it is necessary to compile differently, due to the different
+behavior dyld has. Use the Makefile.MacOS provided to compile
+libfaketime.dylib.1. Additionally, instead of using LD_PRELOAD,
+the variable DYLD_INSERT_LIBRARIES should be set to the path to
+libfaketime.dylib.1, and the variable DYLD_FORCE_FLAT_NAMESPACE should be
+set (to anything).
4. Usage
--------
diff --git a/src/Makefile b/src/Makefile
index d61ebfa..702fc93 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -45,7 +45,7 @@ INSTALL = install
PREFIX = /usr/local
-CFLAGS = -std=gnu99 -Wall -DFAKE_STAT -DFAKE_INTERNAL_CALLS -fPIC
+CFLAGS = -std=gnu99 -Wall -DFAKE_STAT -DFAKE_INTERNAL_CALLS -fPIC -DPOSIX_REALTIME
LDFLAGS = -shared -ldl -lm -lpthread
SRC = faketime.c
diff --git a/src/Makefile.MacOS b/src/Makefile.MacOS
new file mode 100644
index 0000000..b42f13a
--- /dev/null
+++ b/src/Makefile.MacOS
@@ -0,0 +1,78 @@
+#
+# Notes:
+#
+# * Compilation Defines:
+#
+# FAKE_STAT
+# - Enables time faking also for files' timestamps.
+#
+# NO_ATFILE
+# - Disables support for the fstatat() group of functions
+#
+# PTHREAD
+# - Define this to enable multithreading support.
+#
+# PTHREAD_SINGLETHREADED_TIME
+# - Define this if you want to single-thread time() ... there ARE
+# possibile caching side-effects in a multithreaded environment
+# without this, but the performance impact may require you to
+# try it unsynchronized.
+#
+# FAKE_INTERNAL_CALLS
+# - Also intercept libc internal __functions, e.g. not just time(),
+# but also __time(). Enhances compatibility with applications
+# that make use of low-level system calls, such as Java Virtual
+# Machines.
+#
+# NO_CACHING
+# - Disables the caching of the fake time offset. Only disable caching
+# if you change the fake time offset during program runtime very
+# frequently. Disabling the cache may negatively influence the
+# performance.
+#
+#
+# * Compilation addition: second libMT target added for building the pthread-
+# enabled library as a separate library
+#
+# * Compilation switch change: previous versions compiled using '-nostartfiles'
+# This is no longer the case since there is a 'startup' constructor for the library
+# which is used to activate the start-at times when specified. This also initializes
+# the dynamic disabling of the FAKE_STAT calls.
+#
+
+CC = gcc
+INSTALL = install
+
+PREFIX = /usr/local
+
+CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS
+
+SRC = faketime.c
+
+SONAME = 1
+LIBS = libfaketime.dylib.${SONAME}
+
+all: ${LIBS}
+
+libfaketime.dylib.${SONAME}: ${SRC}
+ ${CC} -o $@ ${CFLAGS} $<
+
+clean:
+ @rm -f ${OBJ} ${LIBS}
+
+distclean: clean
+ @echo
+
+install: ${LIBS}
+ @echo
+ @echo "Copying the faketime libraries to ${DESTDIR}${PREFIX}/lib/faketime and the faketime wrapper script to ${DESTDIR}${PREFIX}/bin ..."
+ $(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/lib/faketime/"
+ $(INSTALL) -m0644 ${LIBS} "${DESTDIR}${PREFIX}/lib/faketime/"
+ $(INSTALL) -Dm0755 faketime "${DESTDIR}${PREFIX}/bin/faketime"
+
+uninstall:
+ for f in ${LIBS}; do rm -f "${DESTDIR}${PREFIX}/lib/faketime/$$f"; done
+ rmdir "${DESTDIR}${PREFIX}/lib/faketime"
+ rm -f "${DESTDIR}${PREFIX}/bin/faketime"
+
+.PHONY: all clean distclean install uninstall
diff --git a/src/faketime.c b/src/faketime.c
index 43a9d83..1a961a1 100644
--- a/src/faketime.c
+++ b/src/faketime.c
@@ -60,7 +60,9 @@ static pthread_mutex_t once_mutex=PTHREAD_MUTEX_INITIALIZER;
time_t fake_time(time_t *time_tptr);
int fake_ftime(struct timeb *tp);
int fake_gettimeofday(struct timeval *tv, void *tz);
+#ifdef POSIX_REALTIME
int fake_clock_gettime(clockid_t clk_id, struct timespec *tp);
+#endif
/*
* Intercepted system calls:
@@ -376,32 +378,70 @@ int __lxstat64 (int ver, const char *path, struct stat64 *buf){
#endif
/*
+ * On MacOS, time() internally uses gettimeofday. If we don't
+ * break the cycle by just calling it directly, we double-apply
+ * relative changes.
+ */
+
+#ifdef __APPLE__
+static int (*real_gettimeofday)(struct timeval *, void *);
+static int has_real_gettimeofday = 0;
+#endif
+/*
* Our version of time() allows us to return fake values, so the calling
* program thinks it's retrieving the current date and time, while it is
* not
* Note that this routine is split into two parts so that the initialization
* piece can call the 'real' time function to establish a base time.
*/
-
static time_t _ftpl_time(time_t *time_tptr) {
+#ifdef __APPLE__
+ struct timeval tvm, *tv = &tvm;
+#else
static time_t (*real_time)(time_t *);
static int has_real_time = 0;
+#endif
time_t result;
time_t null_dummy;
-
+
/* Handle null pointers correctly, fix as suggested by Andres Ojamaa */
if (time_tptr == NULL) {
time_tptr = &null_dummy;
/* (void) fprintf(stderr, "NULL pointer caught in time().\n"); */
}
-
+
+#ifdef __APPLE__
+ /* Check whether we've got a pointer to the real ftime() function yet */
+ SINGLE_IF(has_real_gettimeofday==0)
+ real_gettimeofday = NULL;
+ real_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");
+
+ /* check whether dlsym() worked */
+ if (dlerror() == NULL) {
+ has_real_gettimeofday = 1;
+ }
+ END_SINGLE_IF
+ if (!has_real_gettimeofday) { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original gettimeofday() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ /* initialize our result with the real current time */
+ result = (*real_gettimeofday)(tv, NULL);
+ if (result == -1) return result; /* original function failed */
+ if (time_tptr != NULL)
+ *time_tptr = tv->tv_sec;
+ result = tv->tv_sec;
+#else
/* Check whether we've got a pointer to the real time function yet */
SINGLE_IF(has_real_time==0)
real_time = NULL;
real_time = dlsym(RTLD_NEXT, "time");
-
+
/* check whether dlsym() worked */
if (dlerror() == NULL) {
has_real_time = 1;
@@ -415,9 +455,10 @@ static time_t _ftpl_time(time_t *time_tptr) {
*time_tptr = -1;
return -1; /* propagate error to caller */
}
-
+
/* initialize our result with the real current time */
result = (*real_time)(time_tptr);
+#endif
return result;
}
@@ -477,10 +518,12 @@ int ftime(struct timeb *tp) {
}
int gettimeofday(struct timeval *tv, void *tz) {
+#ifndef __APPLE__
static int (*real_gettimeofday)(struct timeval *, void *);
static int has_real_gettimeofday = 0;
+#endif
int result;
-
+
/* sanity check */
if (tv == NULL) {
return -1;
@@ -509,11 +552,12 @@ int gettimeofday(struct timeval *tv, void *tz) {
/* pass the real current time to our faking version, overwriting it */
result = fake_gettimeofday(tv, tz);
-
+
/* return the result to the caller */
return result;
}
+#ifdef POSIX_REALTIME
int clock_gettime(clockid_t clk_id, struct timespec *tp) {
static int (*real_clock_gettime)(clockid_t clk_id, struct timespec *tp);
static int has_real_clock_gettime = 0;
@@ -551,6 +595,7 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp) {
/* return the result to the caller */
return result;
}
+#endif
/*
* Static time_t to store our startup time, followed by a load-time library
@@ -724,31 +769,33 @@ static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
}
int fake_ftime(struct timeb *tp) {
- time_t temp_tt;
+ time_t temp_tt = tp->time;
- tp->time = time(&temp_tt);
+ tp->time = fake_time(&temp_tt);
return 0; /* always returns 0, see manpage */
}
int fake_gettimeofday(struct timeval *tv, void *tz) {
- time_t temp_tt;
-
- tv->tv_sec = time(&temp_tt);
+ time_t temp_tt = tv->tv_sec;
+
+ tv->tv_sec = fake_time(&temp_tt);
return 0;
}
+#ifdef POSIX_REALTIME
int fake_clock_gettime(clockid_t clk_id, struct timespec *tp) {
- time_t temp_tt;
+ time_t temp_tt = tp->tv_sec;
/* Fake only if the call is realtime clock related */
if (clk_id == CLOCK_REALTIME) {
- tp->tv_sec = time(&temp_tt);
+ tp->tv_sec = fake_time(&temp_tt);
}
return 0;
}
+#endif
/* Added in v0.7 as suggested by Jamie Cameron, Google */
#ifdef FAKE_INTERNAL_CALLS
@@ -756,9 +803,11 @@ int __gettimeofday(struct timeval *tv, void *tz) {
return gettimeofday(tv, tz);
}
+#ifdef POSIX_REALTIME
int __clock_gettime(clockid_t clk_id, struct timespec *tp) {
return clock_gettime(clk_id, tp);
}
+#endif
int __ftime(struct timeb *tp) {
return ftime(tp);