From fdae3a6a7f4a0d5f9fcde8124686eb09dd4cace0 Mon Sep 17 00:00:00 2001 From: Rob Browning Date: Sun, 24 Oct 2010 16:05:55 -0500 Subject: [PATCH] Add helpers.fstat and _helpers._have_ns_fs_timestamps. --- lib/bup/_helpers.c | 42 +++++++++++++++++++++++++- lib/bup/helpers.py | 69 +++++++++++++++++++++++++------------------ lib/bup/t/thelpers.py | 8 ++--- 3 files changed, 86 insertions(+), 33 deletions(-) diff --git a/lib/bup/_helpers.c b/lib/bup/_helpers.c index 3fd9b8e..9eef6f2 100644 --- a/lib/bup/_helpers.c +++ b/lib/bup/_helpers.c @@ -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 } diff --git a/lib/bup/helpers.py b/lib/bup/helpers.py index 1223456..53b9459 100644 --- a/lib/bup/helpers.py +++ b/lib/bup/helpers.py @@ -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 diff --git a/lib/bup/t/thelpers.py b/lib/bup/t/thelpers.py index 8fec0f5..6ca4b9d 100644 --- a/lib/bup/t/thelpers.py +++ b/lib/bup/t/thelpers.py @@ -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 -- 2.39.2