7 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
64 changed files with 1094 additions and 2060 deletions

View File

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

30
.gitignore vendored
View File

@@ -1,16 +1,30 @@
*.o
*.so.1
timetest
test/getrandom_test
test/lib*.so
test/use_lib_*
test/run_*
test/repeat_random
test/getentropy_test
test/syscall_test
test/variadic_promotion
src/libfaketime.dylib.1
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

@@ -3,19 +3,15 @@ language: c
matrix:
include:
- os: linux
arch: amd64
compiler: gcc
- os: linux
arch: ppc64le
compiler: gcc
- os: osx
osx_image: xcode11
script:
- cd ${TRAVIS_BUILD_DIR}
- if [ "$TRAVIS_ARCH" = ppc64le ]; then
FAKETIME_COMPILE_CFLAGS="-DFORCE_MONOTONIC_FIX -DFORCE_PTHREAD_NONVER" make;
else
FAKETIME_COMPILE_CFLAGS="-DFORCE_MONOTONIC_FIX" make;
fi
- 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,36 +0,0 @@
INSTALL ?= install
UNAME=$(shell uname)
SELECTOR:=$(shell if test "${UNAME}" = "Darwin" ; then echo "-f Makefile.OSX" ; fi)
PREFIX ?= /usr/local
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

27
NEWS
View File

@@ -1,31 +1,10 @@
Since 0.9.9:
- improved macOS Monterey support through dyld interposing
- changed interception hooks for stat() and similar functions,
refactored to use a common handler (@sirainen)
- added support for timespec_get, timerfd_{get,set} (@sliquister)
- generic syscall() interception for selected syscalls (@dkg)
- improved testing system (@dkg)
Since 0.9.8:
- When compiled with the CFLAG FAKE_RANDOM set,
libfaketime will intercept calls to getrandom()
and return pseudorandom numbers for determinism.
The mechanism needs to be activated by setting
the environment variable FAKERANDOM_SEED to a
64-bit seed value, e.g., "0x12345678DEADBEEF".
Please note that this completely breaks the
security of random numbers for cryptographic
purposes and should only be used for deterministic
tests. Never use this in production!
- When the environment variable FAKETIME_TIMESTAMP_FILE is
set, points to a writeable (creatable) custom config file
and the environment variable FAKETIME_UPDATE_TIMESTAMP_FILE
is "1", then the file also is updated on each call. By
this, a common "virtual time" can be shared by several
processes, where each can adjust the time for all.
- 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)

144
README
View File

@@ -1,5 +1,5 @@
libfaketime, version 0.9.10 (February 2022)
===========================================
libfaketime, version 0.9.8 (August 2019)
========================================
Content of this file:
@@ -20,7 +20,6 @@ Content of this file:
i) "Limiting" libfaketime per process
j) Spawning an external process
k) Saving timestamps to file, loading them from file
l) Replacing random numbers with deterministic number sequences
5. License
6. Contact
@@ -107,8 +106,16 @@ documentation whether it can be achieved by using libfaketime directly.
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.
@@ -131,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
--------
@@ -188,21 +197,19 @@ linker configuration file, e.g., /etc/ld.so.conf.d/local.conf, and then run
the "ldconfig" command. Afterwards, using LD_PRELOAD=libfaketime.so.1 suffices.
However, also the faked time should be specified; otherwise, libfaketime will
be loaded, but just report the real system time. There are multiple ways to
be loaded, but just report the real system time. There are three ways to
specify the faked time:
a) By setting the environment variable FAKETIME.
b) By using the file given in the environment variable FAKETIME_TIMESTAMP_FILE
c) By using the file .faketimerc in your home directory.
d) By using the file /etc/faketimerc for a system-wide default.
e) By using FAKETIME_UPDATE_TIMESTAMP_FILE and date -s "<time>" or alike.
If you want to use b) c) or d), $HOME/.faketimerc or /etc/faketimerc consist of
only one line of text with exactly the same content as the FAKETIME environment
variable, which is described below. Note that /etc/faketimerc will only be used
if there is no $HOME/.faketimerc and no FAKETIME_TIMESTAMP_FILE file exists.
Also, the FAKETIME environment variable _always_ has priority over the files.
For FAKETIME_UPDATE_TIMESTAMP_FILE please see below.
4b) Using absolute dates
@@ -327,7 +334,7 @@ the same global clock without restarting it at the start of each process.
Please note that using "x" or "i" in FAKETIME still requires giving an offset
(see section 4d). This means that "+1y x2" will work, but "x2" only will not.
If you do not want to fake the time, but just modify clock speed, use something
like "+0 x2", i.e., use an explicit zero offset as a prefix in your FAKETIME.
like "+0 x2", i.e., use an explizit zero offset as a prefix in your FAKETIME.
For testing, your should run a command like
@@ -371,8 +378,7 @@ may take up to 10 seconds before the new fake time is applied. If this is a
problem in your scenario, you can change number of seconds before the file is read
again with environment variable FAKETIME_CACHE_DURATION, or disable caching at all
with FAKETIME_NO_CACHE=1. Remember that disabling the cache may negatively
influence the performance (especially when not using FAKETIME environment
but configuration files, such as FAKETIME_TIMESTAMP_FILE).
influence the performance.
Setting FAKETIME by means of a file timestamp
@@ -438,14 +444,9 @@ Cleaning up shared memory
-------------------------
libfaketime uses semaphores and shared memory on platforms that support it in
order to sync faketime settings across parent-child processes.
Please note that this does not share the time set by settimeofday (for that
see FAKETIME_UPDATE_TIMESTAMP_FILE below).
libfaketime will clean up when it exits properly.
However, when processes are terminated (e.g., by Ctrl-C on command line),
shared memory cannot be cleaned up properly. In such
order to sync faketime settings across parent-child processes. It will clean
up when it exits properly. However, when processes are terminated (e.g., by
Ctrl-C on command line), shared memory cannot be cleaned up properly. In such
cases, you should occasionally delete
/dev/shm/faketime_shm_* and
@@ -470,54 +471,9 @@ 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(). The FAKETIME environment
variable will be adjusted on each call.
When the environment variable FAKETIME_TIMESTAMP_FILE is set, points to a
writeable (creatable) custom config file and the environment variable
FAKETIME_UPDATE_TIMESTAMP_FILE is "1", then the file also is updated on each
call. By this, a common "virtual time" can be shared by several
processes, where each can adjust the time for all.
Sharing "virtual settable time" between independent processes
-------------------------------------------------------------
When libfaketime was compiled with FAKETIME_COMPILE_CFLAGS="-DFAKE_SETTIME",
it can be configured to support a common time offset for multiple processes.
This for example allows to use "ntpdate" as normal user without affecting
system clock, interactively testing software with different dates or testing
complex software with multiple independent processes that themself use
settime internally.
Examples:
$ export LD_PRELOAD=libfaketime.so.1
$ export FAKETIME_TIMESTAMP_FILE="/tmp/my-faketime.rc"
$ export FAKETIME_UPDATE_TIMESTAMP_FILE=1
$ export FAKETIME_CACHE_DURATION=1 # in seconds
# or: export FAKETIME_NO_CACHE=1
$ date -s "1999-12-24 16:00:00"
Fri Dec 24 16:00:00 CET 1999
$ LD_PRELOAD="" date
Thu Apr 9 15:19:38 CEST 2020
$ date
Fri Dec 24 16:00:02 CET 1999
$ /usr/sbin/ntpdate -u clock.isc.org
9 Apr 15:18:37 ntpdate[718]: step time server xx offset 640390517.057257 sec
$ date
Thu Apr 9 15:18:40 CEST 2020
In another terminal, script or environmment the same variables could be set
and the same time would be printed.
This also avoid the need to directly update the rc config file to use
different times, but of course only supports time offsets.
Please note that this feature is not compatible with several other features,
such as FAKETIME_FOLLOW_FILE, FAKETIME_XRESET and maybe others. After first
settime, offsets will be used in FAKETIME_TIMESTAMP_FILE, even if it
initially used advanced time specification options.
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
@@ -693,11 +649,6 @@ seconds.
4k) Saving timestamps to file, loading them from file
-----------------------------------------------------
To store and load timestamp _offsets_ using _one and the same_ file allowing
to share a common "virtual time" between independent processes, please see
FAKETIME_UPDATE_TIMESTAMP_FILE above. The FAKETIME_SAVE_FILE feature is
different.
faketime can save faked timestamps to a file specified by FAKETIME_SAVE_FILE
environment variable. It can also use the file specified by FAKETIME_LOAD_FILE
to replay timestamps from it. After consuming the whole file, libfaketime
@@ -717,41 +668,6 @@ faketime needs to be run using the faketime wrapper to use these files. This
functionality has been added by Balint Reczey in v0.9.5.
4l) Replacing random numbers with deterministic number sequences
----------------------------------------------------------------
libfaketime can be compiled with the CFLAG FAKE_RANDOM set (see src/Makefile).
When compiled this way, libfaketime additionally intercepts calls to the
function getrandom(), which currently is Linux-specific.
This functionality is intended to feed a sequence of deterministic, repeatable
numbers to applications, which use getrandom(), instead of the random numbers
provided by /dev/[u]random.
For creating the deterministic number sequence, libfaketime internally
uses Bernard Widynski's Middle Square Weyl Sequence Random Number Generator,
see https://mswsrng.wixsite.com/rand.
It requires a 64-bit seed value, which has to be passed via the environment
variable FAKERANDOM_SEED, as in, for example
LD_PRELOAD=src/libfaketime.so.1 \
FAKERANDOM_SEED="0x12345678DEADBEEF" \
test/getrandom_test
Whenever the same seed value is used, the same sequence of "random-looking"
numbers is generated.
Please be aware that this definitely breaks any security properties that
may be attributed to random numbers delivered by getrandom(), e.g., in the
context of cryptographic operations. Use it for deterministic testing
purposes only. Never use it in production.
For a discussion on why this apparently not date-/time-related function
has been added to libfaketime and how it may evolve, see Github issue #275.
5. License
----------

View File

@@ -1,17 +1,10 @@
README file for libfaketime on macOS
====================================
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! If you compiled libfaketime successfully but even the simple examples !
! with the "date" command do not seem to work, please see the notes about !
! SIP (system integrity protection) in this document! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Support for macOS has meanwhile matured and many command line and
GUI applications will run stable.
Developments and tests are done on Catalina currently.
Developments and tests are done on Mojave currently.
Version 0.9.5 and higher no longer work with OSX <= 10.6 due to
changes in the underlying system libraries. If you need libfaketime
@@ -46,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
@@ -145,13 +143,6 @@ However, there are two important aspects:
application to a non-SIP-protected path, and if libfaketime still does not
work, feel free to report it.
Please note that this also applies to simple programs such as /bin/date,
which is used as an example in the libfaketime documentation and help texts.
Again, either disable SIP on your system (which might not be the best idea),
or copy the applications / programs you want to use with libfaketime to
a different path, which is not SIP-protected, e.g., within your home directory.
- We cannot and will not help with using libfaketime for proprietary or
commercial software unless you are its developer trying to integrate
libfaketime. Please contact the developers or the vendor directly if

View File

@@ -14,10 +14,6 @@ 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.
For "make test", an optional environment variable FAKETIME_TESTLIB can
be set, pointing to the path and filename of the libfaketime library
to be used for tests; the default is "../src/libfaketime.so.1".
However, one problem makes it somewhat difficult to get libfaketime
working on different platforms:

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 -nf "${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,4 +1,4 @@
.TH FAKETIME "1" "February 2022" "faketime 0.9.10" wolfcw
.TH FAKETIME "1" "August 2019" "faketime 0.9.8" wolfcw
.SH NAME
faketime \- manipulate the system time for a given command
.SH SYNOPSIS
@@ -7,11 +7,11 @@ faketime \- manipulate the system time for a given command
.SH DESCRIPTION
.\" \fIfaketime\fR will trick the given program into seeing the specified timestamp as its starting date and time.
.PP
The given command will be tricked into believing that the current system time is the one specified in the timestamp.
Filesystem timestamps will also be reported relative to this timestamp.
The wall clock will continue to run from this date and time unless specified otherwise (see advanced options).
Actually, faketime is a simple wrapper for libfaketime, which uses the LD_PRELOAD mechanism to load a small library which intercepts system calls to functions such as \fItime(2)\fR and \fIfstat(2)\fR.
This wrapper exposes only a subset of libfaketime's functionality; please refer to the README file that came with faketime for more details and advanced options, or have a look at https://github.com/wolfcw/libfaketime
The given command will be tricked into believing that the current system time is the one specified in the timestamp. Filesystem timestamps will also be
reported relative to this timestamp. The wall clock will continue to run from this date and time unless specified otherwise (see advanced options).
Actually, faketime is a simple wrapper for libfaketime, which uses the LD_PRELOAD mechanism to load a small library which intercepts system calls to
functions such as \fItime(2)\fR and \fIfstat(2)\fR. This wrapper exposes only a subset of libfaketime's functionality; please refer to the README file
that came with faketime for more details and advanced options, or have a look at http://github.com/wolfcw/libfaketime
.SH OPTIONS
.TP
\fB\-\-help\fR
@@ -23,17 +23,11 @@ show version information and quit.
\fB\-m\fR
use the multi-threading variant of libfaketime.
.TP
\fB\-p <PID>\fR
pretend that the program's process ID is PID. (only available if built with FAKE_PID)
.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.
.TP
\fB\--date-prog <PATH>\fR
Use a specific GNU-date compatible implementation of the helper used to transform "timestamp format" strings into programmatically usable dates, instead of a compile-time default guess for the generic target platform.
.SH EXAMPLES
.nf
@@ -47,53 +41,41 @@ In this single case all spawned processes will use the same global clock without
(Please note that it depends on your locale settings whether . or , has to be used for fractional offsets)
.fi
.SH ADVANCED TIMESTAMP FORMAT
The simple timestamp format used by default applies the \fB/bin/date -d\fR command to parse user-friendly specifications such as 'last friday'.
When using the faketime option \fB\-f\fR, the timestamp specified on the command line is directly passed to libfaketime, which enables a couple of additional features such as speeding the clock up or slowing it down for the target program.
It is strongly recommended that you have a look at the libfaketime documentation.
Summary:
The simple timestamp format used by default applies the \fB/bin/date -d\fR command to parse user-friendly specifications such as 'last friday'. When using
the faketime option \fB\-f\fR, the timestamp specified on the command line is directly passed to libfaketime, which enables a couple of additional features
such as speeding the clock up or slowing it down for the target program. It is strongly recommended that you have a look at the libfaketime documentation. Summary:
.TP
Freeze clock at absolute timestamp: \fB"YYYY-MM-DD hh:mm:ss"\fR
If you want to specify an absolute point in time, exactly this format must be used.
Please note that freezing the clock is usually not what you want and may break the application.
Only use if you know what you're doing!
If you want to specify an absolute point in time, exactly this format must be used. Please note that freezing the clock is usually not what you want and may break the application. Only use if you know what you're doing!
.TP
Relative time offset: \fB"[+/-]123[m/h/d/y]"\fR, e.g., "+60m", "+2y"
This is the most often used format and specifies the faked time relatively to the current real time.
The first character of the format string \fBmust\fR be a + or a -.
The numeric value by default represents seconds, but the modifiers m, h, d, and y can be used to specify minutes, hours, days, or years, respectively.
For example, "-2y" means "two years ago". Fractional time offsets can be used, e.g., "+2,5y", which means "two and a half years in the future".
Please note that the fraction delimiter depends on your locale settings, so if "+2,5y" does not work, you might want to try "+2.5y".
Relative time offset: \fB"[+/-]123[m/h/d/y]\fR, e.g. "+60m", "+2y"
This is the most often used format and specifies the faked time relatively to the current real time. The first character of the format string \fBmust\fR be a + or a -. The numeric value by default represents seconds, but the modifiers m, h, d, and y can be used to specify minutes, hours, days, or years, respectively. For example, "-2y" means "two years ago". Fractional time offsets can be used, e.g. "+2,5y", which means "two and a half years in the future". Please note that the fraction delimiter depends on your locale settings, so if "+2,5y" does not work, you might want to try "+2.5y".
.TP
Start-at timestamps: \fB"@YYYY-MM-DD hh:mm:ss"\fR
The wall clock will start counting at the given timestamp for the program.
This can be used for specifying absolute timestamps without freezing the clock.
The wall clock will start counting at the given timestamp for the program. This can be used for specifying absolute timestamps without freezing the clock.
.SH ADVANCED USAGE
When using relative time offsets or start-at timestamps (see ADVANCED TIMESTAMP FORMAT above and option \fB\-f\fR), the clock speed can be adjusted, i.e., time may run faster or slower for the executed program.
For example, \fB"+5y x10"\fR will set the faked time 5 years into the future and make the time pass 10 times as fast (one real second equals 10 seconds measured by the program).
Similarly, the flow of time can be slowed, e.g., using \fB"-7d x0,2"\fR, which will set the faked time 7 days in the past and set the clock speed to 20 percent, i.e., it takes five real world seconds for one second measured by the program.
Again, depending on your locale, either "x2.0" or "x2,0" may be required regarding the delimiter.
You can also make faketime to advance the reported time by a preset interval upon each time() call independently from the system's time using \fB"-7d i2,0"\fR, where \fB"i"\fR is followed by the increase interval in seconds.
When using relative time offsets or start-at timestamps (see ADVANCED TIMESTAMP FORMAT above and option \fB\-f\fR), the clock speed can be adjusted, i.e. time may run faster or slower for the executed program. For example, \fB"+5y x10"\fR will set the faked time 5 years into the future and make the time pass 10 times as fast (one real second equals 10 seconds measured by the program). Similarly, the flow of time can be slowed, e.g. using \fB"-7d x0,2"\fR, which will set the faked time 7 days in the past and set the clock speed to 20 percent, i.e. it takes five real world seconds for one second measured by the program. Again, depending on your locale, either "x2.0" or "x2,0" may be required regarding the delimiter. You can also make faketime to advance the reported time by a preset interval upon each time() call independently from the system's time using \fB"-7d i2,0"\fR, where
\fB"i"\fR is followed by the increase interval in seconds.
.PP
Faking times for multiple programs or even system-wide can be simplified by using ~/.faketimerc files and /etc/faketimerc.
Please refer to the README that came with faketime for warnings and details.
Faking times for multiple programs or even system-wide can be simplified by using ~/.faketimerc files and /etc/faketimerc. Please refer to the README that came with faketime for warnings and details.
.PP
Faking of filesystem timestamps may be disabled by setting the NO_FAKE_STAT environment variable to a non-empty value.
.SH AUTHOR
Please see the README and NEWS files for contributors.
.SH BUGS
Due to limitations of the LD_PRELOAD mechanism, faketime will not work with suidroot and statically linked programs.
While timestamps and time offsets will work for child processes, speeding the clock up or slowing it down might not work for child processes spawned by the executed program as expected;
a new instance of libfaketime is used for each child process, which means that the libfaketime start time, which is used in speed adjustments, will also be re-initialized.
Some programs may dynamically load system libraries, such as librt, at run-time and therefore bypass libfaketime.
You may report programs that do not work with libfaketime, but only if they are available as open source.
While timestamps and time offsets will work for child processes, speeding the clock up or slowing it down might not
work for child processes spawned by the executed program as expected; a new instance of libfaketime is used for each
child process, which means that the libfaketime start time, which is used in speed adjustments, will also be
re-initialized. Some programs may dynamically load system libraries, such as librt, at run-time and therefore bypass libfaketime. You may report programs that do not work with libfaketime, but only if they are available as open source.
.SH "REPORTING BUGS"
Please use https://github.com/wolfcw/libfaketime/issues
.SH COPYRIGHT
Copyright \(co 2003-2021 by the libfaketime authors.
Copyright \(co 2003-2013 by the libfaketime authors.
.PP
There is NO warranty;
not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
You may redistribute copies of faketime under the terms of the GNU General Public License.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. You may redistribute copies of faketime under the
terms of the GNU General Public License.
.br
For more information about these matters, see the file named COPYING.
.SH "SEE ALSO"

View File

@@ -1,92 +0,0 @@
#
# Notes:
#
# * Compilation Defines:
#
# MACOS_DYLD_INTERPOSE
# - Use dlyd interposing instead of name-based function interception
# (required since macOS Monterey)
#
# FAKE_SLEEP
# - Also intercept sleep(), nanosleep(), usleep(), alarm(), [p]poll()
#
# FAKE_SETTIME
# - Intercept clock_settime(), settimeofday(), and adjtime()
#
# FAKE_PID
# - Enable faked values for getpid() calls through FAKETIME_FAKEPID
#
# FAKE_RANDOM
# - Intercept getentropy(). Dangerous for production use.
# See README about FAKE_RANDOM.
#
# FAKE_STAT
# - Enables time faking also for files' timestamps.
#
# FAKE_FILE_TIMESTAMPS, FAKE_UTIME
# - Enables time faking for the utime* functions. If enabled via
# FAKE_FILE_TIMESTAMPS, the faking is opt-in at runtime using
# with the FAKE_UTIME environment variable. If enabled via
# FAKE_UTIME, the faking is opt-out at runtime. Requires FAKE_STAT.
#
# 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.
#
# * 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) -DMACOS_DYLD_INTERPOSE -DFAKE_SETTIME
LIB_LDFLAGS += -dynamiclib -current_version 0.9.10 -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

@@ -1,10 +1,25 @@
#
# Notes:
#
# * Compilation Defines that are set by default:
# * Compilation Defines:
#
# FAKE_STAT
# - Enables time faking when reading files' timestamps.
# - Enables time faking also for files' timestamps.
#
# NO_ATFILE
# - Disables support for the fstatat() group of functions
#
# 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_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.
#
# FAKE_SLEEP
# - Also intercept sleep(), nanosleep(), usleep(), alarm(), [p]poll()
@@ -15,58 +30,9 @@
# FAKE_PTHREAD
# - Intercept pthread_cond_timedwait
#
# 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.
#
# PTHREAD_SINGLETHREADED_TIME (only set in libfaketimeMT.so)
# - 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.
#
# * Compilation Defines that are unset by default:
#
# FAKE_FILE_TIMESTAMPS, FAKE_UTIME
# - Enables time faking for the utime* functions. If enabled via
# FAKE_FILE_TIMESTAMPS, the faking is opt-in at runtime using
# with the FAKE_UTIME environment variable. If enabled via
# FAKE_UTIME, the faking is opt-out at runtime.
#
# NO_ATFILE
# - Disables support for the fstatat() group of functions
#
# FAKE_SETTIME
# - Intercept clock_settime(), settimeofday(), and adjtime()
#
# FAKE_RANDOM
# - Intercept getrandom()
#
# FAKE_PID
# - Intercept getpid()
#
# INTERCEPT_SYSCALL
# - (On GNU/Linux only) intercept glibc's syscall() for known relevant syscalls.
# If enabled, this currently only works to divert the getrandom syscall.
#
# - note that on unusual architectures, if INTERCEPT_SYSCALL is set, you may
# need to explicitly define variadic_promotion_t (e.g. by putting
# -Dvariadic_promotion_t=int into CFLAGS). See src/faketime_common.h for
# more info.
#
# FAKE_STATELESS
# - Remove support for any functionality that requires sharing state across
# threads of a process, or different processes. This decreases the risk of
# interference with a program's normal execution, at the cost of supporting
# fewer ways of specifying the time.
# Concretely, this currently:
# - disables PTHREAD_SINGLETHREADED_TIME, which can cause deadlocks in
# multithreaded programs that fork due to making clock_gettime not
# async-signal-safe
# - disables all shared-memory across processes
#
# FORCE_MONOTONIC_FIX
# - If the test program hangs forever on
# " pthread_cond_timedwait: CLOCK_MONOTONIC test
@@ -75,15 +41,11 @@
# (This is a platform-specific issue we cannot handle at run-time.)
#
# MULTI_ARCH
# - If MULTI_ARCH is set, the faketime wrapper program will put a literal
# - If MULTI_ARCH is set, the faketime wrapper program will put a literal
# $LIB into the LD_PRELOAD environment variable it creates, which makes
# ld automatically choose the correct library version to use for the
# target binary. Use for Linux platforms with Multi-Arch support only!
#
# SILENT
# - avoid that the faketime wrapper complains when running within a
# libfaketime environment
#
# * Compilation addition: second libMT target added for building the pthread-
# enabled library as a separate library
#
@@ -110,7 +72,7 @@ PREFIX ?= /usr/local
LIBDIRNAME ?= /lib/faketime
PLATFORM ?=$(shell uname)
CFLAGS += -std=gnu99 -Wall -Wextra -Werror -Wno-nonnull-compare -DFAKE_PTHREAD -DFAKE_STAT -DFAKE_UTIME -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' -DLIBDIRNAME='"'$(LIBDIRNAME)'"' $(FAKETIME_COMPILE_CFLAGS)
CFLAGS += -std=gnu99 -Wall -Wextra -Werror -Wno-nonnull-compare -DFAKE_PTHREAD -DFAKE_STAT -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' -DLIBDIRNAME='"'$(LIBDIRNAME)'"' $(FAKETIME_COMPILE_CFLAGS)
ifeq ($(PLATFORM),SunOS)
CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=600
endif

View File

@@ -1,7 +1,7 @@
/*
* libfaketime wrapper command
*
* This file is part of libfaketime, version 0.9.10
* This file is part of libfaketime, version 0.9.8
*
* libfaketime is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License v2 as published by the
@@ -47,10 +47,11 @@
#include <semaphore.h>
#include "faketime_common.h"
#include "config.h"
const char version[] = "0.9.10";
const char version[] = VERSION;
#if (defined __APPLE__) || (defined __sun)
#ifdef __APPLE__
static const char *date_cmd = "gdate";
#else
static const char *date_cmd = "date";
@@ -75,10 +76,6 @@ void usage(const char *name)
" -m : Use the multi-threaded version of libfaketime\n"
" -f : Use the advanced timestamp specification format (see manpage)\n"
" --exclude-monotonic : Prevent monotonic clock from drifting (not the raw monotonic one)\n"
#ifdef FAKE_PID
" -p PID : Pretend that the program's process ID is PID\n"
#endif
" --date-prog PROG : Use specified GNU-compatible implementation of 'date' program\n"
"\n"
"Examples:\n"
"%s 'last friday 5 pm' /bin/date\n"
@@ -97,11 +94,11 @@ static void cleanup_shobjs()
{
if (-1 == sem_unlink(sem_name))
{
perror("faketime: sem_unlink");
perror("sem_unlink");
}
if (-1 == shm_unlink(shm_name))
{
perror("faketime: shm_unlink");
perror("shm_unlink");
}
}
@@ -111,16 +108,8 @@ int main (int argc, char **argv)
int curr_opt = 1;
bool use_mt = false, use_direct = false;
long offset;
bool fake_pid = false;
const char *pid_val;
#ifndef SILENT
if (getenv("FAKETIME") || getenv("FAKETIME_SHARED") || getenv("FAKETIME_FAKEPID") || getenv("FAKERANDOM_SEED")) {
fprintf(stderr, "faketime: You appear to be running faketime within a libfaketime environment. Proceeding, but check for unexpected results...\n");
}
#endif
while (curr_opt < argc)
while(curr_opt < argc)
{
if (0 == strcmp(argv[curr_opt], "-m"))
{
@@ -128,16 +117,6 @@ int main (int argc, char **argv)
curr_opt++;
continue;
}
if (0 == strcmp(argv[curr_opt], "-p"))
{
fake_pid = true;
pid_val = argv[curr_opt + 1];
curr_opt += 2;
#ifndef FAKE_PID
fprintf(stderr, "faketime: -p argument probably won't work (try rebuilding with -DFAKE_PID)\n");
#endif
continue;
}
else if (0 == strcmp(argv[curr_opt], "-f"))
{
use_direct = true;
@@ -150,20 +129,6 @@ int main (int argc, char **argv)
curr_opt++;
continue;
}
else if (0 == strcmp(argv[curr_opt], "--date-prog"))
{
curr_opt++;
if (curr_opt > argc) {
// At best this avoids a segfault reading beyond the argv[]
// Realistically there would be other args (e.g. program to call)
fprintf(stderr, "faketime: --date-prog requires a further argument\n");
} else {
date_cmd = argv[curr_opt];
curr_opt++;
//fprintf(stderr, "faketime: --date-prog assigned: %s\n", date_cmd);
}
continue;
}
else if ((0 == strcmp(argv[curr_opt], "-v")) ||
(0 == strcmp(argv[curr_opt], "--version")))
{
@@ -205,10 +170,9 @@ int main (int argc, char **argv)
close(1); /* close normal stdout */
(void) (dup(pfds[1]) + 1); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
// fprintf(stderr, "faketime: using --date-prog: %s\n", date_cmd);
if (EXIT_SUCCESS != execlp(date_cmd, date_cmd, "-d", argv[curr_opt], "+%s",(char *) NULL))
{
perror("faketime: Running (g)date failed");
perror("Running (g)date failed");
exit(EXIT_FAILURE);
}
}
@@ -235,8 +199,6 @@ int main (int argc, char **argv)
/* simply pass format string along */
setenv("FAKETIME", argv[curr_opt], true);
}
if (fake_pid)
setenv("FAKETIME_FAKEPID", pid_val, true);
int keepalive_fds[2];
(void) (pipe(keepalive_fds) + 1);
@@ -262,7 +224,7 @@ int main (int argc, char **argv)
if (SEM_FAILED == (sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IWUSR|S_IRUSR, 1)))
{
perror("faketime: sem_open");
perror("sem_open");
fprintf(stderr, "The faketime wrapper only works on platforms that support the sem_open()\nsystem call. However, you may LD_PRELOAD libfaketime without using this wrapper.\n");
exit(EXIT_FAILURE);
}
@@ -270,10 +232,10 @@ int main (int argc, char **argv)
/* create shm */
if (-1 == (shm_fd = shm_open(shm_name, O_CREAT|O_EXCL|O_RDWR, S_IWUSR|S_IRUSR)))
{
perror("faketime: shm_open");
perror("shm_open");
if (-1 == sem_unlink(argv[2]))
{
perror("faketime: sem_unlink");
perror("sem_unlink");
}
exit(EXIT_FAILURE);
}
@@ -281,7 +243,7 @@ int main (int argc, char **argv)
/* set shm size */
if (-1 == ftruncate(shm_fd, sizeof(uint64_t)))
{
perror("faketime: ftruncate");
perror("ftruncate");
cleanup_shobjs();
exit(EXIT_FAILURE);
}
@@ -290,14 +252,14 @@ int main (int argc, char **argv)
if (MAP_FAILED == (ft_shared = mmap(NULL, sizeof(struct ft_shared_s), PROT_READ|PROT_WRITE,
MAP_SHARED, shm_fd, 0)))
{
perror("faketime: mmap");
perror("mmap");
cleanup_shobjs();
exit(EXIT_FAILURE);
}
if (sem_wait(sem) == -1)
{
perror("faketime: sem_wait");
perror("sem_wait");
cleanup_shobjs();
exit(EXIT_FAILURE);
}
@@ -314,14 +276,14 @@ int main (int argc, char **argv)
if (-1 == munmap(ft_shared, (sizeof(struct ft_shared_s))))
{
perror("faketime: munmap");
perror("munmap");
cleanup_shobjs();
exit(EXIT_FAILURE);
}
if (sem_post(sem) == -1)
{
perror("faketime: semop");
perror("semop");
cleanup_shobjs();
exit(EXIT_FAILURE);
}
@@ -334,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");
@@ -357,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);
@@ -384,10 +348,9 @@ int main (int argc, char **argv)
if (0 == (child_pid = fork()))
{
close(keepalive_fds[0]); /* only parent needs to read this */
// fprintf(stderr, "faketime: Executing: %s\n", argv[curr_opt]);
if (EXIT_SUCCESS != execvp(argv[curr_opt], &argv[curr_opt]))
{
perror("faketime: Running specified command failed");
perror("Running specified command failed");
exit(EXIT_FAILURE);
}
}

View File

@@ -45,7 +45,7 @@ struct ft_shared_s
* When advancing time linearly with each time(), etc. call, the calls are
* counted here */
uint64_t ticks;
/* Index of timestamp to be loaded from file */
/* Index of timstamp to be loaded from file */
uint64_t file_idx;
/* System time Faketime started at */
struct system_time_s start_time;
@@ -58,43 +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>
/*
Variadic Argument Re-packing
* Fake sleep prototypes!
*/
struct pollfd;
Functions with variadic arguments typically have most arguments
passed on the stack, but it varies across ABIs.
C specifies that variadic arguments that are smaller than some
standard promotion size are promoted to "int or larger". If your
platform's ABI only promotes to "int" and not "long" (and "int" and
"long" differ on your platform), you should probably add
-Dvariadic_promotion_t=int to CFLAGS.
Note that some ABIs do not put all the variadic arguments on the
stack. For example, x86-64 puts float and double variadic
arguments into floating point registers, according to
https://www.uclibc.org/docs/psABI-x86_64.pdf
The only variadic function faketime cares about intercepting is
syscall. But we don't believe that any syscalls expect float or
double arguments, so we hope all the rest will be on the stack.
tests/variadic/ attempts to confirm this if you are compiling
with -DINTERCEPT_SYSCALL.
If libc were capable of exposing a variadic form of syscall, we
could depend on that and drop this approach, which would be
preferable: https://sourceware.org/bugzilla/show_bug.cgi?id=27508
*/
#ifndef variadic_promotion_t
#define variadic_promotion_t long
#endif
/*
The Linux kernel appears to have baked-in 6 as the maximum number
of arguments for a syscall beyond the syscall number itself.
*/
#ifndef syscall_max_args
#define syscall_max_args 6
#endif
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

File diff suppressed because it is too large Load Diff

View File

@@ -9,4 +9,4 @@
#define htole64(x) LE_64(x)
#define le64toh(x) LE_64(x)
#endif /* SUN_OS_ENDIAN_H */
#endif /* SUN_OS_ENDIAN_H */

View File

@@ -61,7 +61,7 @@
do \
{ \
int64_t tmp_time; \
tmp_time = (c) * (int64_t) ((int64_t) (tvp)->tv_sec * SEC_TO_##prefix##SEC + \
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) / \

View File

@@ -1,78 +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}
TEST_SNIPPETS = $(notdir $(basename $(wildcard snippets/*.c)))
EXPECTATIONS= $(notdir $(basename $(wildcard snippets/*.variable)))
ALL_TESTS = timetest test
ifneq ($(filter -DINTERCEPT_SYSCALL,${CFLAGS}),)
ALL_TESTS += confirm_variadic_promotion
endif
all: $(ALL_TESTS)
.c.o:
${CC} -c ${CFLAGS} $<
timetest: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
test: timetest functest
@echo
@./test.sh
# run functional tests
functest:
./testframe.sh functests
%_test: %_test.c
${CC} -o $@ ${CFLAGS} $<
randomtest: repeat_random
./randomtest.sh
# ensure our variadic argument unpacking/repacking works as expected
confirm_variadic_promotion: variadic_promotion
./variadic_promotion
variadic_promotion: variadic/main.o variadic/outer.o variadic/inner.o
${CC} -o $@ ${CFLAGS} $^
variadic/%.o: variadic/%.c
${CC} -c -o $@ ${CFLAGS} $<
# run snippet tests
snippets: test_variable_data test_library_constructors
## test snippet behavior across env var setting over time:
test_variable_data: test_variable_data.sh $(foreach f,${EXPECTATIONS},run_${f})
./test_variable_data.sh ${EXPECTATIONS}
run_%: _run_test.c snippets/%.c
sed s/SNIPPET_NAME/$*/g < _run_test.c | ${CC} -o $@ ${CFLAGS} -x c -
## test snippets in other library constructors:
test_library_constructors: $(foreach f,${TEST_SNIPPETS},test_lib_${f})
test_lib_%: test_constructors.sh use_lib_% lib%.so
./test_constructors.sh $*
lib%.so: _libtest.c snippets/%.c
sed s/SNIPPET_NAME/$*/g < _libtest.c | ${CC} -shared -o $@ -fpic ${CFLAGS} -x c -
use_lib_%: _use_lib_test.c snippets/%.c lib%.so
sed s/SNIPPET_NAME/$*/g < _use_lib_test.c | ${CC} -L. -o $@ ${CFLAGS} -x c - -l$*
## cleanup and metainformation
clean:
@rm -f ${OBJ} timetest getrandom_test syscall_test $(foreach f,${TEST_SNIPPETS},use_lib_${f} lib${f}.so run_${f}) variadic_promotion variadic/*.o
distclean: clean
@echo
.PHONY: all test clean distclean randomtest snippets test_variable_data test_library_constructors

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

View File

@@ -1,8 +0,0 @@
#include "snippets/include_headers.h"
#define where "libSNIPPET_NAME"
void SNIPPET_NAME_as_needed() {
printf(" called SNIPPET_NAME_as_needed() \n");
}
static __attribute__((constructor)) void init_SNIPPET_NAME() {
#include "snippets/SNIPPET_NAME.c"
}

View File

@@ -1,5 +0,0 @@
#include "snippets/include_headers.h"
#define where "run_SNIPPET_NAME"
int main() {
#include "snippets/SNIPPET_NAME.c"
}

View File

@@ -1,7 +0,0 @@
#include "snippets/include_headers.h"
extern void SNIPPET_NAME_as_needed();
#define where "use_lib_SNIPPET_NAME"
int main() {
SNIPPET_NAME_as_needed();
#include "snippets/SNIPPET_NAME.c"
}

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,8 +42,7 @@ sunos_fakecmd()
linuxlike_fakecmd()
{
typeset timestring="$1"; shift
FTPL="${FAKETIME_TESTLIB:-../src/libfaketime.so.1}"
typeset fakelib="$FTPL"
typeset fakelib="$LIBFAKETIME_LA"
export LD_PRELOAD=$fakelib
FAKETIME="$timestring" \
"$@"

View File

@@ -1,21 +0,0 @@
#!/bin/sh
FTPL="${FAKETIME_TESTLIB:-../src/libfaketime.so.1}"
set -e
error=0
repeat3x5="$(FAKERANDOM_SEED=0xDEADBEEFDEADBEEF LD_PRELOAD="$FTPL" ./repeat_random 3 5)"
repeat5x3="$(FAKERANDOM_SEED=0xDEADBEEFDEADBEEF LD_PRELOAD="$FTPL" ./repeat_random 5 3)"
if [ "$repeat3x5" != "$repeat5x3" ]; then
error=1
printf >&2 '5 calls of getrandom(3) got %s\n3 calls of getrandom(5) got %s\n' "$repeat3x5" "$repeat5x3"
fi
if [ 0 = $error ]; then
printf 'getrandom interception test successful.\n'
fi
exit $error

View File

@@ -1,40 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/random.h>
void usage(const char* name) {
fprintf(stderr,
"Usage: %s REPS SIZE\n\n"
"Gather and print REPS blocks of SIZE bytes from getrandom()\n",
name);
}
int main(int argc, const char **argv) {
int reps, size;
unsigned char *buf;
if (argc != 3) {
usage(argv[0]);
return 1;
}
reps = atoi(argv[1]);
size = atoi(argv[2]);
buf = malloc(size);
if (!buf) {
fprintf(stderr, "failure to allocate buffer of size %d\n", size);
return 1;
}
for (int i = 0; i < reps; i++) {
ssize_t resp = getrandom(buf, size, 0);
if (resp != size) {
fprintf(stderr, "tried to get %d bytes, got %zd\n", size, resp);
free(buf);
return 2;
}
for (int j = 0; j < size; j++) {
printf("%02x", buf[j]);
}
}
free(buf);
printf("\n");
return 0;
};

View File

@@ -1,72 +0,0 @@
Testing Interception with Snippets
==================================
Faketime intercepts some C library functions and system calls. We
want to make it easier to apply certain generic tests across many
different functions. We do that with snippets of C, which each can be
applied in multiple testing frameworks.
Most snippets are just a minimalist invocation of a single function or
syscall that is likely to be intercepted by libfaketime, though it's
possible to test more complex snippets too.
Including a New Snippet
-----------------------
To cover a new bit of intercepted functionality, supply a C snippet in
this directory named `FOO.c` (the name FOO should conform to C
function names -- letters, numbers, and underscores; if you're testing
interception of a single function, the simplest thing is to name
snippet file after the intercepted function name).
This file should contain a small bit of code that exercises the
functionality in question. It should be self-contained, and it should
produce some kind of description of what happened to stdout. The data
sent to stdout should include the const char* "where" value (which is
an indication of which test framework is using the snippet). Take a
look at getpid.c for a simple example.
If the snippet needs additional #include headers, please add them
in `include_headers.h`. These #includes will be used by every snippet,
so try to keep it minimal.
Snippet Testing Frameworks
--------------------------
We have the following frameworks that use the snippets:
### Variable Data
Most functionality intercepted by libfaketime will normally produce
variant output when invoked multiple times across the span of a few
seconds by different processes. But if `FAKETIME` (or an analogous
variable like `FAKERANDOM_SEED`) is set, the output data should remain
constant.
If this describes the functionality in a new snippet `FOO.c`, please
also drop a single-line file `FOO.variable` in this directory, where
the first word of the line is the variable that should hold the output
constant, and the rest of the line is the value of that variable.
See the `test_variable_data` target in `test/Makefile` for how this is
implemented.
### Library Constructors
Library constructor routines are run by ld.so before the main process
is launched. If the LD_PRELOADed libfaketime is masking a symbol from
libc, and another library has a constructor routine that invokes that
symbol, it might get called before libfaketime has had a chance to
initialize its followup pointers to the actual libc functionality.
This framework is applied automatically to all snippets.
See the `test_library_constructors` target in `test/Makefile` for how
this is implemented.
Adding a New Framework
----------------------
If you want to add a new framework that tests across all snippets,
implement it in a few lines of `test/Makefile` and document it in the
section above.

View File

@@ -1,8 +0,0 @@
struct timespec ts;
clockid_t ckid = CLOCK_REALTIME;
int ret = clock_gettime(ckid, &ts);
if (ret == 0) {
printf("[%s] clock_gettime(CLOCK_REALTIME[%d], &ts) -> {%lld, %ld}\n", where, ckid, (long long)ts.tv_sec, ts.tv_nsec);
} else {
printf("[%s] clock_gettime(CLOCK_REALTIME[%d], &ts) returned non-zero (%d), errno = %d (%s)\n", where, ckid, ret, errno, strerror(errno));
}

View File

@@ -1 +0,0 @@
FAKETIME 2020-02-02 02:02:02+00:00

View File

@@ -1,8 +0,0 @@
struct timespec *ts = malloc(sizeof(struct timespec));
clockid_t ckid = CLOCK_REALTIME;
int ret = clock_gettime(ckid, ts);
if (ret == 0) {
printf("[%s] clock_gettime_heap(CLOCK_REALTIME[%d], ts) -> {%lld, %ld}\n", where, ckid, (long long)ts->tv_sec, ts->tv_nsec);
} else {
printf("[%s] clock_gettime_heap(CLOCK_REALTIME[%d], ts) returned non-zero (%d), errno = %d (%s)\n", where, ckid, ret, errno, strerror(errno));
}

View File

@@ -1 +0,0 @@
FAKETIME 2020-02-02 02:02:02+00:00

View File

@@ -1,6 +0,0 @@
unsigned int targ;
if (getentropy(&targ, sizeof(targ)) == 0) {
printf("[%s] getentropy() yielded 0x%08x\n", where, targ);
} else {
printf("[%s] getentropy() failed with %d (%s)\n", where, errno, strerror(errno));
}

View File

@@ -1 +0,0 @@
FAKERANDOM_SEED 0x0123456789ABCDEF

View File

@@ -1,2 +0,0 @@
pid_t pid = getpid();
printf("[%s] getpid() yielded %d\n", where, pid);

View File

@@ -1 +0,0 @@
FAKETIME_FAKEPID 1

View File

@@ -1,7 +0,0 @@
unsigned int targ;
ssize_t ret = getrandom(&targ, sizeof(targ), 0);
if (ret == sizeof(targ)) {
printf("[%s] getrandom() yielded 0x%08x\n", where, targ);
} else {
printf("[%s] getrandom() failed with only %zd\n", where, ret);
}

View File

@@ -1 +0,0 @@
FAKERANDOM_SEED 0xDEADBEEFDEADBEEF

View File

@@ -1,9 +0,0 @@
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/random.h>
#include <sys/syscall.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>

View File

@@ -1,2 +0,0 @@
long uid = syscall(__NR_getuid);
printf("[%s] syscall(__NR_getuid) -> %ld\n", where, uid);

View File

@@ -1,8 +0,0 @@
struct timespec ts;
clockid_t ckid = CLOCK_REALTIME;
long ret = syscall(__NR_clock_gettime, ckid, &ts);
if (ret == 0)
printf("[%s] syscall(__NR_gettime, CLOCK_REALTIME[%d], &ts) -> {%lld, %ld}\n", where, ckid, (long long)ts.tv_sec, ts.tv_nsec);
else
printf("[%s] syscall(__NR_gettime, CLOCK_REALTIME[%d], &ts) returned non-zero (%ld)\n", where, ckid, ret);

View File

@@ -1 +0,0 @@
FAKETIME 2020-01-01 00:00:00

View File

@@ -1,8 +0,0 @@
struct timespec *ts = malloc(sizeof(struct timespec));
clockid_t ckid = CLOCK_REALTIME;
long ret = syscall(__NR_clock_gettime, ckid, ts);
if (ret == 0)
printf("[%s] syscall(__NR_gettime, CLOCK_REALTIME[%d], ts) -> {%lld, %ld}\n", where, ckid, (long long)ts->tv_sec, ts->tv_nsec);
else
printf("[%s] syscall(__NR_gettime, CLOCK_REALTIME[%d], ts) returned non-zero (%ld)\n", where, ckid, ret);

View File

@@ -1 +0,0 @@
FAKETIME 2020-02-02 02:02:02+00:00

View File

@@ -1,2 +0,0 @@
time_t t = time(NULL);
printf("[%s] time() yielded %zd\n", where, t);

View File

@@ -1 +0,0 @@
FAKETIME 2020-02-02 02:02:02+00:00

View File

@@ -1,16 +1,38 @@
#!/bin/sh
FTPL="${FAKETIME_TESTLIB:-../src/libfaketime.so.1}"
##################################################################
# 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=$FTPL ./timetest"
LD_PRELOAD="$FTPL" ./timetest
echo "\$ $(set_libfaketime) ./timetest"
set_libfaketime
./timetest
echo
else
echo "Running the test program with no faked time specified"
echo "\$ LD_PRELOAD=$FTPL ./timetest"
LD_PRELOAD="$FTPL" ./timetest
echo "\$ $(set_libfaketime) ./timetest"
set_libfaketime
./timetest
echo
fi
@@ -18,48 +40,62 @@ echo "==========================================================================
echo
echo "Running the test program with absolute date 2003-01-01 10:00:05 specified"
echo "\$ LD_PRELOAD=$FTPL FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
LD_PRELOAD="$FTPL" 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=$FTPL FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
LD_PRELOAD="$FTPL" 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=$FTPL FAKETIME=\"-10d\" ./timetest"
LD_PRELOAD="$FTPL" 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=$FTPL FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
LD_PRELOAD="$FTPL" 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=$FTPL FAKETIME=\"+10d x1\" ./timetest"
LD_PRELOAD="$FTPL" 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=$FTPL FAKETIME=\"-15d\" date"
LD_PRELOAD="$FTPL" 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

@@ -1,10 +0,0 @@
#!/bin/sh
FTPL="${FAKETIME_TESTLIB:-../src/libfaketime.so.1}"
function="$1"
printf 'Testing library init for %s (no LD_PRELOAD)\n' "$function"
LD_LIBRARY_PATH=. "./use_lib_$function"
printf 'Testing library init for %s (LD_PRELOAD)\n' "$function"
LD_LIBRARY_PATH=. LD_PRELOAD="$FTPL" "./use_lib_$function"

View File

@@ -1,54 +0,0 @@
#!/bin/bash
set -e
FTPL="${FAKETIME_TESTLIB:-../src/libfaketime.so.1}"
DELAY="${DELAY:-2}"
declare -A firstunset first second delayed delayedunset
err=0
for func in "$@"; do
if ! [ -x "./run_$func" ]; then
printf >&2 '%s does not exist, failing\n' "./run_$func"
exit 1
fi
read varname value < "snippets/$func.variable"
unset $varname
firstunset[$func]="$(env LD_PRELOAD="$FTPL" "./run_$func")"
first[$func]="$(env LD_PRELOAD="$FTPL" "$varname=$value" "./run_$func")"
second[$func]="$(env LD_PRELOAD="$FTPL" "$varname=$value" "./run_$func")"
if [ "${first[$func]}" != "${second[$func]}" ]; then
printf >&2 '[%s] Set %s="%s", but got two different outputs:\n - %s\n - %s\n' "$func" "$varname" "$value" "${first[$func]}" "${second[$func]}"
err=$(( $err + 1 ))
fi
if [ "${first[$func]}" == "${firstunset[$func]}" ]; then
printf >&2 '[%s] Same answer when %s="%s" and when unset:\n - set: %s\n - unset: %s\n' "$func" "$varname" "$value" "${first[$func]}" "${firstunset[$func]}"
err=$(( $err + 1 ))
fi
done
printf "Sleeping %d seconds..." "$DELAY"
sleep "$DELAY"
printf 'done\n'
for func in "$@"; do
read varname value < "snippets/$func.variable"
unset $varname
delayed[$func]="$(env LD_PRELOAD="$FTPL" "$varname=$value" "./run_$func")"
delayedunset[$func]="$(LD_PRELOAD="$FTPL" "./run_$func")"
if [ "${first[$func]}" != "${delayed[$func]}" ]; then
printf >&2 '[%s] Vary across delay of %d seconds (%s="%s"):\n - before: %s\n - after: %s\n' "$func" "$DELAY" "$varname" "$value" "${first[$func]}" "${delayed[$func]}"
err=$(( $err + 1 ))
fi
if [ "${firstunset[$func]}" == "${delayedunset[$func]}" ]; then
printf >&2 '[%s] Same answer when unset across delay of %d seconds:\n - before: %s\n - after: %s\n' "$func" "$DELAY" "${firstunset[$func]}" "${delayedunset[$func]}"
err=$(( $err + 1 ))
fi
done
if [ "$err" -gt 0 ]; then
printf >&2 'Got %d errors, failing\n' "$err"
exit 1
fi
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>
@@ -83,7 +84,6 @@ void* pthread_test(void* args)
if (rt != ETIMEDOUT)
{
printf("pthread_cond_timedwait failed\n");
pthread_mutex_unlock(&fakeMutex);
exit(EXIT_FAILURE);
}
pthread_mutex_unlock(&fakeMutex);
@@ -106,7 +106,6 @@ void* pthread_test(void* args)
if (rt != ETIMEDOUT)
{
printf("pthread_cond_timedwait failed\n");
pthread_mutex_unlock(&fakeMutex);
exit(EXIT_FAILURE);
}
pthread_mutex_unlock(&fakeMutex);
@@ -117,6 +116,7 @@ void* pthread_test(void* args)
}
#endif
#include "faketime_common.h"
int main (int argc, char **argv)
{
@@ -218,10 +218,7 @@ printf("%s", 0 == 1 ? argv[0] : "");
printf("time() : Current date and time: %s", ctime(&now));
printf("time(NULL) : Seconds since Epoch : %u\n", (unsigned int)time(NULL));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
ftime(&tb);
#pragma GCC diagnostic pop
printf("ftime() : Current date and time: %s", ctime(&tb.time));
printf("(Intentionally sleeping 2 seconds...)\n");
@@ -248,11 +245,7 @@ printf("%s", 0 == 1 ? argv[0] : "");
int timer_getoverrun_timerid1 = timer_getoverrun(timerid1);
if (timer_getoverrun_timerid1 != 3)
{
#ifdef __GNU__
printf("(Timer overruns are assumed to be fine on Hurd)\n");
#else
printf("timer_getoverrun(timerid1) FAILED, must be 3 but got: %d\n", timer_getoverrun_timerid1);
#endif
}
timer_gettime(timerid1, &its);

View File

@@ -1,46 +0,0 @@
#include <stdio.h>
#include <wchar.h>
#include <stdarg.h>
#include <stddef.h>
/* round 0: c, s, wc, i, wi */
long inner0(char *out, ...) {
char c = 0;
short s = 0;
wchar_t wc = 0;
int i = 0;
wint_t wi = 0;
va_list ap;
va_start(ap, out);
c = va_arg(ap, int);
s = va_arg(ap, int);
wc = va_arg(ap, typeof(wc));
i = va_arg(ap, typeof(i));
wi = va_arg(ap, typeof(wi));
va_end(ap);
int ret = sprintf(out, "c: 0x%x s: 0x%x wc: 0x%lx i: 0x%x wi: 0x%x\n", c, s, (long)wc, i, wi);
return ret;
}
/* round 1: l, ll, ptr, pd, sz */
long inner1(char *out, ...) {
long l = 0;
long long ll = 0;
void *ptr = NULL;
ptrdiff_t pd = 0;
size_t sz = 0;
va_list ap;
va_start(ap, out);
l = va_arg(ap, typeof(l));
ll = va_arg(ap, typeof(ll));
ptr = va_arg(ap, typeof(ptr));
pd = va_arg(ap, typeof(pd));
sz = va_arg(ap, typeof(sz));
va_end(ap);
int ret = sprintf(out, "l: 0x%lx ll: 0x%llx ptr: %p pd: 0x%tx sz: 0x%zx\n", l, ll, ptr, pd, sz);
return ret;
}

View File

@@ -1,70 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <wchar.h>
extern long outer(long num, char *out, ...);
extern long inner0(char *out, ...);
extern long inner1(char *out, ...);
#define bufsize 2048
static int compare_buffers(int round,
long ret_outer, long ret_inner,
const char* outer, const char* inner) {
int ret = 0;
if (ret_outer != ret_inner) {
printf("Round %d: return values differ (outer: %ld inner: %ld)\n", round, ret_outer, ret_inner);
ret++;
}
if (memcmp(outer, inner, bufsize)) {
printf("Round %d strings differ:\n - outer: %s\n - inner: %s\n", round, outer, inner);
ret++;
}
if (ret == 0)
printf("Round %d success: %s\n", round, outer);
return ret;
}
int main() {
/* sizes of intrinsic types as reported by echo | cpp -dM | grep
SIZEOF, pruned to avoid floating point types. Should work with
both clang and gcc, not sure about other C preprocessors.
Note that we set bits in every high octet and every low octet to
see that they end up in the right spot.
*/
char c = 0x03L;
short s = (0x04L << ((__SIZEOF_SHORT__ - 1) * 8)) + 0xff;
wchar_t wc = (0x05L << ((__SIZEOF_WCHAR_T__ - 1) * 8)) + 0xfe;
int i = (0x06L << ((__SIZEOF_INT__ - 1) * 8)) + 0xfd;
wint_t wi = (0x07L << ((__SIZEOF_WINT_T__ - 1) * 8)) + 0xfc;
long l = (0x08L << ((__SIZEOF_LONG__ - 1) * 8) ) + 0xfb;
long long ll = (0x09LL << ((__SIZEOF_LONG_LONG__ - 1) * 8)) + 0xfa;
void *ptr = (void*)((0x0aL << ((__SIZEOF_POINTER__ - 1) * 8)) + 0xf9);
ptrdiff_t pd = (0x0bL << ((__SIZEOF_PTRDIFF_T__ -1) * 8)) + 0xf9;
size_t sz = (0x0cL << ((__SIZEOF_SIZE_T__ - 1) * 8)) + 0xf8;
char *buf[2];
for (int j = 0; j < 2; j++)
buf[j] = malloc(bufsize);
int ret[2];
int errors = 0;
#define reset_buffers(n) for (int j = 0; j < 2; j++) memset(buf[j], n, bufsize)
#define check_buffers(n) errors += compare_buffers(n, ret[0], ret[1], buf[0], buf[1])
reset_buffers(0);
ret[0] = outer(0, buf[0], c, s, wc, i, wi);
ret[1] = inner0(buf[1], c, s, wc, i, wi);
check_buffers(0);
reset_buffers(1);
ret[0] = outer(1, buf[0], l, ll, ptr, pd, sz);
ret[1] = inner1(buf[1], l, ll, ptr, pd, sz);
check_buffers(1);
return (int)errors;
}

View File

@@ -1,21 +0,0 @@
#include <stdarg.h>
#include <time.h>
#include "../../src/faketime_common.h"
extern long inner0(char *out, ...);
extern long inner1(char *out, ...);
long outer(long num, char *out, ...) {
va_list ap;
va_start(ap, out);
variadic_promotion_t a[syscall_max_args];
for (int i = 0; i < syscall_max_args; i++)
a[i] = va_arg(ap, variadic_promotion_t);
va_end(ap);
if (num == 0)
return inner0(out, a[0], a[1], a[2], a[3], a[4], a[5]);
if (num == 1)
return inner1(out, a[0], a[1], a[2], a[3], a[4], a[5]);
else return -1;
}