mirror of
https://github.com/wolfcw/libfaketime.git
synced 2026-05-17 00:26:16 +03:00
Merge pull request #1 from dbrashear/master
I ported libfaketime to MacOS.
This commit is contained in:
6
README
6
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
|
||||
--------
|
||||
|
||||
@@ -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
|
||||
|
||||
84
src/Makefile.MacOS
Normal file
84
src/Makefile.MacOS
Normal file
@@ -0,0 +1,84 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
# If you get an error about an unsupported architecture, remove it. Some
|
||||
# versions of XCode support different subsets of architectures, depending on
|
||||
# age.
|
||||
# 10.5
|
||||
#CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS -arch i386 -arch ppc
|
||||
# 10.6
|
||||
CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS -arch i386 -arch x86_64
|
||||
|
||||
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
|
||||
@@ -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:
|
||||
@@ -375,6 +377,16 @@ 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
|
||||
@@ -382,26 +394,54 @@ int __lxstat64 (int ver, const char *path, struct stat64 *buf){
|
||||
* 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
|
||||
@@ -585,6 +630,9 @@ time_t fake_time(time_t *time_tptr) {
|
||||
static time_t last_data_fetch = 0; /* not fetched previously at first call */
|
||||
static int cache_expired = 1; /* considered expired at first call */
|
||||
static int cache_duration = 10; /* cache fake time input for 10 seconds */
|
||||
#ifdef __APPLE__
|
||||
static int malloc_arena = 0;
|
||||
#endif
|
||||
|
||||
#ifdef PTHREAD_SINGLETHREADED_TIME
|
||||
static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
@@ -654,6 +702,13 @@ static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
} /* cache had expired */
|
||||
|
||||
#ifdef __APPLE__
|
||||
SINGLE_IF(malloc_arena==0)
|
||||
malloc_arena = 1;
|
||||
return *time_tptr;
|
||||
END_SINGLE_IF
|
||||
#endif
|
||||
|
||||
/* check whether the user gave us an absolute time to fake */
|
||||
switch (user_faked_time[0]) {
|
||||
|
||||
@@ -724,31 +779,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 +813,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);
|
||||
|
||||
Reference in New Issue
Block a user