Skip to content

Commit

Permalink
Merge pull request #62 from delroth/ranlib-utime
Browse files Browse the repository at this point in the history
ranlib: attempt to use utimens variants when available
  • Loading branch information
tpoechtrager committed Dec 13, 2018
2 parents 0761902 + 17c2bf9 commit 1e3f614
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 18 deletions.
66 changes: 62 additions & 4 deletions cctools/configure
Expand Up @@ -17044,18 +17044,76 @@ fi



for ac_func in strmode
for ac_func in strmode, utimensat
do :
ac_fn_c_check_func "$LINENO" "strmode" "ac_cv_func_strmode"
if test "x$ac_cv_func_strmode" = xyes; then :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRMODE 1
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done


### Check how to access struct stat's tv_nsec field.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for st_mtimespec.tv_nsec in struct stat" >&5
$as_echo_n "checking for st_mtimespec.tv_nsec in struct stat... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
int
main ()
{

struct stat st;
st.st_mtimespec.tv_nsec = 0;

;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

$as_echo "#define HAVE_STAT_ST_MTIMESPEC 1" >>confdefs.h

{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for st_mtim.tv_nsec in struct stat" >&5
$as_echo_n "checking for st_mtim.tv_nsec in struct stat... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
int
main ()
{

struct stat st;
st.st_mtim.tv_nsec = 0;

;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

$as_echo "#define HAVE_STAT_ST_MTIM 1" >>confdefs.h

{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

### Check for __cxa_demangle in various C++ ABI libs ###

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __cxa_demangle in -lc++abi" >&5
Expand Down
27 changes: 26 additions & 1 deletion cctools/configure.ac
Expand Up @@ -268,7 +268,32 @@ AC_CHECK_LIB([uuid],[uuid_generate_random],[
AC_CHECK_HEADERS([uuid/uuid.h], [UUID_LIB=-luuid])], [])
AC_SUBST(UUID_LIB)

AC_CHECK_FUNCS([strmode])
AC_CHECK_FUNCS([strmode, utimensat])

### Check how to access struct stat's tv_nsec field.
AC_MSG_CHECKING(for st_mtimespec.tv_nsec in struct stat)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <sys/stat.h>]],
[[
struct stat st;
st.st_mtimespec.tv_nsec = 0;
]])],
[AC_DEFINE(HAVE_STAT_ST_MTIMESPEC, 1, [struct stat has st_mtimespec.tv_nsec])
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])

AC_MSG_CHECKING(for st_mtim.tv_nsec in struct stat)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <sys/stat.h>]],
[[
struct stat st;
st.st_mtim.tv_nsec = 0;
]])],
[AC_DEFINE(HAVE_STAT_ST_MTIM, 1, [struct stat has st_mtim.tv_nsec])
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])

### Check for __cxa_demangle in various C++ ABI libs ###

Expand Down
64 changes: 51 additions & 13 deletions cctools/misc/libtool.c
Expand Up @@ -59,9 +59,47 @@
#include <servers/bootstrap.h>
#endif

/* cctools-port */
/* cctools-port start */
int asprintf(char **strp, const char *fmt, ...);

/*
* utimens utility to set file times with sub-second resolution when available.
* This is done by using utimensat if available at compile time.
*
* macOS is special cased: utimensat is only visible at compile time when
* building for macOS >= 10.13, but with proper runtime checks we can make
* builds targeted at older versions also work with sub-second resolution when
* available. This is especially important because APFS introduces sub-second
* timestamp resolution.
*/
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
#pragma weak utimensat
#endif

static int utimens(const char *path, const struct timespec times[2])
{
#ifdef HAVE_UTIMENSAT
#ifdef __APPLE__
if (utimensat != NULL)
#endif
return utimensat(AT_FDCWD, path, times, 0);
#endif

/* Fall back to truncating the timestamp to 1s resolution. */
#ifndef __OPENSTEP__
struct utimbuf timep;
timep.actime = times[0].tv_sec;
timep.modtime = times[1].tv_sec;
return utime(path, &timep);
#else
time_t timep[2];
timep[0] = times[0].tv_sec;
timep[1] = times[1].tv_sec;
return utime(path, timep);
#endif
}
/* cctools-port end */

/*
* This is used internally to build the table of contents.
*/
Expand Down Expand Up @@ -2307,11 +2345,7 @@ struct ofile *ofile)
struct fat_arch *fat_arch;
struct fat_arch_64 *fat_arch64;
int fd;
#ifndef __OPENSTEP__
struct utimbuf timep;
#else
time_t timep[2];
#endif
struct timespec times[2];
struct stat stat_buf;
struct ar_hdr toc_ar_hdr;
enum bool some_tocs, same_toc, different_offsets;
Expand Down Expand Up @@ -2881,15 +2915,19 @@ struct ofile *ofile)
* Now set the modtime of the created library back to it's stat time
* when we first closed it.
*/
#ifndef __OPENSTEP__
timep.actime = stat_buf.st_mtime;
timep.modtime = stat_buf.st_mtime;
if(utime(output, &timep) == -1)
#ifdef HAVE_STAT_ST_MTIMESPEC
times[0] = stat_buf.st_mtimespec;
times[1] = stat_buf.st_mtimespec;
#elif HAVE_STAT_ST_MTIM
times[0] = stat_buf.st_mtim;
times[1] = stat_buf.st_mtim;
#else
timep[0] = stat_buf.st_mtime;
timep[1] = stat_buf.st_mtime;
if(utime(output, timep) == -1)
times[0].tv_sec = stat_buf.st_mtime;
times[0].tv_nsec = 0;
times[1].tv_sec = stat_buf.st_mtime;
times[0].tv_nsec = 0;
#endif
if(utimens(output, times) == -1)
{
system_fatal("can't set the modifiy times in output file: %s",
output);
Expand Down

0 comments on commit 1e3f614

Please sign in to comment.