Browse Source

Add support for dynamically loading utimensat

This allows adding utimensat support in binaries for systems like
FreeBSD that only recently got it without dropping support for older
versions.
pull/44/merge
Daniel Scharrer 11 years ago
parent
commit
f79a3c622b
  1. 25
      CMakeLists.txt
  2. 1
      README.md
  3. 4
      src/configure.hpp.in
  4. 40
      src/util/time.cpp

25
CMakeLists.txt

@ -12,6 +12,7 @@ option(DEBUG_EXTRA "Expensive debug options" OFF)
option(SET_WARNING_FLAGS "Adjust compiler warning flags" ON)
option(SET_OPTIMIZATION_FLAGS "Adjust compiler optimization flags" ON)
option(USE_CXX11 "Try to use C++11 if available" ON)
option(USE_DYNAMIC_UTIMENSAT "Dynamically load utimensat if not available at compile time" OFF)
if(NOT DEFINED DEBUG AND CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DEBUG 1)
endif()
@ -210,11 +211,25 @@ if(NOT WIN32)
check_symbol_exists(ioctl "sys/ioctl.h" INNOEXTRACT_HAVE_IOCTL)
check_symbol_exists(timegm "time.h" INNOEXTRACT_HAVE_TIMEGM)
check_symbol_exists(gmtime_r "time.h" INNOEXTRACT_HAVE_GMTIME_R)
check_symbol_exists(utimensat "sys/stat.h" INNOEXTRACT_HAVE_UTIMENSAT)
check_symbol_exists(AT_FDCWD "fcntl.h" INNOEXTRACT_HAVE_AT_FDCWD)
if(INNOEXTRACT_HAVE_AT_FDCWD)
check_symbol_exists(utimensat "sys/stat.h" INNOEXTRACT_HAVE_UTIMENSAT)
endif()
if(INNOEXTRACT_HAVE_UTIMENSAT AND INNOEXTRACT_HAVE_AT_FDCWD)
set(INNOEXTRACT_HAVE_UTIMENSAT_d 1)
else()
if(USE_DYNAMIC_UTIMENSAT AND INNOEXTRACT_HAVE_AT_FDCWD)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
check_symbol_exists(dlsym "dlfcn.h" INNOEXTRACT_HAVE_DLSYM)
check_symbol_exists(RTLD_DEFAULT "dlfcn.h" INNOEXTRACT_HAVE_RTLD_DEFAULT)
unset(CMAKE_REQUIRED_LIBRARIES)
if(INNOEXTRACT_HAVE_DLSYM AND INNOEXTRACT_HAVE_RTLD_DEFAULT)
set(INNOEXTRACT_HAVE_DYNAMIC_UTIMENSAT 1)
if(CMAKE_DL_LIBS)
list(APPEND LIBRARIES ${CMAKE_DL_LIBS})
endif()
endif()
endif()
check_symbol_exists(utimes "sys/time.h" INNOEXTRACT_HAVE_UTIMES)
endif()
@ -407,11 +422,15 @@ print_configuration("LZMA decompression" FIRST
INNOEXTRACT_HAVE_LZMA "enabled"
1 "disabled"
)
if(INNOEXTRACT_HAVE_DYNAMIC_UTIMENSAT)
set(time_prefix "nanoseconds if supported, ")
set(time_suffix " otherwise")
endif()
print_configuration("File time precision" FIRST
INNOEXTRACT_HAVE_UTIMENSAT_d "nanoseconds"
WIN32 "100-nanoseconds"
INNOEXTRACT_HAVE_UTIMES "microseconds"
1 "seconds"
INNOEXTRACT_HAVE_UTIMES "${time_prefix}microseconds${time_suffix}"
1 "${time_prefix}seconds${time_suffix}"
)
print_configuration("Charset conversion"
INNOEXTRACT_HAVE_ICONV "iconv"

1
README.md

@ -51,6 +51,7 @@ Build options:
| `SET_WARNING_FLAGS` | `ON` | Adjust compiler warning flags. This should not affect the produced binaries but is useful to catch potential problems.
| `SET_OPTIMIZATION_FLAGS` | `ON` | Adjust compiler optimization flags. For non-debug builds the only thing this does is instruct the linker to only link against libraries that are actually needed.
| `USE_CXX11` | `ON` | Try to compile in C++11 mode if available.
| `USE_DYNAMIC_UTIMENSAT` | `OFF` | Dynamically load utimensat(2) if not available at compile time
| `USE_STATIC_LIBS` | `OFF`^3 | Turns on static linking for all libraries, including `-static-libgcc` and `-static-libstdc++`. You can also use the individual options below:
| `LZMA_USE_STATIC_LIBS` | `OFF`^4 | Statically link `liblzma`.
| `Boost_USE_STATIC_LIBS` | `OFF`^4 | Statically link Boost. See also `FindBoost.cmake`

4
src/configure.hpp.in

@ -12,9 +12,13 @@
// File functions
#cmakedefine01 INNOEXTRACT_HAVE_UTIMENSAT
#cmakedefine01 INNOEXTRACT_HAVE_DYNAMIC_UTIMENSAT
#cmakedefine01 INNOEXTRACT_HAVE_AT_FDCWD
#cmakedefine01 INNOEXTRACT_HAVE_UTIMES
// Shared functions
#cmakedefine01 INNOEXTRACT_HAVE_DLSYM
// Endianness
#cmakedefine01 INNOEXTRACT_HAVE_BUILTIN_BSWAP16
#cmakedefine01 INNOEXTRACT_HAVE_BUILTIN_BSWAP32

40
src/util/time.cpp

@ -32,9 +32,16 @@
#include <windows.h>
#endif
#if INNOEXTRACT_HAVE_DLSYM
#include <dlfcn.h>
#endif
#if INNOEXTRACT_HAVE_AT_FDCWD
#include <fcntl.h>
#endif
#if INNOEXTRACT_HAVE_UTIMENSAT && INNOEXTRACT_HAVE_AT_FDCWD
#include <sys/stat.h>
#include <fcntl.h>
#elif !defined(_WIN32) && INNOEXTRACT_HAVE_UTIMES
#include <sys/time.h>
#elif !defined(_WIN32)
@ -246,18 +253,37 @@ static HANDLE open_file(LPCWSTR name) {
#endif
#if INNOEXTRACT_HAVE_DYNAMIC_UTIMENSAT
extern "C" typedef int (*utimensat_proc)
(int fd, const char *path, const struct timespec times[2], int flag);
#endif
bool set_file_time(const boost::filesystem::path & path, time t, boost::uint32_t nsec) {
#if INNOEXTRACT_HAVE_UTIMENSAT && INNOEXTRACT_HAVE_AT_FDCWD
#if (INNOEXTRACT_HAVE_DYNAMIC_UTIMENSAT || INNOEXTRACT_HAVE_UTIMENSAT) \
&& INNOEXTRACT_HAVE_AT_FDCWD
// nanosecond precision, for Linux and POSIX.1-2008+ systems
struct timespec times[2];
times[0].tv_sec = to_time_t<time_t>(t, path.string().c_str());
times[0].tv_nsec = boost::int32_t(nsec);
times[1] = times[0];
struct timespec timens[2];
timens[0].tv_sec = to_time_t<time_t>(t, path.string().c_str());
timens[0].tv_nsec = boost::int32_t(nsec);
timens[1] = timens[0];
#endif
#if INNOEXTRACT_HAVE_DYNAMIC_UTIMENSAT && INNOEXTRACT_HAVE_AT_FDCWD
static utimensat_proc utimensat_func = (utimensat_proc)dlsym(RTLD_DEFAULT, "utimensat");
if(utimensat_func) {
return (utimensat_func(AT_FDCWD, path.string().c_str(), timens, 0) == 0);
}
#endif
#if INNOEXTRACT_HAVE_UTIMENSAT && INNOEXTRACT_HAVE_AT_FDCWD
return (utimensat(AT_FDCWD, path.string().c_str(), times, 0) == 0);
return (utimensat(AT_FDCWD, path.string().c_str(), timens, 0) == 0);
#elif defined(_WIN32)

Loading…
Cancel
Save