]> arthur.barton.de Git - bup.git/commitdiff
Don't require non-negative timespec ns; fix stat timestamp conversions.
authorRob Browning <rlb@defaultvalue.org>
Thu, 19 Dec 2013 04:16:44 +0000 (22:16 -0600)
committerRob Browning <rlb@defaultvalue.org>
Sat, 28 Dec 2013 21:22:50 +0000 (15:22 -0600)
Previously we required that the system timespec tv_nsec values be
non-negative -- stop that.  POSIX doesn't specify, and there's no real
need for us to care, since all significant timestamp manipulations are
now handled as integer nanosecond values, not (sec, ns) pairs.

Change stat_struct_to_py() (used by bup_stat()/bup_lstat()) to use
INTEGER_TO_PY() to convert the timestamp st_atime/st_mtime/st_ctime
values so that we don't have to care about the sign/size of the
underlying type (which should be time_t).

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

index 673ae8ae4ff7dbb6bde11c937e06cc5227dabfe5..65160bf85aefe04a2e1f485007613eb72f49af48 100644 (file)
@@ -948,48 +948,6 @@ static PyObject *bup_lutimes(PyObject *self, PyObject *args)
 #endif
 
 
-static void set_invalid_timespec_msg(const char *field,
-                                     const long long sec,
-                                     const long nsec,
-                                     const char *filename,
-                                     int fd)
-{
-    if (filename != NULL)
-        PyErr_Format(PyExc_ValueError,
-                     "invalid %s timespec (%lld %ld) for file \"%s\"",
-                     field, sec, nsec, filename);
-    else
-        PyErr_Format(PyExc_ValueError,
-                     "invalid %s timespec (%lld %ld) for file descriptor %d",
-                     field, sec, nsec, fd);
-}
-
-
-static int normalize_timespec_values(const char *name,
-                                     long long *sec,
-                                     long *nsec,
-                                     const char *filename,
-                                     int fd)
-{
-    if (*nsec < -999999999 || *nsec > 999999999)
-    {
-        set_invalid_timespec_msg(name, *sec, *nsec, filename, fd);
-        return 0;
-    }
-    if (*nsec < 0)
-    {
-        if (*sec == LONG_MIN)
-        {
-            set_invalid_timespec_msg(name, *sec, *nsec, filename, fd);
-            return 0;
-        }
-        *nsec += 1000000000;
-        *sec -= 1;
-    }
-    return 1;
-}
-
-
 #define INTEGER_TO_PY(x) \
     (((x) >= 0) ? PyLong_FromUnsignedLongLong(x) : PyLong_FromLongLong(x))
 
@@ -998,24 +956,11 @@ static PyObject *stat_struct_to_py(const struct stat *st,
                                    const char *filename,
                                    int fd)
 {
-    long long atime = st->st_atime;
-    long long mtime = st->st_mtime;
-    long long ctime = st->st_ctime;
-    long atime_ns = BUP_STAT_ATIME_NS(st);
-    long mtime_ns = BUP_STAT_MTIME_NS(st);
-    long ctime_ns = BUP_STAT_CTIME_NS(st);
-
-    if (!normalize_timespec_values("atime", &atime, &atime_ns, filename, fd))
-        return NULL;
-    if (!normalize_timespec_values("mtime", &mtime, &mtime_ns, filename, fd))
-        return NULL;
-    if (!normalize_timespec_values("ctime", &ctime, &ctime_ns, filename, fd))
-        return NULL;
-
     // We can check the known (via POSIX) signed and unsigned types at
     // compile time, but not (easily) the unspecified types, so handle
-    // those via INTEGER_TO_PY().
-    return Py_BuildValue("OKOOOOOL(Ll)(Ll)(Ll)",
+    // those via INTEGER_TO_PY().  Assumes ns values will fit in a
+    // long.
+    return Py_BuildValue("OKOOOOOL(Ol)(Ol)(Ol)",
                          INTEGER_TO_PY(st->st_mode),
                          (unsigned PY_LONG_LONG) st->st_ino,
                          INTEGER_TO_PY(st->st_dev),
@@ -1024,12 +969,12 @@ static PyObject *stat_struct_to_py(const struct stat *st,
                          INTEGER_TO_PY(st->st_gid),
                          INTEGER_TO_PY(st->st_rdev),
                          (PY_LONG_LONG) st->st_size,
-                         (PY_LONG_LONG) atime,
-                         (long) atime_ns,
-                         (PY_LONG_LONG) mtime,
-                         (long) mtime_ns,
-                         (PY_LONG_LONG) ctime,
-                         (long) ctime_ns);
+                         INTEGER_TO_PY(st->st_atime),
+                         (long) BUP_STAT_ATIME_NS(st),
+                         INTEGER_TO_PY(st->st_mtime),
+                         (long) BUP_STAT_MTIME_NS(st),
+                         INTEGER_TO_PY(st->st_ctime),
+                         (long) BUP_STAT_CTIME_NS(st));
 }
 
 
index 1d4bad35d08b814eadfe9dcc332b84c7d5fe0f3a..412e71d22795954d2a4e67fb72300c9bfbad0d55 100644 (file)
@@ -12,7 +12,7 @@ def test_fstime():
     WVPASSEQ(xstat.timespec_to_nsecs((-1, 0)), -10**9)
     WVPASSEQ(xstat.timespec_to_nsecs((-1, 10**9 / 2)), -500000000)
     WVPASSEQ(xstat.timespec_to_nsecs((-2, 10**9 / 2)), -1500000000)
-    WVEXCEPT(Exception, xstat.timespec_to_nsecs, (0, -1))
+    WVPASSEQ(xstat.timespec_to_nsecs((0, -1)), -1)
     WVPASSEQ(type(xstat.timespec_to_nsecs((2, 22222222))), type(0))
     WVPASSEQ(type(xstat.timespec_to_nsecs((-2, 22222222))), type(0))
 
index 23483f5991f6d0c226b672a03ce4445722dcf156..8daa2c2509e34246f917cadf08e94046aa4d02f1 100644 (file)
@@ -20,15 +20,12 @@ except AttributeError, e:
 
 
 def timespec_to_nsecs((ts_s, ts_ns)):
-    # c.f. _helpers.c: timespec_vals_to_py_ns()
-    if ts_ns < 0 or ts_ns > 999999999:
-        raise Exception('invalid timespec nsec value')
     return ts_s * 10**9 + ts_ns
 
 
 def nsecs_to_timespec(ns):
     """Return (s, ns) where ns is always non-negative
-    and t = s + ns / 10e8""" # metadata record rep (and libc rep)
+    and t = s + ns / 10e8""" # metadata record rep
     ns = int(ns)
     return (ns / 10**9, ns % 10**9)