summaryrefslogtreecommitdiff
path: root/_summainmodule.c
diff options
context:
space:
mode:
Diffstat (limited to '_summainmodule.c')
-rw-r--r--_summainmodule.c137
1 files changed, 124 insertions, 13 deletions
diff --git a/_summainmodule.c b/_summainmodule.c
index d008fef..73618ea 100644
--- a/_summainmodule.c
+++ b/_summainmodule.c
@@ -1,8 +1,8 @@
/*
- * _summainmodule.c -- Python extensions for Summain
+ * _obnammodule.c -- Python extensions for Obnam
+ *
+ * Copyright (C) 2008-2014 Lars Wirzenius <liw@liw.fi>
*
- * Copyright (C) 2008, 2009 Lars Wirzenius <liw@liw.fi>
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
@@ -19,6 +19,20 @@
*/
+/*
+ * This is a Python extension module written for Obnam, the backup
+ * software.
+ *
+ * This module provides a way to call the posix_fadvise function from
+ * Python. Obnam uses this to use set the POSIX_FADV_SEQUENTIAL and
+ * POSIX_FADV_DONTNEED flags, to make sure the kernel knows that it will
+ * read files sequentially and that the data does not need to be cached.
+ * This makes Obnam not trash the disk buffer cache, which is nice.
+ */
+
+
+#define _FILE_OFFSET_BITS 64
+
#include <Python.h>
@@ -34,14 +48,84 @@
#include <unistd.h>
#include <stdlib.h>
-#ifdef __FreeBSD__
- #define NO_NANOSECONDS 1
+#if defined(__FreeBSD__)
#include <sys/extattr.h>
+ #define NO_NANOSECONDS 1
+#elif defined(__APPLE__)
+ #include <sys/xattr.h>
+ #define NO_NANOSECONDS 1
+ #define llistxattr(path, list, size) \
+ (listxattr(path, list, size, XATTR_NOFOLLOW))
+ #define lgetxattr(path, name, value, size) \
+ (getxattr(path, name, value, size, 0, XATTR_NOFOLLOW))
+ #define lsetxattr(path, name, value, size, flags) \
+ (setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW))
#else
- #define NO_NANOSECONDS 0
#include <sys/xattr.h>
+ #define NO_NANOSECONDS 0
#endif
+
+static PyObject *
+fadvise_dontneed(PyObject *self, PyObject *args)
+{
+#if POSIX_FADV_DONTNEED
+ int fd;
+ /* Can't use off_t for offset and len, since PyArg_ParseTuple
+ doesn't know it. */
+ unsigned long long offset;
+ unsigned long long len;
+ int ret;
+
+ if (!PyArg_ParseTuple(args, "iLL", &fd, &offset, &len))
+ return NULL;
+ ret = posix_fadvise(fd, offset, len, POSIX_FADV_DONTNEED);
+ return Py_BuildValue("i", ret);
+#else
+ return Py_BuildValue("i", 0);
+#endif
+}
+
+
+static PyObject *
+utimensat_wrapper(PyObject *self, PyObject *args)
+{
+ int ret;
+ const char *filename;
+ long atime_sec, atime_nsec;
+ long mtime_sec, mtime_nsec;
+#if NO_NANOSECONDS
+ struct timeval tv[2];
+#else
+ struct timespec tv[2];
+#endif
+ if (!PyArg_ParseTuple(args, "sllll",
+ &filename,
+ &atime_sec,
+ &atime_nsec,
+ &mtime_sec,
+ &mtime_nsec))
+ return NULL;
+
+#if NO_NANOSECONDS
+ tv[0].tv_sec = atime_sec;
+ tv[0].tv_usec = atime_nsec / 1000;
+ tv[1].tv_sec = mtime_sec;
+ tv[1].tv_usec = mtime_nsec / 1000;
+ ret = lutimes(filename, tv);
+#else
+ tv[0].tv_sec = atime_sec;
+ tv[0].tv_nsec = atime_nsec;
+ tv[1].tv_sec = mtime_sec;
+ tv[1].tv_nsec = mtime_nsec;
+ ret = utimensat(AT_FDCWD, filename, tv, AT_SYMLINK_NOFOLLOW);
+#endif
+ if (ret == -1)
+ ret = errno;
+ return Py_BuildValue("i", ret);
+}
+
+
/*
* Since we can't set nanosecond mtime and atimes on some platforms, also
* don't retrieve that level of precision from lstat(), so comparisons
@@ -84,12 +168,21 @@ lstat_wrapper(PyObject *self, PyObject *args)
(long long) st.st_size,
(long long) st.st_blksize,
(long long) st.st_blocks,
+#ifdef __APPLE__
+ (long long) st.st_atimespec.tv_sec,
+ remove_precision(st.st_atimespec.tv_nsec),
+ (long long) st.st_mtimespec.tv_sec,
+ remove_precision(st.st_mtimespec.tv_nsec),
+ (long long) st.st_ctimespec.tv_sec,
+ remove_precision(st.st_ctimespec.tv_nsec));
+#else
(long long) st.st_atim.tv_sec,
remove_precision(st.st_atim.tv_nsec),
(long long) st.st_mtim.tv_sec,
remove_precision(st.st_mtim.tv_nsec),
(long long) st.st_ctim.tv_sec,
remove_precision(st.st_ctim.tv_nsec));
+#endif
}
@@ -108,6 +201,10 @@ llistxattr_wrapper(PyObject *self, PyObject *args)
#ifdef __FreeBSD__
bufsize = extattr_list_link(filename, EXTATTR_NAMESPACE_USER, NULL, 0);
buf = malloc(bufsize);
+ if (buf == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
n = extattr_list_link(filename, EXTATTR_NAMESPACE_USER, buf, bufsize);
if (n >= 0) {
/* Convert from length-prefixed BSD style to '\0'-suffixed
@@ -115,11 +212,11 @@ llistxattr_wrapper(PyObject *self, PyObject *args)
size_t i = 0;
while (i < n) {
unsigned char length = (unsigned char) buf[i];
- memmove(buf + i, buf + i + 1, length);
- buf[i + length] = '\0';
- i += length + 1;
- }
- o = Py_BuildValue("s#", buf, (int) n);
+ memmove(buf + i, buf + i + 1, length);
+ buf[i + length] = '\0';
+ i += length + 1;
+ }
+ o = Py_BuildValue("s#", buf, (int) n);
} else {
o = Py_BuildValue("i", errno);
}
@@ -130,6 +227,10 @@ llistxattr_wrapper(PyObject *self, PyObject *args)
do {
bufsize += 1024;
buf = malloc(bufsize);
+ if (buf == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
n = llistxattr(filename, buf, bufsize);
if (n >= 0)
@@ -159,8 +260,13 @@ lgetxattr_wrapper(PyObject *self, PyObject *args)
do {
bufsize += 1024;
char *buf = malloc(bufsize);
+ if (buf == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
#ifdef __FreeBSD__
- int n = extattr_get_link(filename, EXTATTR_NAMESPACE_USER, attrname, buf, bufsize);
+ int n = extattr_get_link(filename, EXTATTR_NAMESPACE_USER,
+ attrname, buf, bufsize);
#else
ssize_t n = lgetxattr(filename, attrname, buf, bufsize);
#endif
@@ -188,7 +294,8 @@ lsetxattr_wrapper(PyObject *self, PyObject *args)
return NULL;
#ifdef __FreeBSD__
- ret = extattr_set_link(filename, EXTATTR_NAMESPACE_USER, name, value, size);
+ ret = extattr_set_link(filename, EXTATTR_NAMESPACE_USER,
+ name, value, size);
#else
ret = lsetxattr(filename, name, value, size, 0);
#endif
@@ -199,6 +306,10 @@ lsetxattr_wrapper(PyObject *self, PyObject *args)
static PyMethodDef methods[] = {
+ {"fadvise_dontneed", fadvise_dontneed, METH_VARARGS,
+ "Call posix_fadvise(2) with POSIX_FADV_DONTNEED argument."},
+ {"utimensat", utimensat_wrapper, METH_VARARGS,
+ "utimensat(2) wrapper."},
{"lstat", lstat_wrapper, METH_VARARGS,
"lstat(2) wrapper; arg is filename, returns tuple."},
{"llistxattr", llistxattr_wrapper, METH_VARARGS,