Merge branch 'develop' (Jon Ringle's patches)

Merge pull request #55 from ringlej/feature/fix-FAKETIME-cache

Conflicts:
	src/libfaketime.c
This commit is contained in:
Jon Ringle
2015-02-08 17:42:44 +01:00
committed by Wolfgang Hommel
6 changed files with 138 additions and 18 deletions

View File

@@ -25,6 +25,9 @@ use the multi-threading variant of libfaketime.
.TP
\fB\-f\fR
use the advanced timestamp specification format.
.TP
\fB\--exclude-monotonic\fR
Do not fake time when the program makes a call to clock_gettime with a CLOCK_MONOTONIC clock.
.SH EXAMPLES
.nf

View File

@@ -60,10 +60,20 @@ INSTALL ?= install
PREFIX ?= /usr/local
LIBDIRNAME ?= /lib/faketime
PLATFORM ?=$(shell uname)
CFLAGS += -std=gnu99 -Wall -Wextra -Werror -DFAKE_STAT -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' -DLIBDIRNAME='"'$(LIBDIRNAME)'"'
ifeq ($(PLATFORM),SunOS)
CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=600
endif
LIB_LDFLAGS += -shared
LDFLAGS += -Wl,--version-script=libfaketime.map -lpthread
LDFLAGS += -lpthread
ifneq ($(PLATFORM),SunOS)
LDFLAGS += -Wl,--version-script=libfaketime.map
endif
LDADD += -ldl -lm -lrt
BIN_LDFLAGS += -lrt

View File

@@ -211,8 +211,15 @@ int main (int argc, char **argv)
struct ft_shared_s *ft_shared;
char shared_objs[PATH_BUFSIZE];
snprintf(sem_name, PATH_BUFSIZE -1 ,"/faketime_sem_%d", getpid());
snprintf(shm_name, PATH_BUFSIZE -1 ,"/faketime_shm_%d", getpid());
/*
* Casting of getpid() return value to long needed to make GCC on SmartOS
* happy, since getpid's return value's type on SmartOS is long. Since
* getpid's return value's type is int on most other systems, and that
* sizeof(long) always >= sizeof(int), this works on all platforms without
* the need for crazy #ifdefs.
*/
snprintf(sem_name, PATH_BUFSIZE -1 ,"/faketime_sem_%ld", (long)getpid());
snprintf(shm_name, PATH_BUFSIZE -1 ,"/faketime_shm_%ld", (long)getpid());
if (SEM_FAILED == (sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IWUSR|S_IRUSR, 1)))
{
@@ -358,6 +365,8 @@ int main (int argc, char **argv)
}
exit(WEXITSTATUS(ret));
}
return EXIT_SUCCESS;
}
/*

View File

@@ -22,7 +22,6 @@
*/
#define _GNU_SOURCE /* required to get RTLD_NEXT defined */
#define _XOPEN_SOURCE /* required to get strptime() defined */
#include <stdio.h>
#include <stdlib.h>
@@ -57,7 +56,11 @@
#ifndef __APPLE__
extern char *__progname;
#ifdef __sun
#include "sunos_endian.h"
#else
#include <endian.h>
#endif
#else
/* endianness related macros */
#define htobe64(x) OSSwapHostToBigInt64(x)
@@ -145,6 +148,7 @@ static unsigned int (*real_sleep) (unsigned int seconds);
static unsigned int (*real_alarm) (unsigned int seconds);
static int (*real_poll) (struct pollfd *, nfds_t, int);
static int (*real_ppoll) (struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
static int (*real_sem_timedwait) (sem_t*, const struct timespec*);
#endif
#ifdef __APPLE__
static int (*real_clock_get_time) (clock_serv_t clock_serv, mach_timespec_t *cur_timeclockid_t);
@@ -216,6 +220,8 @@ static char user_faked_time_fmt[BUFSIZ] = {0};
static struct timespec user_faked_time_timespec = {0, -1};
/* User supplied base time is set */
static bool user_faked_time_set = false;
static char user_faked_time_saved[BUFFERLEN] = {0};
/* Fractional user offset provided through FAKETIME env. var.*/
static struct timespec user_offset = {0, -1};
/* Speed up or slow down clock */
@@ -989,6 +995,52 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout)
DONT_FAKE_TIME(ret = (*real_poll)(fds, nfds, timeout_real));
return ret;
}
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
{
int result;
struct timespec real_abs_timeout, *real_abs_timeout_pt;
/* sanity check */
if (abs_timeout == NULL)
{
return -1;
}
if (NULL == real_sem_timedwait)
{ /* dlsym() failed */
#ifdef DEBUG
(void) fprintf(stderr, "faketime problem: original sem_timedwait() not found.\n");
#endif
return -1; /* propagate error to caller */
}
if (!dont_fake)
{
struct timespec tdiff, timeadj;
timespecsub(abs_timeout, &ftpl_starttime.real, &tdiff);
if (user_rate_set)
{
timespecmul(&tdiff, user_rate, &timeadj);
}
else
{
timeadj = tdiff;
}
timespecadd(&user_faked_time_timespec, &timeadj, &real_abs_timeout);
real_abs_timeout_pt = &real_abs_timeout;
}
else
{
/* cast away constness */
real_abs_timeout_pt = (struct timespec *)abs_timeout;
}
DONT_FAKE_TIME(result = (*real_sem_timedwait)(sem, real_abs_timeout_pt));
return result;
}
#endif
#ifndef __APPLE__
@@ -1416,6 +1468,13 @@ static void parse_ft_string(const char *user_faked_time)
{
struct tm user_faked_time_tm;
char * tmp_time_fmt;
if (!strncmp(user_faked_time, user_faked_time_saved, BUFFERLEN))
{
/* No change */
return;
}
/* check whether the user gave us an absolute time to fake */
switch (user_faked_time[0])
{
@@ -1464,6 +1523,9 @@ static void parse_ft_string(const char *user_faked_time)
user_faked_time_timespec.tv_sec = mktime(&user_faked_time_tm);
user_faked_time_timespec.tv_nsec = 0;
/* Reset starttime */
system_time_from_system(&ftpl_starttime);
goto parse_modifiers;
break;
@@ -1486,6 +1548,12 @@ parse_modifiers:
}
break;
} // end of switch
strncpy(user_faked_time_saved, user_faked_time, BUFFERLEN-1);
user_faked_time_saved[BUFFERLEN-1] = 0;
#ifdef DEBUG
fprintf(stderr, "new FAKETIME: %s\n", user_faked_time_saved);
#endif
}
@@ -1524,6 +1592,7 @@ void ftpl_init(void)
real_alarm = dlsym(RTLD_NEXT, "alarm");
real_poll = dlsym(RTLD_NEXT, "poll");
real_ppoll = dlsym(RTLD_NEXT, "ppoll");
real_sem_timedwait = dlsym(RTLD_NEXT, "sem_timedwait");
#endif
#ifdef FAKE_INTERNAL_CALLS
real___ftime = dlsym(RTLD_NEXT, "__ftime");
@@ -1540,6 +1609,10 @@ void ftpl_init(void)
real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
}
#ifdef FAKE_TIMERS
#if defined(__sun)
real_timer_gettime_233 = dlsym(RTLD_NEXT, "timer_gettime");
real_timer_settime_233 = dlsym(RTLD_NEXT, "timer_settime");
#else
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");
if (NULL == real_timer_settime_233)
@@ -1554,6 +1627,8 @@ void ftpl_init(void)
}
#endif
#endif
#endif
initialized = 1;
ft_shm_init();
@@ -1883,29 +1958,30 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
if (cache_expired == 1)
{
last_data_fetch = tp->tv_sec;
static char user_faked_time[BUFFERLEN]; /* changed to static for caching in v0.6 */
/* initialize with default or env. variable */
char *tmp_env;
/* Can be enabled for testing ...
fprintf(stderr, "***************++ Cache expired ++**************\n");
*/
if (NULL != (tmp_env = getenv("FAKETIME")))
{
strncpy(user_faked_time, tmp_env, BUFFERLEN);
}
else
{
snprintf(user_faked_time, BUFFERLEN, "+0");
}
last_data_fetch = tp->tv_sec;
/* fake time supplied as environment variable? */
if (parse_config_file)
{
static char user_faked_time[BUFFERLEN]; /* changed to static for caching in v0.6 */
char custom_filename[BUFSIZ];
char filename[BUFSIZ];
FILE *faketimerc;
/* initialize with default or env. variable */
char *tmp_env;
if (NULL != (tmp_env = getenv("FAKETIME")))
{
strncpy(user_faked_time, tmp_env, BUFFERLEN);
}
else
{
snprintf(user_faked_time, BUFFERLEN, "+0");
}
/* check whether there's a .faketimerc in the user's home directory, or
* a system-wide /etc/faketimerc present.
* The /etc/faketimerc handling has been contributed by David Burley,
@@ -1930,8 +2006,8 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
}
fclose(faketimerc);
}
parse_ft_string(user_faked_time);
} /* read fake time from file */
parse_ft_string(user_faked_time);
} /* cache had expired */
if (infile_set)

12
src/sunos_endian.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef SUN_OS_ENDIAN_H
#define SUN_OS_ENDIAN_H
#include <sys/byteorder.h>
#define htobe64(x) BE_64(x)
#define be64toh(x) BE_64(x)
#define htole64(x) LE_64(x)
#define le64toh(x) LE_64(x)
#endif /* SUN_OS_ENDIAN_H */

View File

@@ -9,6 +9,7 @@ platform()
*Darwin*) echo "mac" ;;
*Linux*) echo "linuxlike" ;;
GNU|GNU/kFreeBSD) echo "linuxlike" ;;
*SunOS*) echo "sunos" ;;
*) echo 1>&2 unsupported platform, uname=\"$out\" ;;
esac
}
@@ -25,6 +26,15 @@ mac_fakecmd()
"$@"
}
sunos_fakecmd()
{
typeset timestring="$1"; shift
typeset fakelib=../src/libfaketime.so.1
export LD_PRELOAD=$fakelib
FAKETIME="$timestring" \
"$@"
}
# run faked command on linuxlike OS
linuxlike_fakecmd()
{