#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>
#ifdef linux
#include <linux/fs.h>
#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
#endif
static int istty2 = 0;
|| _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;
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;
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;
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,
{ "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
};
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);
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):
@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))