X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fbup%2F_helpers.c;h=9078be3da723d8e7757662950a7521bdc275754f;hb=544208fae44dfeaccb626c16f3a5c387f318d08f;hp=04a5cb6a7bd01c71ea383ecc66dbcb6f2865374c;hpb=3ff7455dd474533a6ceaef6f7b9e49c8059b07a2;p=bup.git diff --git a/lib/bup/_helpers.c b/lib/bup/_helpers.c index 04a5cb6..9078be3 100644 --- a/lib/bup/_helpers.c +++ b/lib/bup/_helpers.c @@ -29,6 +29,9 @@ #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_SYS_TIME_H +#include +#endif #ifdef HAVE_LINUX_FS_H #include @@ -63,7 +66,19 @@ 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 @@ -95,6 +110,8 @@ static uint64_t htonll(uint64_t value) (((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) { @@ -115,12 +132,15 @@ static int bup_ulong_from_pyint(unsigned long *x, PyObject *py, *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)) { @@ -159,6 +179,7 @@ static int bup_uint_from_py(unsigned int *x, PyObject *py, const char *name) 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; @@ -169,6 +190,7 @@ static int bup_ullong_from_py(unsigned PY_LONG_LONG *x, PyObject *py, } return 0; } +#endif if (!PyLong_Check(py)) { @@ -723,6 +745,11 @@ struct sha { 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; @@ -733,17 +760,6 @@ struct idx { 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; @@ -842,7 +858,7 @@ static PyObject *merge_into(PyObject *self, PyObject *args) { 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]; @@ -1234,7 +1250,7 @@ static PyObject *bup_utimensat(PyObject *self, PyObject *args) 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), @@ -1276,7 +1292,7 @@ static int bup_parse_xutimes_args(char **path, 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)) @@ -1392,7 +1408,7 @@ static PyObject *bup_stat(PyObject *self, PyObject *args) int rc; char *filename; - if (!PyArg_ParseTuple(args, "s", &filename)) + if (!PyArg_ParseTuple(args, cstr_argf, &filename)) return NULL; struct stat st; @@ -1408,7 +1424,7 @@ static PyObject *bup_lstat(PyObject *self, PyObject *args) int rc; char *filename; - if (!PyArg_ParseTuple(args, "s", &filename)) + if (!PyArg_ParseTuple(args, cstr_argf, &filename)) return NULL; struct stat st; @@ -1462,43 +1478,59 @@ static PyObject *bup_localtime(PyObject *self, PyObject *args) #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 */ @@ -1575,12 +1607,12 @@ static PyMethodDef helper_methods[] = { { 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)); @@ -1600,10 +1632,6 @@ PyMODINIT_FUNC init_helpers(void) } 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(). { @@ -1640,6 +1668,52 @@ PyMODINIT_FUNC init_helpers(void) #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