From ae876c28baa5159ec9db259204cc3ffa23b2e25c Mon Sep 17 00:00:00 2001 From: Rob Browning Date: Mon, 23 Nov 2020 18:21:00 -0600 Subject: [PATCH] Depend on python 3 for utime when using 3 Since python 3.3+ now claims to implement what we need (follow symlinks, ns resolution), rely on it for utime when possible in preference to our own C code in _helpers. This should fix new failures on macos due to changes to the availability of utimensat, etc. Signed-off-by: Rob Browning Tested-by: Rob Browning --- config/configure | 27 +++++++++++++++++++-------- lib/bup/_helpers.c | 15 +++++++++++++++ lib/bup/xstat.py | 13 +++++++++++-- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/config/configure b/config/configure index afdfa38..407bd4b 100755 --- a/config/configure +++ b/config/configure @@ -78,8 +78,16 @@ if test -z "$bup_python"; then AC_FAIL "ERROR: unable to find python" else AC_SUB bup_python "$bup_python" - AC_SUB bup_python_majver \ - "$("$bup_python" -c 'import sys; print(sys.version_info[0])')" + bup_python_majver=$("$bup_python" -c 'import sys; print(sys.version_info[0])') + bup_python_minver=$("$bup_python" -c 'import sys; print(sys.version_info[1])') + AC_SUB bup_python_majver "$bup_python_majver" +fi + +# May not be correct yet, i.e. actual requirement may be higher. +if test "$bup_python_majver" -gt 2 -a "$bup_python_minver" -lt 3; then + # utime follow_symlinks >= 3.3 + bup_version_str=$("$bup_python" --version 2>&1) + AC_FAIL "ERROR: found $bup_version_str (must be >= 3.3 if >= 3)" fi bup_git="$(bup_find_prog git '')" @@ -101,13 +109,16 @@ AC_CHECK_HEADERS sys/mman.h AC_CHECK_HEADERS linux/fs.h AC_CHECK_HEADERS sys/ioctl.h -# On GNU/kFreeBSD utimensat is defined in GNU libc, but won't work. -if [ -z "$OS_GNU_KFREEBSD" ]; then - AC_CHECK_FUNCS utimensat +if test "$bup_python_majver" -gt 2; then + AC_DEFINE BUP_USE_PYTHON_UTIME 1 +else # Python 2 + # On GNU/kFreeBSD utimensat is defined in GNU libc, but won't work. + if [ -z "$OS_GNU_KFREEBSD" ]; then + AC_CHECK_FUNCS utimensat + fi + AC_CHECK_FUNCS utimes + AC_CHECK_FUNCS lutimes fi -AC_CHECK_FUNCS utimes -AC_CHECK_FUNCS lutimes - builtin_mul_overflow_code=" #include diff --git a/lib/bup/_helpers.c b/lib/bup/_helpers.c index 5f07d44..2790b07 100644 --- a/lib/bup/_helpers.c +++ b/lib/bup/_helpers.c @@ -70,6 +70,7 @@ #define BUP_HAVE_FILE_ATTRS 1 #endif +#ifndef BUP_USE_PYTHON_UTIME // just for Python 2 now /* * Check for incomplete UTIMENSAT support (NetBSD 6), and if so, * pretend we don't have it. @@ -77,6 +78,7 @@ #if !defined(AT_FDCWD) || !defined(AT_SYMLINK_NOFOLLOW) #undef HAVE_UTIMENSAT #endif +#endif // defined BUP_USE_PYTHON_UTIME #ifndef FS_NOCOW_FL // Of course, this assumes it's a bitfield value. @@ -1406,6 +1408,7 @@ static PyObject *bup_set_linux_file_attr(PyObject *self, PyObject *args) #endif /* def BUP_HAVE_FILE_ATTRS */ +#ifndef BUP_USE_PYTHON_UTIME // just for Python 2 now #ifndef HAVE_UTIMENSAT #ifndef HAVE_UTIMES #error "cannot find utimensat or utimes()" @@ -1414,6 +1417,7 @@ static PyObject *bup_set_linux_file_attr(PyObject *self, PyObject *args) #error "cannot find utimensat or lutimes()" #endif #endif +#endif // defined BUP_USE_PYTHON_UTIME #define ASSIGN_PYLONG_TO_INTEGRAL(dest, pylong, overflow) \ ({ \ @@ -1450,6 +1454,7 @@ static PyObject *bup_set_linux_file_attr(PyObject *self, PyObject *args) }) +#ifndef BUP_USE_PYTHON_UTIME // just for Python 2 now #ifdef HAVE_UTIMENSAT static PyObject *bup_utimensat(PyObject *self, PyObject *args) @@ -1567,6 +1572,8 @@ static PyObject *bup_lutimes(PyObject *self, PyObject *args) } #endif /* def HAVE_LUTIMES */ +#endif // defined BUP_USE_PYTHON_UTIME + #ifdef HAVE_STAT_ST_ATIM # define BUP_STAT_ATIME_NS(st) (st)->st_atim.tv_nsec @@ -2276,6 +2283,8 @@ static PyMethodDef helper_methods[] = { { "set_linux_file_attr", bup_set_linux_file_attr, METH_VARARGS, "Set the Linux attributes for the given file." }, #endif + +#ifndef BUP_USE_PYTHON_UTIME // just for Python 2 now #ifdef HAVE_UTIMENSAT { "bup_utimensat", bup_utimensat, METH_VARARGS, "Change path timestamps with nanosecond precision (POSIX)." }, @@ -2289,6 +2298,8 @@ static PyMethodDef helper_methods[] = { "Change path timestamps with microsecond precision;" " don't follow symlinks." }, #endif +#endif // defined BUP_USE_PYTHON_UTIME + { "stat", bup_stat, METH_VARARGS, "Extended version of stat." }, { "lstat", bup_lstat, METH_VARARGS, @@ -2420,6 +2431,8 @@ static int setup_module(PyObject *m) PyObject_SetAttrString(m, "UINT_MAX", value); Py_DECREF(value); } + +#ifndef BUP_USE_PYTHON_UTIME // just for Python 2 now #ifdef HAVE_UTIMENSAT { PyObject *value; @@ -2434,6 +2447,8 @@ static int setup_module(PyObject *m) Py_DECREF(value); } #endif +#endif // defined BUP_USE_PYTHON_UTIME + #ifdef BUP_HAVE_MINCORE_INCORE { PyObject *value; diff --git a/lib/bup/xstat.py b/lib/bup/xstat.py index 461c932..b334ffd 100644 --- a/lib/bup/xstat.py +++ b/lib/bup/xstat.py @@ -20,6 +20,9 @@ try: except AttributeError as e: _bup_lutimes = False +assert sys.version_info[0] < 3 \ + or not (_bup_utimensat or _bup_utimes or _bup_lutimes) + def timespec_to_nsecs(ts): ts_s, ts_ns = ts @@ -58,8 +61,14 @@ def fstime_to_sec_bytes(fstime): else: return b'%d.%09d' % (s, ns) - -if _bup_utimensat: +if sys.version_info[0] > 2: + def utime(path, times): + """Times must be provided as (atime_ns, mtime_ns).""" + os.utime(path, ns=times) + def lutime(path, times): + """Times must be provided as (atime_ns, mtime_ns).""" + os.utime(path, ns=times, follow_symlinks=False) +elif _bup_utimensat: def utime(path, times): """Times must be provided as (atime_ns, mtime_ns).""" atime = nsecs_to_timespec(times[0]) -- 2.39.2