]> arthur.barton.de Git - bup.git/commitdiff
Add helpers.fstat and _helpers._have_ns_fs_timestamps.
authorRob Browning <rlb@defaultvalue.org>
Sun, 24 Oct 2010 21:05:55 +0000 (16:05 -0500)
committerRob Browning <rlb@defaultvalue.org>
Sun, 24 Oct 2010 21:16:04 +0000 (16:16 -0500)
lib/bup/_helpers.c
lib/bup/helpers.py
lib/bup/t/thelpers.py

index 3fd9b8e94e0836092e55e7822c8aa134310ec49c..9eef6f224353ca1f56f8c0fdb519b6b38d90a355 100644 (file)
@@ -335,8 +335,8 @@ static PyObject *bup_utimensat(PyObject *self, PyObject *args)
 
 
 #ifdef linux /* and likely others */
-#define HAVE_BUP_LSTAT 1
 
+#define HAVE_BUP_LSTAT 1
 static PyObject *bup_lstat(PyObject *self, PyObject *args)
 {
     int rc;
@@ -370,6 +370,39 @@ static PyObject *bup_lstat(PyObject *self, PyObject *args)
                          (long) st.st_ctim.tv_nsec);
 }
 
+#define HAVE_BUP_FSTAT 1
+static PyObject *bup_fstat(PyObject *self, PyObject *args)
+{
+    int rc, fd;
+
+    if (!PyArg_ParseTuple(args, "i", &fd))
+        return NULL;
+
+    struct stat st;
+    rc = fstat(fd, &st);
+    if (rc != 0)
+        return PyErr_SetFromErrno(PyExc_IOError);
+
+    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);
+}
+
 #endif /* def linux */
 
 
@@ -405,6 +438,10 @@ static PyMethodDef helper_methods[] = {
 #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
 };
@@ -420,4 +457,7 @@ PyMODINIT_FUNC init_helpers(void)
     PyModule_AddObject(m, "AT_SYMLINK_NOFOLLOW",
                        Py_BuildValue("i", AT_SYMLINK_NOFOLLOW));
 #endif
+#ifdef HAVE_BUP_LSTAT
+    PyModule_AddObject(m, "_have_ns_fs_timestamps", Py_BuildValue("i", 1));
+#endif
 }
index 1223456b0f889c40516c99d5ec1e974a3994d9c6..53b94596f1b718be8e00541ff763395f4e70ac88 100644 (file)
@@ -509,41 +509,54 @@ def utime(path, times):
 
 
 class stat_result():
-    pass
+
+    @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 = FSTime.from_stat_time(st.st_atime)
+            mtime = FSTime.from_stat_time(st.st_mtime)
+            ctime = FSTime.from_stat_time(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)
+        return result
+
+
+def fstat(path):
+    if _helpers.fstat:
+        st = _helpers.fstat(path)
+    else:
+        st = os.fstat(path)
+    return stat_result.from_stat_rep(st)
 
 
 def lstat(path):
-    result = stat_result()
     if _helpers.lstat:
         st = _helpers.lstat(path)
-        (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:
         st = os.lstat(path)
-        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 = FSTime.from_stat_time(st.st_atime)
-        mtime = FSTime.from_stat_time(st.st_mtime)
-        ctime = FSTime.from_stat_time(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)
-    return result
+    return stat_result.from_stat_rep(st)
 
 
 # hashlib is only available in python 2.5 or higher, but the 'sha' module
index 8fec0f55df91c468629785228fd4564918f214c5..6ca4b9d65ca70a195daac8183e05d2bd705cb4d0 100644 (file)
@@ -67,10 +67,10 @@ def _test_fstime():
 @wvtest
 def test_fstime():
     _test_fstime();
-    if _helpers.lstat: # Also test native python timestamp rep since we can.
-        orig_lstat = _helpers.lstat
+    if _helpers._have_ns_fs_timestamps: # Test native python timestamp rep too.
+        orig = _helpers._have_ns_fs_timestamps
         try:
-            _helpers.lstat = None
+            _helpers._have_ns_fs_timestamps = None
             _test_fstime();
         finally:
-            _helpers.lstat = orig_lstat
+            _helpers._have_ns_fs_timestamps = orig