From b3d587fafc524f42ae5acac596075651e127e4cd Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 16 Aug 2015 17:26:34 +0200 Subject: Copy new version from Obnam This is now identical as Obnam's extension module, except the init function is init_summain, not init_obnam. --- _summainmodule.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file 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 * - * Copyright (C) 2008, 2009 Lars Wirzenius - * * 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 @@ -34,14 +48,84 @@ #include #include -#ifdef __FreeBSD__ - #define NO_NANOSECONDS 1 +#if defined(__FreeBSD__) #include + #define NO_NANOSECONDS 1 +#elif defined(__APPLE__) + #include + #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 + #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, -- cgit v1.2.1