]> arthur.barton.de Git - bup.git/commitdiff
Drop xstat floating point timestamp support -- use integer ns.
authorRob Browning <rlb@defaultvalue.org>
Sun, 27 Mar 2011 17:01:44 +0000 (12:01 -0500)
committerAvery Pennarun <apenwarr@gmail.com>
Sun, 8 May 2011 07:39:14 +0000 (03:39 -0400)
Drop conditional support for floating point timestamps (the xstat
os.stat() fallback).  Switch to integer nanosecond timestamps
everywhere except the metadata record encoding and _helpers.c.

The metadata encoding is still a timespec because separate s and ns
timespec vints compress much better, and timespecs are still returned
by _helpers because the conversion to integer nanoseconds is much more
convenient in Python.

Enforce timespec range expectations -- throw an exception if the
system returns a nanosecond value less than 0 or greater than
999999999.  Remove _have_ns_fs_timestamps.

Depend on bup_stat(), bup_stat(), and bup_lstat() unconditionally, and
change the timespec return conversion from "(ll)" to "(Ll)", i.e. long
long range for secs.

This commit may break the build on some platforms -- we'll have to add
suitable conditionals once we see what's needed.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
lib/bup/_helpers.c
lib/bup/t/txstat.py
lib/bup/xstat.py

index 54246436e847a889a5bab83e0b4cf6a7bfc8fcf6..5343b8d839aeb66ecb20b0bfd6197a462b986adb 100644 (file)
@@ -7,6 +7,8 @@
 #include <fcntl.h>
 #include <arpa/inet.h>
 #include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -14,8 +16,6 @@
 #ifdef linux
 #include <linux/fs.h>
 #include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
 #endif
 
 static int istty2 = 0;
@@ -761,9 +761,43 @@ static PyObject *bup_utimensat(PyObject *self, PyObject *args)
           || _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L */
 
 
-#ifdef linux /* and likely others */
+static PyObject *stat_struct_to_py(const struct stat *st)
+{
+    /* Enforce the current timespec nanosecond range expectations. */
+    if (st->st_atim.tv_nsec < 0 || st->st_atim.tv_nsec > 999999999)
+    {
+        PyErr_SetString(PyExc_ValueError, "invalid atime timespec nanoseconds");
+        return NULL;
+    }
+    if (st->st_mtim.tv_nsec < 0 || st->st_mtim.tv_nsec > 999999999)
+    {
+        PyErr_SetString(PyExc_ValueError, "invalid mtime timespec nanoseconds");
+        return NULL;
+    }
+    if (st->st_ctim.tv_nsec < 0 || st->st_ctim.tv_nsec > 999999999)
+    {
+        PyErr_SetString(PyExc_ValueError, "invalid ctime timespec nanoseconds");
+        return NULL;
+    }
+
+    return Py_BuildValue("kkkkkkkk(Ll)(Ll)(Ll)",
+                         (unsigned long) st->st_mode,
+                         (unsigned long) st->st_ino,
+                         (unsigned long) st->st_dev,
+                         (unsigned long) st->st_nlink,
+                         (unsigned long) st->st_uid,
+                         (unsigned long) st->st_gid,
+                         (unsigned long) st->st_rdev,
+                         (unsigned long) st->st_size,
+                         (long long) st->st_atime,
+                         (long) st->st_atim.tv_nsec,
+                         (long long) st->st_mtime,
+                         (long) st->st_mtim.tv_nsec,
+                         (long long) st->st_ctime,
+                         (long) st->st_ctim.tv_nsec);
+}
+
 
-#define HAVE_BUP_STAT 1
 static PyObject *bup_stat(PyObject *self, PyObject *args)
 {
     int rc;
@@ -776,29 +810,10 @@ static PyObject *bup_stat(PyObject *self, PyObject *args)
     rc = stat(filename, &st);
     if (rc != 0)
         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
+    return stat_struct_to_py(&st);
+}
+
 
-    return Py_BuildValue("kkkkkkkk"
-                         "(ll)"
-                         "(ll)"
-                         "(ll)",
-                         (unsigned long) st.st_mode,
-                         (unsigned long) st.st_ino,
-                         (unsigned long) st.st_dev,
-                         (unsigned long) st.st_nlink,
-                         (unsigned long) st.st_uid,
-                         (unsigned long) st.st_gid,
-                         (unsigned long) st.st_rdev,
-                         (unsigned long) st.st_size,
-                         (long) st.st_atime,
-                         (long) st.st_atim.tv_nsec,
-                         (long) st.st_mtime,
-                         (long) st.st_mtim.tv_nsec,
-                         (long) st.st_ctime,
-                         (long) st.st_ctim.tv_nsec);
-}
-
-
-#define HAVE_BUP_LSTAT 1
 static PyObject *bup_lstat(PyObject *self, PyObject *args)
 {
     int rc;
@@ -811,29 +826,10 @@ static PyObject *bup_lstat(PyObject *self, PyObject *args)
     rc = lstat(filename, &st);
     if (rc != 0)
         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
+    return stat_struct_to_py(&st);
+}
+
 
-    return Py_BuildValue("kkkkkkkk"
-                         "(ll)"
-                         "(ll)"
-                         "(ll)",
-                         (unsigned long) st.st_mode,
-                         (unsigned long) st.st_ino,
-                         (unsigned long) st.st_dev,
-                         (unsigned long) st.st_nlink,
-                         (unsigned long) st.st_uid,
-                         (unsigned long) st.st_gid,
-                         (unsigned long) st.st_rdev,
-                         (unsigned long) st.st_size,
-                         (long) st.st_atime,
-                         (long) st.st_atim.tv_nsec,
-                         (long) st.st_mtime,
-                         (long) st.st_mtim.tv_nsec,
-                         (long) st.st_ctime,
-                         (long) st.st_ctim.tv_nsec);
-}
-
-
-#define HAVE_BUP_FSTAT 1
 static PyObject *bup_fstat(PyObject *self, PyObject *args)
 {
     int rc, fd;
@@ -845,29 +841,9 @@ static PyObject *bup_fstat(PyObject *self, PyObject *args)
     rc = fstat(fd, &st);
     if (rc != 0)
         return PyErr_SetFromErrno(PyExc_OSError);
-
-    return Py_BuildValue("kkkkkkkk"
-                         "(ll)"
-                         "(ll)"
-                         "(ll)",
-                         (unsigned long) st.st_mode,
-                         (unsigned long) st.st_ino,
-                         (unsigned long) st.st_dev,
-                         (unsigned long) st.st_nlink,
-                         (unsigned long) st.st_uid,
-                         (unsigned long) st.st_gid,
-                         (unsigned long) st.st_rdev,
-                         (unsigned long) st.st_size,
-                         (long) st.st_atime,
-                         (long) st.st_atim.tv_nsec,
-                         (long) st.st_mtime,
-                         (long) st.st_mtim.tv_nsec,
-                         (long) st.st_ctime,
-                         (long) st.st_ctim.tv_nsec);
+    return stat_struct_to_py(&st);
 }
 
-#endif /* def linux */
-
 
 static PyMethodDef helper_methods[] = {
     { "selftest", selftest, METH_VARARGS,
@@ -908,18 +884,12 @@ static PyMethodDef helper_methods[] = {
     { "utimensat", bup_utimensat, METH_VARARGS,
       "Change file timestamps with nanosecond precision." },
 #endif
-#ifdef HAVE_BUP_STAT
     { "stat", bup_stat, METH_VARARGS,
       "Extended version of stat." },
-#endif
-#ifdef HAVE_BUP_LSTAT
     { "lstat", bup_lstat, METH_VARARGS,
       "Extended version of lstat." },
-#endif
-#ifdef HAVE_BUP_FSTAT
     { "fstat", bup_fstat, METH_VARARGS,
       "Extended version of fstat." },
-#endif
     { NULL, NULL, 0, NULL },  // sentinel
 };
 
@@ -934,11 +904,6 @@ PyMODINIT_FUNC init_helpers(void)
     PyModule_AddObject(m, "AT_FDCWD", Py_BuildValue("i", AT_FDCWD));
     PyModule_AddObject(m, "AT_SYMLINK_NOFOLLOW",
                        Py_BuildValue("i", AT_SYMLINK_NOFOLLOW));
-#endif
-#ifdef HAVE_BUP_STAT
-    PyModule_AddIntConstant(m, "_have_ns_fs_timestamps", 1);
-#else
-    PyModule_AddIntConstant(m, "_have_ns_fs_timestamps", 0);
 #endif
     e = getenv("BUP_FORCE_TTY");
     istty2 = isatty(2) || (atoi(e ? e : "0") & 2);
index a56ac05b07936e1d5f74699dca1c0cd72ec5c92c..a43da6683c58432bc39ddcc6f91bb83ceb578bfc 100644 (file)
@@ -3,7 +3,8 @@ from wvtest import *
 import bup._helpers as _helpers
 from bup.xstat import FSTime
 
-def _test_fstime():
+@wvtest
+def test_fstime():
     def approx_eq(x, y):
         return math.fabs(x - y) < 1 / 10e8
     def ts_eq_ish(x, y):
@@ -43,14 +44,3 @@ def _test_fstime():
     WVPASS(s_ns_eq_ish(from_secs(-0.5), 0, - 10**9 / 2))
     WVPASS(s_ns_eq_ish(from_secs(-1.5), -1, - 10**9 / 2))
     WVPASS(s_ns_eq_ish(from_secs(-1 / 10e8), 0, -1))
-
-@wvtest
-def test_fstime():
-    _test_fstime();
-    if _helpers._have_ns_fs_timestamps: # Test native python timestamp rep too.
-        orig = _helpers._have_ns_fs_timestamps
-        try:
-            _helpers._have_ns_fs_timestamps = None
-            _test_fstime();
-        finally:
-            _helpers._have_ns_fs_timestamps = orig
index abc93fe3756cc7959692e4cbe0b78a69da0a9783..e3044bebfd505a9a9573dc73f9e454253e9802fa 100644 (file)
@@ -51,15 +51,6 @@ class FSTime:
         abs_val = -self._value
         return (- (abs_val / 10**9), - (abs_val % 10**9))
 
-    if _helpers._have_ns_fs_timestamps: # Use integer nanoseconds.
-        @staticmethod
-        def from_stat_time(stat_time):
-            return FSTime.from_timespec(stat_time)
-    else: # Use python default floating-point seconds.
-        @staticmethod
-        def from_stat_time(stat_time):
-            return FSTime.from_secs(stat_time)
-
 
 if _have_utimensat:
     def lutime(path, times):
@@ -85,58 +76,30 @@ class stat_result:
     @staticmethod
     def from_stat_rep(st):
         result = stat_result()
-        if _helpers._have_ns_fs_timestamps:
-            (result.st_mode,
-             result.st_ino,
-             result.st_dev,
-             result.st_nlink,
-             result.st_uid,
-             result.st_gid,
-             result.st_rdev,
-             result.st_size,
-             atime,
-             mtime,
-             ctime) = st
-        else:
-            result.st_mode = st.st_mode
-            result.st_ino = st.st_ino
-            result.st_dev = st.st_dev
-            result.st_nlink = st.st_nlink
-            result.st_uid = st.st_uid
-            result.st_gid = st.st_gid
-            result.st_rdev = st.st_rdev
-            result.st_size = st.st_size
-            atime = st.st_atime
-            mtime = st.st_mtime
-            ctime = st.st_ctime
-        result.st_atime = FSTime.from_stat_time(atime)
-        result.st_mtime = FSTime.from_stat_time(mtime)
-        result.st_ctime = FSTime.from_stat_time(ctime)
+        (result.st_mode,
+         result.st_ino,
+         result.st_dev,
+         result.st_nlink,
+         result.st_uid,
+         result.st_gid,
+         result.st_rdev,
+         result.st_size,
+         result.st_atime,
+         result.st_mtime,
+         result.st_ctime) = st
+        result.st_atime = FSTime.from_timespec(result.st_atime)
+        result.st_mtime = FSTime.from_timespec(result.st_mtime)
+        result.st_ctime = FSTime.from_timespec(result.st_ctime)
         return result
 
 
-try:
-    _stat = _helpers.stat
-except AttributeError, e:
-    _stat = os.stat
-
 def stat(path):
-    return stat_result.from_stat_rep(_stat(path))
-
+    return stat_result.from_stat_rep(_helpers.stat(path))
 
-try:
-    _fstat = _helpers.fstat
-except AttributeError, e:
-    _fstat = os.fstat
 
 def fstat(path):
-    return stat_result.from_stat_rep(_fstat(path))
-
+    return stat_result.from_stat_rep(_helpers.fstat(path))
 
-try:
-    _lstat = _helpers.lstat
-except AttributeError, e:
-    _lstat = os.lstat
 
 def lstat(path):
-    return stat_result.from_stat_rep(_lstat(path))
+    return stat_result.from_stat_rep(_helpers.lstat(path))