#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
typedef unsigned char byte;
-static int istty2 = 0;
+
+typedef struct {
+ int istty2;
+} state_t;
+
+#if PY_MAJOR_VERSION < 3
+static state_t state;
+# define get_state(x) (&state)
+# define cstr_argf "s"
+#else
+# define get_state(x) ((state_t *) PyModule_GetState(x))
+# define cstr_argf "y"
+#endif // PY_MAJOR_VERSION >= 3
#ifndef htonll
(((x) >= 0) ? PyLong_FromUnsignedLongLong(x) : PyLong_FromLongLong(x))
+
+#if PY_MAJOR_VERSION < 3
static int bup_ulong_from_pyint(unsigned long *x, PyObject *py,
const char *name)
{
*x = tmp;
return 1;
}
+#endif
static int bup_ulong_from_py(unsigned long *x, PyObject *py, const char *name)
{
+#if PY_MAJOR_VERSION < 3
if (PyInt_Check(py))
return bup_ulong_from_pyint(x, py, name);
+#endif
if (!PyLong_Check(py))
{
static int bup_ullong_from_py(unsigned PY_LONG_LONG *x, PyObject *py,
const char *name)
{
+#if PY_MAJOR_VERSION < 3
if (PyInt_Check(py))
{
unsigned long tmp;
}
return 0;
}
+#endif
if (!PyLong_Check(py))
{
unsigned char bytes[20];
};
+static inline int _cmp_sha(const struct sha *sha1, const struct sha *sha2)
+{
+ return memcmp(sha1->bytes, sha2->bytes, sizeof(sha1->bytes));
+}
+
struct idx {
unsigned char *map;
int name_base;
};
-
-static int _cmp_sha(const struct sha *sha1, const struct sha *sha2)
-{
- int i;
- for (i = 0; i < sizeof(struct sha); i++)
- if (sha1->bytes[i] != sha2->bytes[i])
- return sha1->bytes[i] - sha2->bytes[i];
- return 0;
-}
-
-
static void _fix_idx_order(struct idx **idxs, int *last_i)
{
struct idx *idx;
{
struct idx *idx;
uint32_t new_prefix;
- if (count % 102424 == 0 && istty2)
+ if (count % 102424 == 0 && get_state(self)->istty2)
fprintf(stderr, "midx: writing %.2f%% (%d/%d)\r",
count*100.0/total, count, total);
idx = idxs[last_i];
PyObject *access_py, *modification_py;
struct timespec ts[2];
- if (!PyArg_ParseTuple(args, "is((Ol)(Ol))i",
+ if (!PyArg_ParseTuple(args, "i" cstr_argf "((Ol)(Ol))i",
&fd,
&path,
&access_py, &(ts[0].tv_nsec),
PyObject *access_py, *modification_py;
long long access_us, modification_us; // POSIX guarantees tv_usec is signed.
- if (!PyArg_ParseTuple(args, "s((OL)(OL))",
+ if (!PyArg_ParseTuple(args, cstr_argf "((OL)(OL))",
path,
&access_py, &access_us,
&modification_py, &modification_us))
int rc;
char *filename;
- if (!PyArg_ParseTuple(args, "s", &filename))
+ if (!PyArg_ParseTuple(args, cstr_argf, &filename))
return NULL;
struct stat st;
int rc;
char *filename;
- if (!PyArg_ParseTuple(args, "s", &filename))
+ if (!PyArg_ParseTuple(args, cstr_argf, &filename))
return NULL;
struct stat st;
#ifdef BUP_MINCORE_BUF_TYPE
static PyObject *bup_mincore(PyObject *self, PyObject *args)
{
- const char *src;
- Py_ssize_t src_ssize;
- Py_buffer dest;
+ Py_buffer src, dest;
PyObject *py_src_n, *py_src_off, *py_dest_off;
- if (!PyArg_ParseTuple(args, "s#OOw*O",
- &src, &src_ssize, &py_src_n, &py_src_off,
+
+ if (!PyArg_ParseTuple(args, cstr_argf "*OOw*O",
+ &src, &py_src_n, &py_src_off,
&dest, &py_dest_off))
return NULL;
- unsigned long long src_size, src_n, src_off, dest_size, dest_off;
+ PyObject *result = NULL;
+
+ unsigned long long src_n, src_off, dest_off;
if (!(bup_ullong_from_py(&src_n, py_src_n, "src_n")
&& bup_ullong_from_py(&src_off, py_src_off, "src_off")
&& bup_ullong_from_py(&dest_off, py_dest_off, "dest_off")))
- return NULL;
+ goto clean_and_return;
- if (!INTEGRAL_ASSIGNMENT_FITS(&src_size, src_ssize))
- return PyErr_Format(PyExc_OverflowError, "invalid src size");
unsigned long long src_region_end;
+ if (!uadd(&src_region_end, src_off, src_n)) {
+ result = PyErr_Format(PyExc_OverflowError, "(src_off + src_n) too large");
+ goto clean_and_return;
+ }
+ if (src_region_end > src.len) {
+ result = PyErr_Format(PyExc_OverflowError, "region runs off end of src");
+ goto clean_and_return;
+ }
- if (!uadd(&src_region_end, src_off, src_n))
- return PyErr_Format(PyExc_OverflowError, "(src_off + src_n) too large");
- if (src_region_end > src_size)
- return PyErr_Format(PyExc_OverflowError, "region runs off end of src");
-
- if (!INTEGRAL_ASSIGNMENT_FITS(&dest_size, dest.len))
- return PyErr_Format(PyExc_OverflowError, "invalid dest size");
- if (dest_off > dest_size)
- return PyErr_Format(PyExc_OverflowError, "region runs off end of dest");
+ unsigned long long dest_size;
+ if (!INTEGRAL_ASSIGNMENT_FITS(&dest_size, dest.len)) {
+ result = PyErr_Format(PyExc_OverflowError, "invalid dest size");
+ goto clean_and_return;
+ }
+ if (dest_off > dest_size) {
+ result = PyErr_Format(PyExc_OverflowError, "region runs off end of dest");
+ goto clean_and_return;
+ }
size_t length;
- if (!INTEGRAL_ASSIGNMENT_FITS(&length, src_n))
- return PyErr_Format(PyExc_OverflowError, "src_n overflows size_t");
- int rc = mincore((void *)(src + src_off), src_n,
+ if (!INTEGRAL_ASSIGNMENT_FITS(&length, src_n)) {
+ result = PyErr_Format(PyExc_OverflowError, "src_n overflows size_t");
+ goto clean_and_return;
+ }
+ int rc = mincore((void *)(src.buf + src_off), src_n,
(BUP_MINCORE_BUF_TYPE *) (dest.buf + dest_off));
- if (rc != 0)
- return PyErr_SetFromErrno(PyExc_OSError);
- return Py_BuildValue("O", Py_None);
+ if (rc != 0) {
+ result = PyErr_SetFromErrno(PyExc_OSError);
+ goto clean_and_return;
+ }
+ result = Py_BuildValue("O", Py_None);
+
+ clean_and_return:
+ PyBuffer_Release(&src);
+ PyBuffer_Release(&dest);
+ return result;
}
#endif /* def BUP_MINCORE_BUF_TYPE */
{ NULL, NULL, 0, NULL }, // sentinel
};
-
-PyMODINIT_FUNC init_helpers(void)
+static int setup_module(PyObject *m)
{
- // FIXME: migrate these tests to configure. Check against the
- // type we're going to use when passing to python. Other stat
- // types are tested at runtime.
+ // FIXME: migrate these tests to configure, or at least don't
+ // possibly crash the whole application. Check against the type
+ // we're going to use when passing to python. Other stat types
+ // are tested at runtime.
assert(sizeof(ino_t) <= sizeof(unsigned PY_LONG_LONG));
assert(sizeof(off_t) <= sizeof(PY_LONG_LONG));
assert(sizeof(blksize_t) <= sizeof(PY_LONG_LONG));
}
char *e;
- PyObject *m = Py_InitModule("_helpers", helper_methods);
- if (m == NULL)
- return;
-
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare" // For INTEGER_TO_PY().
{
#pragma clang diagnostic pop // ignored "-Wtautological-compare"
e = getenv("BUP_FORCE_TTY");
- istty2 = isatty(2) || (atoi(e ? e : "0") & 2);
+ get_state(m)->istty2 = isatty(2) || (atoi(e ? e : "0") & 2);
unpythonize_argv();
+ return 1;
+}
+
+
+#if PY_MAJOR_VERSION < 3
+
+PyMODINIT_FUNC init_helpers(void)
+{
+ PyObject *m = Py_InitModule("_helpers", helper_methods);
+ if (m == NULL)
+ return;
+
+ if (!setup_module(m))
+ {
+ Py_DECREF(m);
+ return;
+ }
+}
+
+# else // PY_MAJOR_VERSION >= 3
+
+static struct PyModuleDef helpers_def = {
+ PyModuleDef_HEAD_INIT,
+ "_helpers",
+ NULL,
+ sizeof(state_t),
+ helper_methods,
+ NULL,
+ NULL, // helpers_traverse,
+ NULL, // helpers_clear,
+ NULL
+};
+
+PyMODINIT_FUNC PyInit__helpers(void)
+{
+ PyObject *module = PyModule_Create(&helpers_def);
+ if (module == NULL)
+ return NULL;
+ if (!setup_module(module))
+ {
+ Py_DECREF(module);
+ return NULL;
+ }
+ return module;
}
+
+#endif // PY_MAJOR_VERSION >= 3