mirror of
https://github.com/wolfcw/libfaketime.git
synced 2026-06-11 21:03:21 +03:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57de5bbe83 | ||
|
|
c2b5b71777 | ||
|
|
6c0947c86e | ||
|
|
b36ad2342c | ||
|
|
d40d0ebaa7 | ||
|
|
081845440b | ||
|
|
30207e8fdf | ||
|
|
d2f0daf092 | ||
|
|
c5b5d0b56e | ||
|
|
f8a0ad2496 | ||
|
|
0e3269efdc | ||
|
|
04e78e67bf | ||
|
|
0e798503a4 | ||
|
|
a7f7a54e1d | ||
|
|
8075c2e250 | ||
|
|
a12ca58dfa | ||
|
|
b4dea2ef9b | ||
|
|
796b30bebf | ||
|
|
70d26ec15c | ||
|
|
052239d828 | ||
|
|
fe8c0acee6 | ||
|
|
c44a332e0e | ||
|
|
a54f204209 | ||
|
|
195888434a | ||
|
|
f7de52c07b | ||
|
|
0efe7b3e3e | ||
|
|
b542e14959 | ||
|
|
78385ba8b7 | ||
|
|
b3dcef470e | ||
|
|
90f11685b5 | ||
|
|
d7ef17a0de | ||
|
|
3123ad7fe2 | ||
|
|
af2d2e5111 | ||
|
|
11fbc2ada1 | ||
|
|
f92d919fb0 | ||
|
|
22f8c3dd36 | ||
|
|
a0fe6b56b0 | ||
|
|
fdc3c81ae0 | ||
|
|
10b9818c2c | ||
|
|
826f8b7792 | ||
|
|
5d1e6325f2 | ||
|
|
8ed946cb63 | ||
|
|
108370f850 | ||
|
|
3de0d02353 | ||
|
|
150a6cb3b2 | ||
|
|
39a85e380c | ||
|
|
825043515f | ||
|
|
335617c4c7 | ||
|
|
96668a9c6d | ||
|
|
24fd806e6b | ||
|
|
39c6872f6d |
23
.github/workflows/make-test.yml
vendored
Normal file
23
.github/workflows/make-test.yml
vendored
Normal 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
21
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
11
ChangeLog
Normal file
11
ChangeLog
Normal 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
|
||||
35
Makefile
35
Makefile
@@ -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
4
Makefile.am
Normal 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
17
NEWS
@@ -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
44
README
@@ -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
|
||||
----------------------------------------
|
||||
|
||||
|
||||
13
README.OSX
13
README.OSX
@@ -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
63
README.packagers
Normal 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
270
ar-lib
Executable 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
46
build.sh
Normal 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
62
configure.ac
Normal 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
|
||||
14
man/Makefile
14
man/Makefile
@@ -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
|
||||
@@ -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
18
man/Makefile.am
Normal 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
|
||||
@@ -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
39
src/Makefile.am
Normal 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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(×[0], &user_offset2, &tn[0]);
|
||||
timersub(×[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, ¤t_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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
29
test/Makefile.am
Normal 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
7
test/functests.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
[ "${srcdir}" ] || srcdir=.
|
||||
|
||||
# run functional tests
|
||||
# cd "${srcdir}/"
|
||||
${srcdir}/testframe.sh ${srcdir}/functests
|
||||
@@ -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" \
|
||||
"$@"
|
||||
|
||||
72
test/test.sh
72
test/test.sh
@@ -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 "============================================================================="
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user