51 Commits

Author SHA1 Message Date
Wolfgang Hommel
57de5bbe83 Merge pull request #252 from sdettmer/automake_make_check
**FOR REVIEW** Automake make check
2020-04-09 19:29:29 +02:00
Steffen Dettmer
c2b5b71777 First few fixes for make check (#250) 2020-04-09 17:43:51 +02:00
Steffen Dettmer
6c0947c86e Fixed make distcheck (#250) 2020-04-09 17:43:10 +02:00
Steffen Dettmer
b36ad2342c Removed automatically created files (#250) 2020-04-09 16:58:44 +02:00
Wolfgang Hommel
d40d0ebaa7 adapt travis.yml to automake 2020-04-09 06:37:39 +02:00
Wolfgang Hommel
081845440b fix bracket syntax on Linux 2020-04-09 06:34:20 +02:00
Wolfgang Hommel
30207e8fdf merge with @manchicken's automake branch 2020-04-09 06:26:49 +02:00
Wolfgang Hommel
d2f0daf092 Merge pull request #246 from sdettmer/dev/sde/pthread_cond_init_232_lazy_init
Add lazy ftpl_init() to pthread_cond_init_232(), fixes #245.
2020-04-08 20:11:57 +02:00
Steffen Dettmer
c5b5d0b56e Add lazy ftpl_init() to pthread_cond_init_232(), fixes #245. 2020-04-08 19:57:14 +02:00
Wolfgang Hommel
f8a0ad2496 Merge pull request #244 from sdettmer/dev/sde/faketime_link_flags
Added support for FAKETIME_LINK_FLAGS for #243.
2020-04-08 19:47:46 +02:00
Steffen Dettmer
0e3269efdc Added support for FAKETIME_LINK_FLAGS for #243. 2020-04-08 19:40:31 +02:00
Wolfgang Hommel
04e78e67bf Unskip file parsing on improper initialization #240 2020-03-26 20:07:24 +01:00
Wolfgang Hommel
0e798503a4 Merge pull request #237 from FeepingCreature/fix/use-pthread-mutex-initializer-again
replace global state struct with local state struct holding a pointer to the global mutex variable
2020-03-16 13:45:37 +01:00
Mathis Beer
a7f7a54e1d replace global state struct with local state struct holding a pointer to the global mutex variable
this fixes the `{ 0 }` initializer not compiling on some platforms
fix issue 231
fix issue 235
2020-03-16 07:57:07 +01:00
Wolfgang Hommel
8075c2e250 Merge pull request #234 from FeepingCreature/fix/use-appropriate-mask-function
Fix timing issue with multiple threads
2020-03-12 21:39:17 +01:00
Mathis Beer
a12ca58dfa fix threading issue: don't assign to the global lock state struct until we're safely inside the mutex.
Otherwise, we might be overwriting the global lock state from two different
threads at once.
2020-03-12 06:49:29 +01:00
Mathis Beer
b4dea2ef9b Unlock faketime lock on all return paths from libfaketime.c.
These gymnastics are necessary because pthread_cleanup_push
and pthread_cleanup_pop must match exactly 1:1 and appear at
the same level of indentation.

This is because pthread_cleanup_push/pop are implemented in
such a way that pthread_cleanup_push opens a scope and
pthread_cleanup_pop closes it.

They're macros with unbalanced brackets.
C, ladies and gentlemen.

So instead of returning, we have to set a field indicating our
intent to return and then jump to the unlock site.
2020-03-12 06:45:43 +01:00
Mathis Beer
796b30bebf use pthread_sigmask instead of sigprocmask
pthread_sigmask is the one meant for threaded programs.
2020-03-12 06:43:33 +01:00
Wolfgang Hommel
70d26ec15c Merge pull request #230 from FeepingCreature/fix/block-signals-while-locked
Fix deadlock issues with signals: block all signals while inside mutex.
2020-03-03 19:47:49 +01:00
Mathis Beer
052239d828 Fix deadlock issues with signals: block all signals while inside mutex. 2020-03-03 17:22:52 +01:00
Wolfgang Hommel
fe8c0acee6 Merge pull request #229 from FeepingCreature/fix/dont-allocate-stack-buffers
fake_clock_gettime: avoid placing large buffers on the stack
2020-02-20 21:10:19 +01:00
Mathis Beer
c44a332e0e fake_clock_gettime: avoid placing large buffers on the stack 2020-02-20 12:14:14 +01:00
Wolfgang Hommel
a54f204209 Merge pull request #227 from wolfcw/develop
Refresh the monotonic faketime setting envvar when cache expires.
2020-02-14 19:42:23 +01:00
Wolfgang Hommel
195888434a Merge pull request #225 from tjhowse/develop
Refresh the monotonic faketime setting envar when cache expires.
2020-02-14 19:36:06 +01:00
thowse
f7de52c07b Refresh the monotonic faketime setting envar when cache expires. 2020-02-14 10:36:29 +10:00
Wolfgang Hommel
0efe7b3e3e Merge pull request #220 from aristanemi/mul_overflow_fix
timespec multiplication overflow fix
2019-12-17 18:55:20 +01:00
Abhishek Sunkum Rammurthy
b542e14959 time multiplication overflow fix
In 32 bit platforms, timespecmul2() macro function, overflow occurs during multiplication.
Size of `long` type in 32 bit platform is 4 bytes, but the size of `long` type in 64 bit platform is 8 bytes.
2019-12-17 15:16:38 +01:00
Wolfgang Hommel
78385ba8b7 Use -DFAKE_FILE_TIMESTAMPS to intercept utime[s](), by @speq, #183 2019-12-14 21:49:23 +01:00
Wolfgang Hommel
b3dcef470e fix #ifndef for timermul, @speq, #183 2019-12-14 21:30:31 +01:00
Wolfgang Hommel
90f11685b5 wrap nanosec ops in #ifndef, patch by @paul-j-lucas, #219 2019-12-14 19:49:04 +01:00
Wolfgang Hommel
d7ef17a0de Merge pull request #218 from wolfcw/revert-178-automake-branch
Revert "Automake branch"
2019-11-30 09:37:00 +01:00
Wolfgang Hommel
3123ad7fe2 Revert "Automake branch" 2019-11-30 09:36:46 +01:00
Wolfgang Hommel
af2d2e5111 Merge pull request #178 from manchicken/automake-branch
Automake branch
2019-11-30 09:36:36 +01:00
Wolfgang Hommel
11fbc2ada1 Create make-test.yml 2019-11-30 09:16:43 +01:00
Michael D. Stemle, Jr
f92d919fb0 Merged master in and cleaned up.
We no longer need the OSX-specific test. Tests are passing, too.
2019-11-27 14:32:15 -05:00
Wolfgang Hommel
22f8c3dd36 Work around race conditions when semaphore gets deleted by parent process (#217) 2019-11-20 08:43:24 +01:00
Wolfgang Hommel
a0fe6b56b0 Merge pull request #215 from wolfcw/develop
Merge changes from develop branch
2019-11-14 19:33:00 +01:00
Wolfgang Hommel
fdc3c81ae0 Merge pull request #214 from daowens01/unused_variable_compiler_error
Wrap user_per_tick_inc_set_backup declaration in ifdef
2019-11-14 19:08:44 +01:00
David Owens
10b9818c2c Wrap user_per_tick_inc_set_backup declaration in ifdef
Building without FAKE_STAT defined causes compilation errors due to
unused variable user_per_tick_inc_set_backup.  Move declaration inside
FAKE_STAT section along with the code making use of it.
2019-11-14 09:27:27 -06:00
Wolfgang Hommel
826f8b7792 Detect and bail out of endless recursive calls to clock_gettime() (#130) 2019-09-05 22:52:07 +02:00
Wolfgang Hommel
5d1e6325f2 Add FAKE_SETTIME to CFLAGS to intercept time-setting calls (#179) 2019-09-03 12:01:33 +02:00
Wolfgang Hommel
8ed946cb63 Documentation for packagers, esp. about FORCE_PTHREAD_NONVER and FORCE_MONOTONIC_FIX 2019-08-31 21:32:52 +02:00
Wolfgang Hommel
108370f850 Adds FORCE_PTHREAD_NONVER flag for platforms where pthread functions are not intercepted 2019-08-29 09:55:04 +02:00
Wolfgang Hommel
3de0d02353 Add macOS / OSX build to .travis.yml 2019-08-23 21:20:48 +02:00
Mike Stemle
150a6cb3b2 Added a check for missing libtool. 2018-10-11 10:22:04 -04:00
Michael D. Stemle, Jr
39a85e380c Fixed a _bunch_ of autotools bugs. 2018-10-07 22:38:55 -04:00
Michael D. Stemle, Jr
825043515f Applying fixes for GNU/Linux, and the MT variant of the library. 2018-10-03 22:17:28 -04:00
Michael D. Stemle, Jr
335617c4c7 Fixed a bunch more issues, including prefix-related issues and library version breakage. 2018-10-02 23:22:51 -04:00
Michael D. Stemle, Jr
96668a9c6d Fixing a couple of issues I just found. 2018-10-02 22:20:14 -04:00
Michael D. Stemle, Jr
24fd806e6b Added GNU autotools support. 2018-10-02 22:02:30 -04:00
Michael D. Stemle, Jr
39c6872f6d Removing old makefiles. 2018-10-01 20:08:27 -04:00
33 changed files with 1143 additions and 372 deletions

23
.github/workflows/make-test.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Run make test
on:
push:
branches:
- master
- develop
schedule:
- cron: '30 9 * * *'
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v1
- name: make
run: make
- name: make test
run: make test

21
.gitignore vendored
View File

@@ -7,3 +7,24 @@ src/libfaketime.1.dylib
src/core
src/faketime
.vscode/
Makefile
Makefile.in
/aclocal.m4
/autom4te.cache/
/config.*
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4/
/missing
/stamp-h?
.deps/
.dirstamp
.libs/
*.l[ao]
compile
test-driver

View File

@@ -4,8 +4,14 @@ matrix:
include:
- os: linux
compiler: gcc
- os: osx
osx_image: xcode11
script:
- cd ${TRAVIS_BUILD_DIR}
- sh ./build.sh init
- ./configure
- FAKETIME_COMPILE_CFLAGS="-DFORCE_MONOTONIC_FIX" make
- cd test
- make test
- make distcheck

2
AUTHORS Normal file
View File

@@ -0,0 +1,2 @@
Wolfgang Hommel <wolfcw>
Balint Reczey <rbalint>

11
ChangeLog Normal file
View File

@@ -0,0 +1,11 @@
# Changelog
All notable changes to this project will be documented in this file.
Additional change history is viewable in the `NEWS` file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Changed
- Mike Stemle added GNU autotools

View File

@@ -1,35 +0,0 @@
INSTALL ?= install
UNAME=$(shell uname)
SELECTOR:=$(shell if test "${UNAME}" = "Darwin" ; then echo "-f Makefile.OSX" ; fi)
all:
$(MAKE) $(SELECTOR) -C src all
test:
$(MAKE) $(SELECTOR) -C src all
$(MAKE) $(SELECTOR) -C test all
install:
$(MAKE) $(SELECTOR) -C src install
$(MAKE) $(SELECTOR) -C man install
$(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/share/doc/faketime/"
$(INSTALL) -m0644 README "${DESTDIR}${PREFIX}/share/doc/faketime/README"
$(INSTALL) -m0644 NEWS "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
uninstall:
$(MAKE) $(SELECTOR) -C src uninstall
$(MAKE) $(SELECTOR) -C man uninstall
rm -f "${DESTDIR}${PREFIX}/share/doc/faketime/README"
rm -f "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
rmdir "${DESTDIR}${PREFIX}/share/doc/faketime"
clean:
$(MAKE) $(SELECTOR) -C src clean
$(MAKE) $(SELECTOR) -C test clean
distclean:
$(MAKE) $(SELECTOR) -C src distclean
$(MAKE) $(SELECTOR) -C test distclean
.PHONY: all test install uninstall clean distclean

4
Makefile.am Normal file
View File

@@ -0,0 +1,4 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS=-I m4
SUBDIRS=src test man
EXTRA_DIST=README.developers README.OSX README.packagers TODO

17
NEWS
View File

@@ -1,3 +1,20 @@
Since 0.9.9:
- Mike Stemle added GNU autotools
- Additional link-time LDFLAGS can be passed via the
environment variable FAKETIME_LINK_FLAGS when
running 'make'.
Since 0.9.8:
- Compile-time CFLAG FAKE_SETTIME can be enabled to
intercept calls to clock_settime(), settimeofday(), and
adjtime(). (suggested and prototyped by @ojura)
- Additional compile-time CFLAGs can be passed via the
environment variable FAKETIME_COMPILE_CFLAGS when
running 'make'.
- src/Makefile CFLAG FORCE_PTHREAD_NONVER should be set on
systems that hang on CLOCK_REALTIME, or that hang on
CLOCK_MONOTONIC where FORCE_MONOTONIC_FIX is not sufficient.
Since 0.9.7:
- Passthrough for unknown clock ids to avoid error messages
- Fixes for multithreaded operations (mliertzer, qnox)

44
README
View File

@@ -97,11 +97,25 @@ documentation whether it can be achieved by using libfaketime directly.
src/Makefile and recompile libfaketime. Do not set FORCE_MONOTONIC_FIX on
platforms where the test does not hang.
If you observe hangs on the CLOCK_REALTIME test, add the CFLAG
-DFORCE_PTHREAD_NONVER. Also set this FORCE_PTHREAD_NONVER flag in case
FORCE_MONOTONIC_FIX alone does not solve the hang on the MONOTONIC_CLOCK
test.
3. Installation
---------------
Running "make" compiles both library versions and a test program, which it then
also executes.
This library supports GNU autotools, so you should be able to build it with:
sh ./build.sh init
./configure
make
After you have built the library, you may--optionally--run the tests with:
cd test
make test
If the test works fine, you should copy the libfaketime libraries
(libfaketime.so.1, and libfaketimeMT.so.1) to the place you want them in.
@@ -124,14 +138,16 @@ 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.OSX file provided to compile
libfaketime.1.dylib. Additionally, instead of using LD_PRELOAD,
the variable DYLD_INSERT_LIBRARIES should be set to the path to
libfaketime.1.dylib, and the variable DYLD_FORCE_FLAT_NAMESPACE should be
set (to anything). macOS users should read README.OSX for additional
details.
On macOS, instead of using LD_PRELOAD, the variable DYLD_INSERT_LIBRARIES
should be set to the path to libfaketime.0.dylib, and the variable
DYLD_FORCE_FLAT_NAMESPACE should be set (to anything). macOS users should
read README.OSX for additional details.
NOTE: When committing, clean up potentially non-portable files with:
sh build.sh clean
This will clean up the build files which we don't want to version-control.
4. Usage
--------
@@ -450,6 +466,16 @@ a lot of processes are started (e.g., servers handling many containers
or similar virtualization mechanisms).
Intercepting time-setting calls
-------------------------------
libfaketime can be compiled with the CFLAG "-DFAKE_SETTIME" in order
to also intercept time-setting functions, i.e., clock_settime(),
settimeofday(), and adjtime(). Instead of passing the timestamp a
program sets through to the system, only the FAKETIME environment
variable will be adjusted accordingly.
4f) Faking the date and time system-wide
----------------------------------------

View File

@@ -39,18 +39,23 @@ Otherwise, you have to compile and install libfaketime manually; this
will require a working installation of Xcode and its command line tools
on your machine.
You can compile libfaketime by running the command
This library now supports GNU autotools, so you can build it using:
sh build.sh init
./configure
make
in libfaketime's top-level directory.
The resulting library will be named libfaketime.1.dylib ; to check
whether it works properly, run the test suite and verify whether its
output is correct:
cd test
make -f Makefile.OSX
make test
NOTE: When committing, be sure to clean up potentially
system-dependent files by running:
sh build.sh clean
2) Using libfaketime from the command line on macOS

63
README.packagers Normal file
View File

@@ -0,0 +1,63 @@
README for packagers of libfaketime
First, thank you for your efforts to make libfaketime packages available
on your platform / distribution!
libfaketime has tagged releases about once every 1-2 years, made available
through github.com/wolfcw/libfaketime, but usually it is also safe (i.e.,
stable) to use the latest HEAD of the master branch, which contains bug
fixes since the last tagged release.
You may want to familiarize yourself with the options you can set into
src/Makefile, but sane defaults for stable operations have been chosen.
Currently, libfaketime does not use autotools yet, so there is
_no_ ./configure step, but "make" and "make test" will work as expected.
However, one problem makes it somewhat difficult to get libfaketime
working on different platforms:
libfaketime currently has the challenge that depending on the version
of glibc and the platform (e.g., x86_64 or aarch64) certain compiler
CFLAGS have to be set manually, as we have not yet found a way to
safely determine behavior at run-time automatically.
Please proceed as follows:
- run "make test". If everything runs through smoothly and you do not
encounter any hangs or test failure reports, use the binaries as
they are.
- If you encounter endless hangs during the CLOCK_REALTIME test,
add -DFORCE_PTHREAD_NONVER to the CFLAGS.
- If you encounter endless hangs during the CLOCK_MONOTONIC test,
add -DFORCE_MONOTONIC_FIX to the CFLAGS. If it works with that,
it's fine, otherwise additionally use -DFORCE_PTHREAD_NONVER.
CFLAGS can also be passed through the FAKETIME_COMPILE_CFLAGS environment
variable, so for example
FAKETIME_COMPILE_CFLAGS="-DFORCE_PTHREAD_NONVER" make test
would create the libfaketime binaries and run the tests with the
FORCE_PTHREAD_NONVER flag set in a single step. Likewise there is
FAKETIME_LINK_FLAGS.
Please do not use FORCE_MONOTONIC_FIX by default, as it would result
in incorrect operations on platforms that do not need it.
Our observations with a limited number of Linux distributions is that
libfaketime may require different compile flags per platform even
if the same distribution and glibc version is used across these
platforms.
As soon as we have found a reliable way to automatically choose the
correct compile-time flags, we will remove this burden from you as
packager for obvious reasons. Until then, please feel free to report
your experiences with different platforms and distribution versions
through the issue tracker on Github.
Again, thanks for your time and effort to make libfaketime available
easily for everyone else!

270
ar-lib Executable file
View File

@@ -0,0 +1,270 @@
#! /bin/sh
# Wrapper for Microsoft lib.exe
me=ar-lib
scriptversion=2012-03-01.08; # UTC
# Copyright (C) 2010-2018 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# func_error message
func_error ()
{
echo "$me: $1" 1>&2
exit 1
}
file_conv=
# func_file_conv build_file
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv in
mingw)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin)
file=`cygpath -m "$file" || echo "$file"`
;;
wine)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_at_file at_file operation archive
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
# for each of them.
# When interpreting the content of the @FILE, do NOT use func_file_conv,
# since the user would need to supply preconverted file names to
# binutils ar, at least for MinGW.
func_at_file ()
{
operation=$2
archive=$3
at_file_contents=`cat "$1"`
eval set x "$at_file_contents"
shift
for member
do
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
done
}
case $1 in
'')
func_error "no command. Try '$0 --help' for more information."
;;
-h | --h*)
cat <<EOF
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
Members may be specified in a file named with @FILE.
EOF
exit $?
;;
-v | --v*)
echo "$me, version $scriptversion"
exit $?
;;
esac
if test $# -lt 3; then
func_error "you must specify a program, an action and an archive"
fi
AR=$1
shift
while :
do
if test $# -lt 2; then
func_error "you must specify a program, an action and an archive"
fi
case $1 in
-lib | -LIB \
| -ltcg | -LTCG \
| -machine* | -MACHINE* \
| -subsystem* | -SUBSYSTEM* \
| -verbose | -VERBOSE \
| -wx* | -WX* )
AR="$AR $1"
shift
;;
*)
action=$1
shift
break
;;
esac
done
orig_archive=$1
shift
func_file_conv "$orig_archive"
archive=$file
# strip leading dash in $action
action=${action#-}
delete=
extract=
list=
quick=
replace=
index=
create=
while test -n "$action"
do
case $action in
d*) delete=yes ;;
x*) extract=yes ;;
t*) list=yes ;;
q*) quick=yes ;;
r*) replace=yes ;;
s*) index=yes ;;
S*) ;; # the index is always updated implicitly
c*) create=yes ;;
u*) ;; # TODO: don't ignore the update modifier
v*) ;; # TODO: don't ignore the verbose modifier
*)
func_error "unknown action specified"
;;
esac
action=${action#?}
done
case $delete$extract$list$quick$replace,$index in
yes,* | ,yes)
;;
yesyes*)
func_error "more than one action specified"
;;
*)
func_error "no action specified"
;;
esac
if test -n "$delete"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
for member
do
case $1 in
@*)
func_at_file "${1#@}" -REMOVE "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
;;
esac
done
elif test -n "$extract"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
if test $# -gt 0; then
for member
do
case $1 in
@*)
func_at_file "${1#@}" -EXTRACT "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
;;
esac
done
else
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
do
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
done
fi
elif test -n "$quick$replace"; then
if test ! -f "$orig_archive"; then
if test -z "$create"; then
echo "$me: creating $orig_archive"
fi
orig_archive=
else
orig_archive=$archive
fi
for member
do
case $1 in
@*)
func_file_conv "${1#@}"
set x "$@" "@$file"
;;
*)
func_file_conv "$1"
set x "$@" "$file"
;;
esac
shift
shift
done
if test -n "$orig_archive"; then
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
else
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
fi
elif test -n "$list"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
$AR -NOLOGO -LIST "$archive" || exit $?
fi

46
build.sh Normal file
View File

@@ -0,0 +1,46 @@
#!/bin/sh
#autoreconf --install
# Thanks, https://github.com/raywill/automake
export AUTOM4TE="autom4te"
export AUTOCONF="autoconf"
# On OSX, it's glibtoolize
LIBTOOLIZE=$(which libtoolize)
if [ "$LIBTOOLIZE" = "" ]; then
LIBTOOLIZE=$(which glibtoolize)
fi
if [ "$LIBTOOLIZE" = "" ]; then
echo "CANNOT CONTINUE! MISSING (G)LIBTOOLIZE! Install libtool!" >&2
exit 2
fi
case "x$1" in
xinit)
[ -d m4 ] || mkdir m4
set -x
autoheader
aclocal
$LIBTOOLIZE --force --copy --automake
autoconf --force
automake --foreign --copy --add-missing -Woverride
;;
xclean)
echo 'cleaning...'
make distclean >/dev/null 2>&1
rm -rf autom4te.cache
for fn in aclocal.m4 configure config.guess config.sub depcomp install-sh \
ltmain.sh libtool missing mkinstalldirs config.log config.status Makefile; do
rm -f $fn
done
find . -name Makefile.in -exec rm -f {} \;
find . -name Makefile -exec rm -f {} \;
find . -name .deps -prune -exec rm -rf {} \;
echo 'done'
;;
*)
./configure
;;
esac

62
configure.ac Normal file
View File

@@ -0,0 +1,62 @@
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
m4_define([lft_major_version], [0])
m4_define([lft_minor_version], [9])
m4_define([lft_micro_version], [8])
m4_define([libfaketime_version],
[lft_major_version.lft_minor_version.lft_micro_version])
AC_PREREQ([2.68])
AC_INIT([libfaketime], [libfaketime_version])
AC_SUBST([LIBTOOL_DEPS])
#AC_CONFIG_MACRO_DIRS([m4])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AM_CONDITIONAL(MACOS, test `uname` = "Darwin")
AM_CONDITIONAL(SOLARIS, test `uname` = "SunOS")
eval PREFIX=`test "$prefix" = NONE && prefix=$ac_default_prefix; eval echo "${prefix}"`
eval LIBPREFIX="$PREFIX/lib"
LIBFAKETIME_MAJOR_VERSION=lft_major_version
AC_SUBST(PREFIX)
AC_SUBST(LIBPREFIX)
AC_SUBST(LIBVERSION)
AC_DEFINE_UNQUOTED(PREFIX, "$PREFIX", [The install prefix for the package])
AC_DEFINE_UNQUOTED(LIBPREFIX, "$LIBPREFIX", [The install prefix for libraries])
AC_DEFINE(LIBVERSION, ["lft_major_version"], [The library version number])
AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADERS([config.h])
# libtool versioning
LIBFAKETIME_VERSION=libfaketime_version
AC_SUBST(LIBFAKETIME_VERSION)
# Checks for programs.
AC_PROG_CC
AM_PROG_AR
# Checks for libraries.
AC_CHECK_LIB([c], [timespecadd], [timespecmul])
## FORESHADOWING...
## AC_CHECK_LIB([cunit], [CU_assertImplementation])
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h sys/param.h unistd.h stdbool.h time.h netinet/in.h math.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT32_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CHECK_FUNCS([memset])
LT_INIT
AC_CONFIG_FILES([Makefile src/Makefile test/Makefile man/Makefile])
AC_OUTPUT

View File

@@ -1,14 +0,0 @@
INSTALL ?= install
PREFIX ?= /usr/local
all:
install:
$(INSTALL) -Dm0644 faketime.1 "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
gzip -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
uninstall:
rm -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1.gz"
.PHONY: all install uninstall

View File

@@ -1,15 +0,0 @@
INSTALL ?= install
PREFIX ?= /usr/local
all:
install:
$(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/share/man/man1"
$(INSTALL) -m0644 faketime.1 "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
gzip -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
uninstall:
rm -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1.gz"
.PHONY: all install uninstall

18
man/Makefile.am Normal file
View File

@@ -0,0 +1,18 @@
ACLOCAL_AMFLAGS=-I m4
dist_man_MANS = faketime.1
# INSTALL ?= install
#
# PREFIX ?= /usr/local
#
# all:
#
# install:
# $(INSTALL) -Dm0644 faketime.1 "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
# gzip -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
#
# uninstall:
# rm -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1.gz"
#
# .PHONY: all install uninstall

View File

@@ -1,75 +0,0 @@
#
# 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
# possible caching side-effects in a multithreaded environment
# without this, but the performance impact may require you to
# try it unsynchronized.
#
# FAKE_SLEEP
# - Also intercept sleep(), nanosleep(), usleep(), alarm(), [p]poll()
#
# * 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.
#
# By default, libfaketime will be compiled for your system's default architecture.
# To build for a different architecture, add -arch flags to CFLAGS and LDFLAGS.
#
# default to clang to support thread local variables
CC ?= clang
INSTALL ?= install
PREFIX ?= /usr/local
CFLAGS += -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -DPREFIX='"'${PREFIX}'"' $(FAKETIME_COMPILE_CFLAGS)
LIB_LDFLAGS += -dynamiclib -current_version 0.9.8 -compatibility_version 0.7
SONAME = 1
LIBS = libfaketime.${SONAME}.dylib
BINS = faketime
all: ${LIBS} ${BINS}
libfaketime.${SONAME}.dylib: libfaketime.c
${CC} -o $@ ${CFLAGS} ${LDFLAGS} ${LIB_LDFLAGS} -install_name ${PREFIX}/lib/faketime/$@ $<
faketime: faketime.c
${CC} -o $@ ${CFLAGS} ${LDFLAGS} $<
clean:
@rm -f ${OBJ} ${LIBS} ${BINS}
distclean: clean
@echo
install: ${LIBS} ${BINS}
@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 "${DESTDIR}${PREFIX}/bin"
$(INSTALL) -m0755 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

39
src/Makefile.am Normal file
View File

@@ -0,0 +1,39 @@
ACLOCAL_AMFLAGS=-I m4
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIBOBJDIR = "."
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status libtool
AM_CFLAGS =-DFAKE_SLEEP -DFAKE_INTERNAL_CALLS
AM_LDFLAGS =
if SOLARIS
AM_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=600
AM_LDFLAGS += -Wl,--version-script=@srcdir@/libfaketime.map
endif
if !MACOS
AM_CFLAGS += -std=gnu99 -Wall -Wextra -Werror -DFAKE_STAT -DFAKE_PTHREAD -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -Wno-nonnull-compare
endif
LTCFLAGS=""
EXTRA_DIST=libfaketime.map
lib_LTLIBRARIES = libfaketime.la libfaketimeMT.la
libfaketime_la_SOURCES = libfaketime.c
libfaketimeMT_la_SOURCES = libfaketime.c
noinst_HEADERS = faketime_common.h sunos_endian.h time_ops.h uthash.h
bin_PROGRAMS = faketime
faketime_SOURCES = faketime.c
if MACOS
libfaketime_la_LDFLAGS = -dynamiclib -current_version 0.9.8 -compatibility_version 0.7
else
libfaketime_la_LIBADD = -ldl -lm -lrt -lpthread
libfaketime_la_LDFLAGS = -shared -Wl,--version-script=@srcdir@/libfaketime.map
libfaketimeMT_la_LIBADD = -ldl -lm -lrt -lpthread
libfaketimeMT_la_CFLAGS = -DPTHREAD_SINGLETHREADED_TIME
libfaketimeMT_la_LDFLAGS = -shared -Wl,--version-script=@srcdir@/libfaketime.map -DPTHREAD_SINGLETHREADED_TIME
faketime_LDADD = -ldl -lm -lrt -lpthread
endif

View File

@@ -30,6 +30,9 @@
# FAKE_PTHREAD
# - Intercept pthread_cond_timedwait
#
# FAKE_SETTIME
# - Intercept clock_settime(), settimeofday(), and adjtime()
#
# FORCE_MONOTONIC_FIX
# - If the test program hangs forever on
# " pthread_cond_timedwait: CLOCK_MONOTONIC test
@@ -76,7 +79,7 @@ endif
LIB_LDFLAGS += -shared
LDFLAGS += -lpthread
LDFLAGS += $(FAKETIME_LINK_FLAGS) -lpthread
ifneq ($(PLATFORM),SunOS)
LDFLAGS += -Wl,--version-script=libfaketime.map
endif

View File

@@ -47,8 +47,9 @@
#include <semaphore.h>
#include "faketime_common.h"
#include "config.h"
const char version[] = "0.9.7";
const char version[] = VERSION;
#ifdef __APPLE__
static const char *date_cmd = "gdate";
@@ -295,19 +296,21 @@ int main (int argc, char **argv)
{
char *ftpl_path;
#ifdef __APPLE__
ftpl_path = PREFIX "/libfaketime.1.dylib";
FILE *check;
check = fopen(ftpl_path, "ro");
if (check == NULL)
{
ftpl_path = PREFIX "/lib/faketime/libfaketime.1.dylib";
if (!getenv("DYLD_INSERT_LIBRARIES") && !getenv("DYLD_FORCE_FLAT_NAMESPACE")) {
ftpl_path = LIBPREFIX "/libfaketime." LIBVERSION ".dylib";
FILE *check;
check = fopen(ftpl_path, "ro");
if (check == NULL)
{
ftpl_path = PREFIX "/lib/faketime/libfaketime." LIBVERSION ".dylib";
}
else
{
fclose(check);
}
setenv("DYLD_INSERT_LIBRARIES", ftpl_path, true);
setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", true);
}
else
{
fclose(check);
}
setenv("DYLD_INSERT_LIBRARIES", ftpl_path, true);
setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", true);
#else
{
char *ld_preload_new, *ld_preload = getenv("LD_PRELOAD");
@@ -318,17 +321,17 @@ int main (int argc, char **argv)
* on MultiArch platforms, such as Debian, we put a literal $LIB into LD_PRELOAD.
*/
#ifndef MULTI_ARCH
ftpl_path = PREFIX LIBDIRNAME "/libfaketimeMT.so.1";
ftpl_path = LIBPREFIX "/libfaketimeMT.so." LIBVERSION;
#else
ftpl_path = PREFIX "/$LIB/faketime/libfaketimeMT.so.1";
ftpl_path = PREFIX "/$LIB/faketime/libfaketimeMT.so." LIBVERSION;
#endif
}
else
{
#ifndef MULTI_ARCH
ftpl_path = PREFIX LIBDIRNAME "/libfaketime.so.1";
ftpl_path = LIBPREFIX "/libfaketime.so." LIBVERSION;
#else
ftpl_path = PREFIX "/$LIB/faketime/libfaketime.so.1";
ftpl_path = PREFIX "/$LIB/faketime/libfaketime.so." LIBVERSION;
#endif
}
len = ((ld_preload)?strlen(ld_preload) + 1: 0) + 1 + strlen(ftpl_path);

View File

@@ -58,4 +58,28 @@ struct ft_shared_s
#include <mach/mach_port.h>
#endif
#ifdef FAKE_SLEEP
#include <time.h>
#include <poll.h>
#include <sys/types.h>
#include <semaphore.h>
/*
* Fake sleep prototypes!
*/
struct pollfd;
int nanosleep(const struct timespec *req, struct timespec *rem);
int usleep(useconds_t usec);
unsigned int sleep(unsigned int seconds);
unsigned int alarm(unsigned int seconds);
int ppoll(struct pollfd *fds, nfds_t nfds,
const struct timespec *timeout_ts, const sigset_t *sigmask);
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
int select(int nfds, fd_set *readfds,
fd_set *writefds,
fd_set *errorfds,
struct timeval *timeout);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
#endif /* FAKE_SLEEP */
#endif

View File

@@ -44,6 +44,7 @@
#include <netinet/in.h>
#include <limits.h>
#include "config.h"
#include "uthash.h"
#include "time_ops.h"
@@ -53,6 +54,7 @@
/* pthread-handling contributed by David North, TDI in version 0.7 */
#if defined PTHREAD_SINGLETHREADED_TIME || defined FAKE_PTHREAD
#include <pthread.h>
#include <signal.h>
#endif
#include <sys/timeb.h>
@@ -110,6 +112,13 @@ typedef int clockid_t;
#define CLOCK_MONOTONIC_RAW (CLOCK_MONOTONIC + 1)
#endif
#ifdef FAKE_FILE_TIMESTAMPS
struct utimbuf {
time_t actime; /* access time */
time_t modtime; /* modification time */
};
#endif
/*
* Per thread variable, which we turn on inside real_* calls to avoid modifying
* time multiple times of for the whole process to prevent faking time
@@ -170,7 +179,7 @@ static int (*real_timer_gettime_233) (timer_t timerid,
#ifdef FAKE_SLEEP
static int (*real_nanosleep) (const struct timespec *req, struct timespec *rem);
#ifndef __APPLE__
static int (*real_clock_nanosleep) (clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem);
static int (*real_clock_nanosleep) (clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem);
#endif
static int (*real_usleep) (useconds_t usec);
static unsigned int (*real_sleep) (unsigned int seconds);
@@ -200,11 +209,17 @@ static int apple_clock_gettime (clockid_t clk_id, struct timespec *
static clock_serv_t clock_serv_real;
#endif
#ifdef FAKE_FILE_TIMESTAMPS
static int (*real_utimes) (const char *filename, const struct timeval times[2]);
static int (*real_utime) (const char *filename, const struct utimbuf *times);
#endif
static int initialized = 0;
/* prototypes */
static int fake_gettimeofday(struct timeval *tv);
static int fake_clock_gettime(clockid_t clk_id, struct timespec *tp);
int read_config_file();
/** Semaphore protecting shared data */
static sem_t *shared_sem = NULL;
@@ -255,6 +270,7 @@ static int fake_monotonic_clock = 1;
#endif
static int cache_enabled = 1;
static int cache_duration = 10; /* cache fake time input for 10 seconds */
static int force_cache_expiration = 0;
/*
* Static timespec to store our startup time, followed by a load-time library
@@ -285,8 +301,6 @@ static double user_rate = 1.0;
static bool user_rate_set = false;
static struct timespec user_per_tick_inc = {0, -1};
static bool user_per_tick_inc_set = false;
static bool user_per_tick_inc_set_backup = false;
enum ft_mode_t {FT_FREEZE, FT_START_AT, FT_NOOP} ft_mode = FT_FREEZE;
/* Time to fake is not provided through FAKETIME env. var. */
@@ -316,11 +330,11 @@ static void ft_shm_create(void) {
snprintf(shm_name, 255, "/faketime_shm_%ld", (long)getpid());
if (SEM_FAILED == (semN = sem_open(sem_name, O_CREAT|O_EXCL, S_IWUSR|S_IRUSR, 1)))
{ /* silently fail on platforms that do not support sem_open() */
return;
return;
}
/* create shm */
if (-1 == (shm_fdN = shm_open(shm_name, O_CREAT|O_EXCL|O_RDWR, S_IWUSR|S_IRUSR)))
{
{
perror("libfaketime: In ft_shm_create(), shm_open failed");
exit(EXIT_FAILURE);
}
@@ -329,7 +343,7 @@ static void ft_shm_create(void) {
{
perror("libfaketime: In ft_shm_create(), ftruncate failed");
exit(EXIT_FAILURE);
}
}
/* map shm */
if (MAP_FAILED == (ft_sharedN = mmap(NULL, sizeof(struct ft_shared_s), PROT_READ|PROT_WRITE,
MAP_SHARED, shm_fdN, 0)))
@@ -361,7 +375,7 @@ static void ft_shm_create(void) {
{
perror("libfaketime: In ft_shm_create(), sem_post failed");
exit(EXIT_FAILURE);
}
}
snprintf(shared_objsN, sizeof(shared_objsN), "%s %s", sem_name, shm_name);
@@ -414,6 +428,7 @@ static void ft_shm_init (void)
int ticks_shm_fd;
char sem_name[256], shm_name[256], *ft_shared_env = getenv("FAKETIME_SHARED");
sem_t *shared_semR = NULL;
static int nt=1;
/* create semaphore and shared memory locally unless it has been passed along */
if (ft_shared_env == NULL)
@@ -421,7 +436,7 @@ static void ft_shm_init (void)
ft_shm_create();
ft_shared_env = getenv("FAKETIME_SHARED");
}
/* check for stale semaphore / shared memory information */
if (ft_shared_env != NULL)
{
@@ -435,7 +450,7 @@ static void ft_shm_init (void)
ft_shm_create();
ft_shared_env = getenv("FAKETIME_SHARED");
}
else
else
{
sem_close(shared_semR);
}
@@ -452,10 +467,28 @@ static void ft_shm_init (void)
if (SEM_FAILED == (shared_sem = sem_open(sem_name, 0)))
{
perror("libfaketime: In ft_shm_init(), sem_open failed");
fprintf(stderr, "libfaketime: sem_name was %s, created locally: %s\n", sem_name, shmCreator ? "true":"false");
fprintf(stderr, "libfaketime: parsed from env: %s\n", ft_shared_env);
exit(1);
if (shmCreator)
{
perror("libfaketime: In ft_shm_init(), sem_open failed");
fprintf(stderr, "libfaketime: sem_name was %s, created locally: %s\n", sem_name, shmCreator ? "true":"false");
fprintf(stderr, "libfaketime: parsed from env: %s\n", ft_shared_env);
exit(1);
}
else
{
nt++;
if (nt > 3)
{
perror("libfaketime: In ft_shm_init(), sem_open failed and recreation attempts failed");
fprintf(stderr, "libfaketime: sem_name was %s, created locally: %s\n", sem_name, shmCreator ? "true":"false");
exit(1);
}
else{
ft_shm_init();
return;
}
}
}
if (-1 == (ticks_shm_fd = shm_open(shm_name, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)))
@@ -498,6 +531,30 @@ static void ft_cleanup (void)
}
/*
* =======================================================================
* Get monotonic faketime setting === GETENV
* =======================================================================
*/
static void get_fake_monotonic_setting(int* current_value)
{
char *tmp_env;
if ((tmp_env = getenv("FAKETIME_DONT_FAKE_MONOTONIC")) != NULL
|| (tmp_env = getenv("DONT_FAKE_MONOTONIC")) != NULL)
{
if (0 == strcmp(tmp_env, "1"))
{
(*current_value) = 0;
}
else
{
(*current_value) = 1;
}
}
}
/*
* =======================================================================
* Internal time retrieval === INTTIME
@@ -680,6 +737,7 @@ static bool load_time(struct timespec *tp)
#include <sys/stat.h>
static int fake_stat_disabled = 0;
static bool user_per_tick_inc_set_backup = false;
void lock_for_stat()
{
@@ -1013,6 +1071,65 @@ int __lxstat64 (int ver, const char *path, struct stat64 *buf)
}
#endif
#ifdef FAKE_FILE_TIMESTAMPS
int utime(const char *filename, const struct utimbuf *times)
{
if (!initialized)
{
ftpl_init();
}
if (NULL == real_utime)
{ /* dlsym() failed */
#ifdef DEBUG
(void) fprintf(stderr, "faketime problem: original utime() not found.\n");
#endif
return -1; /* propagate error to caller */
}
int result;
struct utimbuf ntbuf;
ntbuf.actime = times->actime - user_offset.tv_sec;
ntbuf.modtime = times->modtime - user_offset.tv_sec;
DONT_FAKE_TIME(result = real_utime(filename, &ntbuf));
if (result == -1)
{
return -1;
}
return result;
}
int utimes(const char *filename, const struct timeval times[2])
{
if (!initialized)
{
ftpl_init();
}
if (NULL == real_utimes)
{ /* dlsym() failed */
#ifdef DEBUG
(void) fprintf(stderr, "faketime problem: original utimes() not found.\n");
#endif
return -1; /* propagate error to caller */
}
int result;
struct timeval tn[2];
struct timeval user_offset2;
user_offset2.tv_sec = user_offset.tv_sec;
user_offset2.tv_usec = 0;
timersub(&times[0], &user_offset2, &tn[0]);
timersub(&times[1], &user_offset2, &tn[1]);
DONT_FAKE_TIME(result = real_utimes(filename, tn));
if (result == -1)
{
return -1;
}
return result;
}
#endif
/*
* =======================================================================
* Faked system functions: sleep/alarm/poll/timer related === FAKE(SLEEP)
@@ -1892,10 +2009,32 @@ int gettimeofday(struct timeval *tv, void *tz)
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
int result;
static int recursion_depth = 0;
if (!initialized)
{
ftpl_init();
recursion_depth++;
if (recursion_depth == 2)
{
fprintf(stderr, "libfaketime: Unexpected recursive calls to clock_gettime() without proper initialization. Trying alternative.\n");
DONT_FAKE_TIME(ftpl_init()) ;
}
else if (recursion_depth == 3)
{
fprintf(stderr, "libfaketime: Cannot recover from unexpected recursive calls to clock_gettime().\n");
fprintf(stderr, "libfaketime: Please check whether any other libraries are in use that clash with libfaketime.\n");
fprintf(stderr, "libfaketime: Returning -1 on clock_gettime() to break recursion now... if that does not work, please check other libraries' error handling.\n");
if (tp != NULL)
{
tp->tv_sec = 0;
tp->tv_nsec = 0;
}
return -1;
}
else {
ftpl_init();
}
recursion_depth--;
}
/* sanity check */
if (tp == NULL)
@@ -2064,7 +2203,7 @@ parse_modifiers:
{
user_rate = atof(strchr(user_faked_time, 'x')+1);
user_rate_set = true;
if (NULL != getenv("FAKETIME_XRESET")) {
if (NULL != getenv("FAKETIME_XRESET")) {
if (ftpl_timecache.real.tv_nsec >= 0) {
user_faked_time_timespec.tv_sec = ftpl_faketimecache.real.tv_sec;
user_faked_time_timespec.tv_nsec = ftpl_faketimecache.real.tv_nsec;
@@ -2079,7 +2218,7 @@ parse_modifiers:
ftpl_starttime.boot.tv_nsec = ftpl_timecache.boot.tv_nsec;
#endif
}
}
}
}
else if (NULL != (tmp_time_fmt = strchr(user_faked_time, 'i')))
{
@@ -2132,6 +2271,10 @@ static void ftpl_init(void)
real_lstat64 = dlsym(RTLD_NEXT, "__lxstat64");
real_time = dlsym(RTLD_NEXT, "time");
real_ftime = dlsym(RTLD_NEXT, "ftime");
#ifdef FAKE_FILE_TIMESTAMPS
real_utimes = dlsym(RTLD_NEXT, "utimes");
real_utime = dlsym(RTLD_NEXT, "utime");
#endif
#if defined(__alpha__) && defined(__GLIBC__)
real_gettimeofday = dlvsym(RTLD_NEXT, "gettimeofday", "GLIBC_2.1");
#else
@@ -2249,14 +2392,7 @@ static void ftpl_init(void)
cache_enabled = 0;
}
}
if ((tmp_env = getenv("FAKETIME_DONT_FAKE_MONOTONIC")) != NULL
|| (tmp_env = getenv("DONT_FAKE_MONOTONIC")) != NULL)
{
if (0 == strcmp(tmp_env, "1"))
{
fake_monotonic_clock = 0;
}
}
get_fake_monotonic_setting(&fake_monotonic_clock);
/* Check whether we actually should be faking the returned timestamp. */
/* We can prevent faking time for specified commands */
@@ -2451,6 +2587,10 @@ static void ftpl_init(void)
parse_config_file = false;
parse_ft_string(tmp_env);
}
else
{
read_config_file();
}
dont_fake = dont_fake_final;
}
@@ -2486,13 +2626,62 @@ static void remove_trailing_eols(char *line)
*/
#ifdef PTHREAD_SINGLETHREADED_TIME
/*
* To avoid a deadlock if a faketime function is interrupted by a signal while
* holding the lock, we block all signals while the mutex is locked.
* The original_mask field is used to restore the previous set of signals
* after the lock has been released.
* (Prompted by issues with parallel garbage collection in D 2.090. D uses signals
* to freeze all but one thread. The frozen threads may be in faketime operations.)
*/
struct LockedState {
pthread_mutex_t *mutex;
sigset_t original_mask;
};
static void pthread_cleanup_mutex_lock(void *data)
{
pthread_mutex_t *mutex = data;
pthread_mutex_unlock(mutex);
struct LockedState *state = data;
pthread_mutex_unlock(state->mutex);
pthread_sigmask(SIG_SETMASK, &state->original_mask, NULL);
}
#endif
int read_config_file()
{
static char user_faked_time[BUFFERLEN]; /* changed to static for caching in v0.6 */
static char custom_filename[BUFSIZ];
static char filename[BUFSIZ];
FILE *faketimerc;
/* 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,
* Jacob Moorman, and Wayne Davison of SourceForge, Inc. in version 0.6 */
(void) snprintf(custom_filename, BUFSIZ, "%s", getenv("FAKETIME_TIMESTAMP_FILE"));
(void) snprintf(filename, BUFSIZ, "%s/.faketimerc", getenv("HOME"));
if ((faketimerc = fopen(custom_filename, "rt")) != NULL ||
(faketimerc = fopen(filename, "rt")) != NULL ||
(faketimerc = fopen("/etc/faketimerc", "rt")) != NULL)
{
static char line[BUFFERLEN];
while(fgets(line, BUFFERLEN, faketimerc) != NULL)
{
if ((strlen(line) > 1) && (line[0] != ' ') &&
(line[0] != '#') && (line[0] != ';'))
{
remove_trailing_eols(line);
strncpy(user_faked_time, line, BUFFERLEN-1);
user_faked_time[BUFFERLEN-1] = 0;
break;
}
}
fclose(faketimerc);
parse_ft_string(user_faked_time);
return 1;
}
return 0;
}
int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
{
/* variables used for caching, introduced in version 0.6 */
@@ -2518,10 +2707,20 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
/* Sanity check by Karl Chan since v0.8 */
if (tp == NULL) return -1;
// {ret = value; goto abort;} to call matching pthread_cleanup_pop and return value
int ret = INT_MAX;
#ifdef PTHREAD_SINGLETHREADED_TIME
static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER;
// block all signals while locked. prevents deadlocks if signal interrupts in in mid-operation.
sigset_t all_signals, original_mask;
sigfillset(&all_signals);
pthread_sigmask(SIG_SETMASK, &all_signals, &original_mask);
pthread_mutex_lock(&time_mutex);
pthread_cleanup_push(pthread_cleanup_mutex_lock, &time_mutex);
struct LockedState state = { .mutex = &time_mutex, .original_mask = original_mask };
pthread_cleanup_push(pthread_cleanup_mutex_lock, &state);
#endif
if ((limited_faking &&
@@ -2566,10 +2765,14 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
{
/* Check whether we actually should be faking the returned timestamp. */
/* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu\n", (*time_tptr - ftpl_starttime), callcounter); */
if ((ft_start_after_secs != -1) && (tmp_ts.tv_sec < ft_start_after_secs)) return 0;
if ((ft_stop_after_secs != -1) && (tmp_ts.tv_sec >= ft_stop_after_secs)) return 0;
if ((ft_start_after_ncalls != -1) && (callcounter < ft_start_after_ncalls)) return 0;
if ((ft_stop_after_ncalls != -1) && (callcounter >= ft_stop_after_ncalls)) return 0;
if (((ft_start_after_secs != -1) && (tmp_ts.tv_sec < ft_start_after_secs))
|| ((ft_stop_after_secs != -1) && (tmp_ts.tv_sec >= ft_stop_after_secs))
|| ((ft_start_after_ncalls != -1) && (callcounter < ft_start_after_ncalls))
|| ((ft_stop_after_ncalls != -1) && (callcounter >= ft_stop_after_ncalls)))
{
ret = 0;
goto abort;
}
/* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu continues\n", (*time_tptr - ftpl_starttime), callcounter); */
}
@@ -2607,6 +2810,12 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
cache_expired = 1;
}
if (force_cache_expiration != 0)
{
cache_expired = 1;
force_cache_expiration = 0;
}
if (cache_expired == 1)
{
static char user_faked_time[BUFFERLEN]; /* changed to static for caching in v0.6 */
@@ -2631,42 +2840,22 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
/* fake time supplied as environment variable? */
if (parse_config_file)
{
char custom_filename[BUFSIZ];
char filename[BUFSIZ];
FILE *faketimerc;
/* 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,
* Jacob Moorman, and Wayne Davison of SourceForge, Inc. in version 0.6 */
(void) snprintf(custom_filename, BUFSIZ, "%s", getenv("FAKETIME_TIMESTAMP_FILE"));
(void) snprintf(filename, BUFSIZ, "%s/.faketimerc", getenv("HOME"));
if ((faketimerc = fopen(custom_filename, "rt")) != NULL ||
(faketimerc = fopen(filename, "rt")) != NULL ||
(faketimerc = fopen("/etc/faketimerc", "rt")) != NULL)
{
char line[BUFFERLEN];
while(fgets(line, BUFFERLEN, faketimerc) != NULL)
{
if ((strlen(line) > 1) && (line[0] != ' ') &&
(line[0] != '#') && (line[0] != ';'))
{
remove_trailing_eols(line);
strncpy(user_faked_time, line, BUFFERLEN-1);
user_faked_time[BUFFERLEN-1] = 0;
break;
}
}
fclose(faketimerc);
}
if (read_config_file() == 0) parse_ft_string(user_faked_time);
} /* read fake time from file */
parse_ft_string(user_faked_time);
else
{
parse_ft_string(user_faked_time);
}
/* read monotonic faketime setting from envar */
get_fake_monotonic_setting(&fake_monotonic_clock);
} /* cache had expired */
if (infile_set)
{
if (load_time(tp))
{
return 0;
ret = 0;
goto abort;
}
}
@@ -2729,12 +2918,16 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
break;
default:
return -1;
ret = -1;
goto abort;
} // end of switch(ft_mode)
abort:
#ifdef PTHREAD_SINGLETHREADED_TIME
pthread_cleanup_pop(1);
#endif
// came here via goto abort?
if (ret != INT_MAX) return ret;
save_time(tp);
/* Cache this most recent real and faked time we encountered */
@@ -2768,7 +2961,7 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
ftpl_faketimecache.boot.tv_nsec = tp->tv_nsec;
}
#endif
return 0;
}
@@ -3017,6 +3210,17 @@ int pthread_cond_init_232(pthread_cond_t *restrict cond, const pthread_condattr_
clockid_t clock_id;
int result;
if (!initialized)
{
ftpl_init();
}
if (NULL == real_pthread_cond_init_232)
{ /* dlsym() failed */
#ifdef DEBUG
(void) fprintf(stderr, "faketime problem: original pthread_cond_init (@@GLIBC_2.3.2, fallback) not found.\n");
#endif
return -1; /* propagate error to caller */
}
result = real_pthread_cond_init_232(cond, attr);
if (result != 0 || attr == NULL)
@@ -3157,7 +3361,7 @@ int pthread_cond_timedwait_232(pthread_cond_t *cond, pthread_mutex_t *mutex, con
}
__asm__(".symver pthread_cond_timedwait_225, pthread_cond_timedwait@GLIBC_2.2.5");
#ifdef __ARM_ARCH
#if defined __ARM_ARCH || defined FORCE_PTHREAD_NONVER
__asm__(".symver pthread_cond_timedwait_232, pthread_cond_timedwait@@");
__asm__(".symver pthread_cond_init_232, pthread_cond_init@@");
__asm__(".symver pthread_cond_destroy_232, pthread_cond_destroy@@");
@@ -3169,6 +3373,89 @@ __asm__(".symver pthread_cond_destroy_232, pthread_cond_destroy@@GLIBC_2.3.2");
#endif
/*
* Intercept calls to time-setting functions if compiled with FAKE_SETTIME set.
* Based on suggestion and prototype by @ojura, see https://github.com/wolfcw/libfaketime/issues/179
*/
#ifdef FAKE_SETTIME
int clock_settime(clockid_t clk_id, const struct timespec *tp) {
/* only CLOCK_REALTIME can be set */
if (clk_id != CLOCK_REALTIME) {
errno = EPERM;
return -1;
}
/* sanity check for the pointer */
if (tp == NULL) {
errno = EFAULT;
return -1;
}
/* When setting the FAKETIME environment variable to the new timestamp,
we do not have to care about 'x' or 'i' modifiers given previously,
as they are not erased when parsing them. */
struct timespec current_time;
DONT_FAKE_TIME(clock_gettime(clk_id, &current_time))
;
time_t sec_diff = tp->tv_sec - current_time.tv_sec;
long nsec_diff = tp->tv_nsec - current_time.tv_nsec;
char newenv_string[256];
double offset = (double) sec_diff;
offset += (double) nsec_diff/SEC_TO_nSEC;
snprintf(newenv_string, 255, "%+f", offset);
setenv("FAKETIME", newenv_string, 1);
force_cache_expiration = 1; /* make sure it becomes effective immediately */
return 0;
}
int settimeofday(const struct timeval *tv, void *tz)
{
/* The use of timezone *tz is obsolete and simply ignored here. */
if (tz == NULL) tz = NULL;
if (tv == NULL)
{
errno = EFAULT;
return -1;
}
else
{
struct timespec tp;
tp.tv_sec = tv->tv_sec;
tp.tv_nsec = tv->tv_usec * 1000;
clock_settime(CLOCK_REALTIME, &tp);
}
return 0;
}
int adjtime (const struct timeval *delta, struct timeval *olddelta)
{
/* Always signal true full success when olddelta is requested. */
if (olddelta != NULL)
{
olddelta->tv_sec = 0;
olddelta->tv_usec = 0;
}
if (delta != NULL)
{
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
tp.tv_sec += delta->tv_sec;
tp.tv_nsec += delta->tv_usec * 1000;
/* This actually will make the clock jump instead of gradually
adjusting it, but we fulfill the caller's intention and an
additional thread just for the gradual changes does not seem
to be worth the effort presently. */
clock_settime(CLOCK_REALTIME, &tp);
}
return 0;
}
#endif
/*
* Editor modelines

View File

@@ -60,9 +60,9 @@
#define timermul2(tvp, c, result, prefix) \
do \
{ \
long long tmp_time; \
tmp_time = (c) * ((tvp)->tv_sec * SEC_TO_##prefix##SEC + \
(tvp)->tv_##prefix##sec); \
int64_t tmp_time; \
tmp_time = (c) * (int64_t) ((tvp)->tv_sec * SEC_TO_##prefix##SEC + \
(int64_t) (tvp)->tv_##prefix##sec); \
(result)->tv_##prefix##sec = tmp_time % SEC_TO_##prefix##SEC; \
(result)->tv_sec = (tmp_time - (result)->tv_##prefix##sec) / \
SEC_TO_##prefix##SEC; \
@@ -89,16 +89,28 @@
#ifndef timersub
#define timersub(a, b, result) timersub2(a, b, result, u)
#endif
#ifndef timersub
#ifndef timermul
#define timermul(a, c, result) timermul2(a, c, result, u)
#endif
/* ops for nanosecs */
#ifndef timespecisset
#define timespecisset(tvp) timerisset2(tvp,n)
#endif
#ifndef timespecclear
#define timespecclear(tvp) timerclear2(tvp, n)
#endif
#ifndef timespeccmp
#define timespeccmp(a, b, CMP) timercmp2(a, b, CMP, n)
#endif
#ifndef timespecadd
#define timespecadd(a, b, result) timeradd2(a, b, result, n)
#endif
#ifndef timespecsub
#define timespecsub(a, b, result) timersub2(a, b, result, n)
#endif
#ifndef timespecmul
#define timespecmul(a, c, result) timermul2(a, c, result, n)
#endif
#endif

View File

@@ -1,31 +0,0 @@
CC = gcc
CFLAGS = -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra $(FAKETIME_COMPILE_CFLAGS)
LDFLAGS = -lrt -lpthread
SRC = timetest.c
OBJ = ${SRC:.c=.o}
all: timetest test
.c.o:
${CC} -c ${CFLAGS} $<
timetest: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
test: timetest functest
@echo
@./test.sh
# run functional tests
functest:
./testframe.sh functests
clean:
@rm -f ${OBJ} timetest
distclean: clean
@echo
.PHONY: all test clean distclean

View File

@@ -1,30 +0,0 @@
CC ?= clang
CFLAGS += -std=gnu99 -Wall -DFAKE_STAT $(FAKETIME_COMPILE_CFLAGS)
SRC = timetest.c
OBJ = ${SRC:.c=.o}
all: timetest test
.c.o:
${CC} -c ${CFLAGS} $<
timetest: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
test: timetest functest
@echo
@./test_OSX.sh
# run functional tests
functest:
./testframe.sh functests
clean:
@rm -f ${OBJ} timetest
distclean: clean
@echo
.PHONY: all test clean distclean

29
test/Makefile.am Normal file
View File

@@ -0,0 +1,29 @@
AM_CPPFLAGS =-DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -I@top_srcdir@/src
AM_CFLAGS =
AM_LDFLAGS =
# functests.sh fail for me, test.sh hangs for me.
# TESTS = test.sh functests.sh
check_PROGRAMS = timetest
timetest_SOURCES = timetest.c
check_SCRIPTS = functests.sh testframe.sh test.sh
EXTRA_DIST = $(check_SCRIPTS) \
functests/common.inc \
functests/dont_test_false.sh \
functests/test_exclude_mono.sh \
functests/test_null.sh \
functests/test_true.sh \
functests/test_walkone.sh
if SOLARIS
AM_CPPFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=600
AM_LDFLAGS += -Wl,--version-script=libfaketime.map
endif
if !MACOS
AM_CPPFLAGS += -DFAKE_STAT -DFAKE_PTHREAD -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS
AM_CFLAGS += -std=gnu99 -Wall -Wextra -Werror -fPIC -Wno-nonnull-compare
timetest_LDADD = -ldl -lm -lrt -lpthread
endif

7
test/functests.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
set -e
[ "${srcdir}" ] || srcdir=.
# run functional tests
# cd "${srcdir}/"
${srcdir}/testframe.sh ${srcdir}/functests

View File

@@ -1,5 +1,8 @@
# libfaketime-specific common support routines for tests
LIB_BUILD_PATH="../src/$(grep 'LT_OBJDIR' ../config.h | cut -d'"' -f2)"
LIBFAKETIME_LA=$(find "$LIB_BUILD_PATH" | grep 'libfaketime\.\(dylib\|so\)$')
# say which *_fakecmd wrapper to use
platform()
{
@@ -19,7 +22,7 @@ platform()
mac_fakecmd()
{
typeset timestring="$1"; shift
typeset fakelib=../src/libfaketime.1.dylib
typeset fakelib="$LIBFAKETIME_LA"
export DYLD_INSERT_LIBRARIES=$fakelib
export DYLD_FORCE_FLAT_NAMESPACE=1
FAKETIME="$timestring" \
@@ -29,7 +32,7 @@ mac_fakecmd()
sunos_fakecmd()
{
typeset timestring="$1"; shift
typeset fakelib=../src/libfaketime.so.1
typeset fakelib="$LIBFAKETIME_LA"
export LD_PRELOAD=$fakelib
FAKETIME="$timestring" \
"$@"
@@ -39,7 +42,7 @@ sunos_fakecmd()
linuxlike_fakecmd()
{
typeset timestring="$1"; shift
typeset fakelib=../src/libfaketime.so.1
typeset fakelib="$LIBFAKETIME_LA"
export LD_PRELOAD=$fakelib
FAKETIME="$timestring" \
"$@"

View File

@@ -1,14 +1,38 @@
#!/bin/sh
##################################################################
# NOTICE: #
# When you edit this script, maintain compatibility with BASH 3. #
# This is the version that Apple distributes. #
##################################################################
LIB_BUILD_PATH="../src/$(grep 'LT_OBJDIR' ../config.h | cut -d'"' -f2)"
LIBFAKETIME_LA=$(find "$LIB_BUILD_PATH" | grep 'libfaketime\.\(dylib\|so\)$')
set_libfaketime() {
the_path="$LIBFAKETIME_LA"
if [ "$(uname)" = "Darwin" ]; then
export DYLD_INSERT_LIBRARIES="$the_path"
export DYLD_FORCE_FLAT_NAMESPACE=1
else
export LD_PRELOAD="$the_path"
fi
}
echo $(set_libfaketime)
if [ -f /etc/faketimerc ] ; then
echo "Running the test program with your system-wide default in /etc/faketimerc"
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 ./timetest"
LD_PRELOAD=../src/libfaketime.so.1 ./timetest
echo "\$ $(set_libfaketime) ./timetest"
set_libfaketime
./timetest
echo
else
echo "Running the test program with no faked time specified"
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 ./timetest"
LD_PRELOAD=../src/libfaketime.so.1 ./timetest
echo "\$ $(set_libfaketime) ./timetest"
set_libfaketime
./timetest
echo
fi
@@ -16,48 +40,62 @@ echo "==========================================================================
echo
echo "Running the test program with absolute date 2003-01-01 10:00:05 specified"
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="2003-01-01 10:00:05" ./timetest
echo "\$ $(set_libfaketime) FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
set_libfaketime
export FAKETIME="2003-01-01 10:00:05"
./timetest
echo
echo "============================================================================="
echo
echo "Running the test program with START date @2005-03-29 14:14:14 specified"
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="@2005-03-29 14:14:14" ./timetest
echo "\$ $(set_libfaketime) FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
set_libfaketime
export FAKETIME="@2005-03-29 14:14:14"
./timetest
echo
echo "============================================================================="
echo
echo "Running the test program with 10 days negative offset specified"
echo "LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-10d\" ./timetest"
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-10d" ./timetest
echo "$(set_libfaketime) FAKETIME=\"-10d\" ./timetest"
set_libfaketime
export FAKETIME="-10d"
./timetest
echo
echo "============================================================================="
echo
echo "Running the test program with 10 days negative offset specified, and FAKE_STAT disabled"
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-10d" NO_FAKE_STAT=1 ./timetest
echo "\$ $(set_libfaketime) FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
set_libfaketime
export FAKETIME="-10d"
export NO_FAKE_STAT=1
./timetest
echo
echo "============================================================================="
echo
echo "Running the test program with 10 days positive offset specified, and speed-up factor"
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"+10d x1\" ./timetest"
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="+10d x1" NO_FAKE_STAT=1 ./timetest
echo "Running the test program with 10 days positive offset specified, and sped up 2 times"
echo "\$ $(set_libfaketime) FAKETIME=\"+10d x2\" ./timetest"
set_libfaketime
export FAKETIME="+10d x2"
export NO_FAKE_STAT=1
./timetest
echo
echo "============================================================================="
echo
echo "Running the 'date' command with 15 days negative offset specified"
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-15d\" date"
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-15d" date
echo "\$ $(set_libfaketime) FAKETIME=\"-15d\" date"
set_libfaketime
export FAKETIME="-15d"
date
echo
echo "============================================================================="

View File

@@ -1,52 +0,0 @@
#!/bin/sh
export DYLD_FORCE_FLAT_NAMESPACE=1
export DYLD_INSERT_LIBRARIES=../src/libfaketime.1.dylib
if [ -f /etc/faketimerc ] ; then
echo "Running the test program with your system-wide default in /etc/faketimerc"
./timetest
echo
else
echo "Running the test program with no faked time specified"
./timetest
echo
fi
echo "Running the test program with absolute date 2003-01-01 10:00:05 specified"
echo "FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
FAKETIME="2003-01-01 10:00:05" ./timetest
echo
echo "Running the test program with START date @2005-03-29 14:14:14 specified"
echo "FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
FAKETIME="@2005-03-29 14:14:14" ./timetest
echo
echo "Running the test program with 10 days negative offset specified"
echo "FAKETIME=\"-10d\" ./timetest"
FAKETIME="-10d" ./timetest
echo
# FAKE_STAT is disabled on macOS by default, so testing NO_FAKE_STAT is not useful
#echo "Running the test program with 10 days negative offset specified, and FAKE_STAT disabled"
#echo "FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
#FAKETIME="-10d" NO_FAKE_STAT=1 ./timetest
#echo
echo "Running the test program with 10 days positive offset specified, and sped up 2 times"
echo "FAKETIME=\"+10d x2\" ./timetest"
FAKETIME="+10d x2" NO_FAKE_STAT=1 ./timetest
echo
# On more recent macOS versions, the following won't work without copying gdate
# to a different folder beforehand. We don't do that here, and since the output
# of these tests must be reviewed manually anyway, the timetest binary should be
# sufficient to determine whether everything works as planned.
#echo "Running the 'date' command with 15 days negative offset specified"
#echo "FAKETIME=\"-15d\" date"
#FAKETIME="-15d" date
#echo
exit 0

View File

@@ -6,6 +6,8 @@
# see README.testframe.txt for details.
#
testframedir="${BASH_SOURCE%/*}"
# echo labelled error/warning message to stderr
report()
{
@@ -33,7 +35,7 @@ run_testsuite()
# add testsuite dir to PATH for convenience
typeset dir=$(dirname $testsuite)
PATH=$dir:$PATH
. testframe.inc
. $testframedir/testframe.inc
if [ -f $dir/common.inc ]; then
. $dir/common.inc
fi

View File

@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
@@ -115,6 +116,7 @@ void* pthread_test(void* args)
}
#endif
#include "faketime_common.h"
int main (int argc, char **argv)
{