X-Git-Url: https://arthur.barton.de/gitweb/?p=bup.git;a=blobdiff_plain;f=lib%2Fbup%2F_helpers.c;h=ba8cd6035b6e8ecbf70d66b0d4175a9c3c58a068;hp=b2eb7819a3fe4b2ab65aa09e7d2b583cf1ce6c11;hb=9c4acb514533925ccbfa6b5ceb88876fb36cb819;hpb=a8616d0366d3b0f77cdb9e68f2a8142b5a4c28e1 diff --git a/lib/bup/_helpers.c b/lib/bup/_helpers.c index b2eb781..ba8cd60 100644 --- a/lib/bup/_helpers.c +++ b/lib/bup/_helpers.c @@ -54,8 +54,13 @@ #ifdef BUP_HAVE_READLINE # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstrict-prototypes" -# include -# include +# ifdef BUP_READLINE_INCLUDES_IN_SUBDIR +# include +# include +# else +# include +# include +# endif # pragma GCC diagnostic pop #endif @@ -124,7 +129,7 @@ static void *checked_malloc(size_t n, size_t size) if (__builtin_mul_overflow(n, size, &total)) { PyErr_Format(PyExc_OverflowError, - "request to allocate %lu items of size %lu is too large", + "request to allocate %zu items of size %zu is too large", n, size); return NULL; } @@ -170,12 +175,17 @@ static uint64_t htonll(uint64_t value) }) -// At the moment any code that calls INTEGER_TO_PY() will have to -// disable -Wtautological-compare for clang. See below. - -#define INTEGER_TO_PY(x) \ - (((x) >= 0) ? PyLong_FromUnsignedLongLong(x) : PyLong_FromLongLong(x)) - +#define INTEGER_TO_PY(x) \ + ({ \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wtype-limits\""); \ + _Pragma("clang diagnostic push"); \ + _Pragma("clang diagnostic ignored \"-Wtautological-compare\""); \ + PyObject *result = ((x) >= 0) ? PyLong_FromUnsignedLongLong(x) : PyLong_FromLongLong(x); \ + _Pragma("clang diagnostic pop"); \ + _Pragma("GCC diagnostic pop"); \ + result; \ + }) #if PY_MAJOR_VERSION < 3 @@ -1572,9 +1582,6 @@ static PyObject *bup_lutimes(PyObject *self, PyObject *args) #endif -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-compare" // For INTEGER_TO_PY(). - static PyObject *stat_struct_to_py(const struct stat *st, const char *filename, int fd) @@ -1600,7 +1607,6 @@ static PyObject *stat_struct_to_py(const struct stat *st, (long) BUP_STAT_CTIME_NS(st)); } -#pragma clang diagnostic pop // ignored "-Wtautological-compare" static PyObject *bup_stat(PyObject *self, PyObject *args) { @@ -1719,7 +1725,7 @@ static PyObject *bup_mincore(PyObject *self, PyObject *args) result = PyErr_Format(PyExc_OverflowError, "src_n overflows size_t"); goto clean_and_return; } - int rc = mincore((void *)(src.buf + src_off), src_n, + int rc = mincore((void *)(src.buf + src_off), length, (BUP_MINCORE_BUF_TYPE *) (dest.buf + dest_off)); if (rc != 0) { result = PyErr_SetFromErrno(PyExc_OSError); @@ -1761,31 +1767,38 @@ static PyObject *tuple_from_cstrs(char **cstrs) return result; } +static PyObject *appropriate_errno_ex(void) +{ + switch (errno) { + case ENOMEM: + return PyErr_NoMemory(); + case EIO: + case EMFILE: + case ENFILE: + // In 3.3 IOError was merged into OSError. + return PyErr_SetFromErrno(PyExc_IOError); + default: + return PyErr_SetFromErrno(PyExc_OSError); + } +} -static long getpw_buf_size; -static PyObject *pwd_struct_to_py(const struct passwd *pwd, int rc) +static PyObject *pwd_struct_to_py(const struct passwd *pwd) { // We can check the known (via POSIX) signed and unsigned types at // compile time, but not (easily) the unspecified types, so handle // those via INTEGER_TO_PY(). - if (pwd != NULL) - return Py_BuildValue(cstr_argf cstr_argf "OO" - cstr_argf cstr_argf cstr_argf, - pwd->pw_name, - pwd->pw_passwd, - INTEGER_TO_PY(pwd->pw_uid), - INTEGER_TO_PY(pwd->pw_gid), - pwd->pw_gecos, - pwd->pw_dir, - pwd->pw_shell); - if (rc == 0) - return Py_BuildValue("O", Py_None); - if (rc == EIO || rc == EMFILE || rc == ENFILE) - return PyErr_SetFromErrno(PyExc_IOError); - if (rc < 0) - return PyErr_SetFromErrno(PyExc_OSError); - assert(0); + if (pwd == NULL) + Py_RETURN_NONE; + return Py_BuildValue(cstr_argf cstr_argf "OO" + cstr_argf cstr_argf cstr_argf, + pwd->pw_name, + pwd->pw_passwd, + INTEGER_TO_PY(pwd->pw_uid), + INTEGER_TO_PY(pwd->pw_gid), + pwd->pw_gecos, + pwd->pw_dir, + pwd->pw_shell); } static PyObject *bup_getpwuid(PyObject *self, PyObject *args) @@ -1797,15 +1810,11 @@ static PyObject *bup_getpwuid(PyObject *self, PyObject *args) if (!INTEGRAL_ASSIGNMENT_FITS(&uid, py_uid)) return PyErr_Format(PyExc_OverflowError, "uid too large for uid_t"); - struct passwd pwd, *result_pwd; - char *buf = PyMem_Malloc(getpw_buf_size); - if (buf == NULL) - return NULL; - - int rc = getpwuid_r(uid, &pwd, buf, getpw_buf_size, &result_pwd); - PyObject *result = pwd_struct_to_py(result_pwd, rc); - PyMem_Free(buf); - return result; + errno = 0; + struct passwd *pwd = getpwuid(uid); + if (!pwd && errno) + return appropriate_errno_ex(); + return pwd_struct_to_py(pwd); } static PyObject *bup_getpwnam(PyObject *self, PyObject *args) @@ -1814,41 +1823,30 @@ static PyObject *bup_getpwnam(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "S", &py_name)) return NULL; - struct passwd pwd, *result_pwd; - char *buf = PyMem_Malloc(getpw_buf_size); - if (buf == NULL) - return NULL; - char *name = PyBytes_AS_STRING(py_name); - int rc = getpwnam_r(name, &pwd, buf, getpw_buf_size, &result_pwd); - PyObject *result = pwd_struct_to_py(result_pwd, rc); - PyMem_Free(buf); - return result; + errno = 0; + struct passwd *pwd = getpwnam(name); + if (!pwd && errno) + return appropriate_errno_ex(); + return pwd_struct_to_py(pwd); } -static long getgr_buf_size; - -static PyObject *grp_struct_to_py(const struct group *grp, int rc) +static PyObject *grp_struct_to_py(const struct group *grp) { // We can check the known (via POSIX) signed and unsigned types at // compile time, but not (easily) the unspecified types, so handle // those via INTEGER_TO_PY(). - if (grp != NULL) { - PyObject *members = tuple_from_cstrs(grp->gr_mem); - if (members == NULL) - return NULL; - return Py_BuildValue(cstr_argf cstr_argf "OO", - grp->gr_name, - grp->gr_passwd, - INTEGER_TO_PY(grp->gr_gid), - members); - } - if (rc == 0) - return Py_BuildValue("O", Py_None); - errno = rc; - if (rc == EIO || rc == EMFILE || rc == ENFILE) - return PyErr_SetFromErrno(PyExc_IOError); - return PyErr_SetFromErrno(PyExc_OSError); + if (grp == NULL) + Py_RETURN_NONE; + + PyObject *members = tuple_from_cstrs(grp->gr_mem); + if (members == NULL) + return NULL; + return Py_BuildValue(cstr_argf cstr_argf "OO", + grp->gr_name, + grp->gr_passwd, + INTEGER_TO_PY(grp->gr_gid), + members); } static PyObject *bup_getgrgid(PyObject *self, PyObject *args) @@ -1860,15 +1858,11 @@ static PyObject *bup_getgrgid(PyObject *self, PyObject *args) if (!INTEGRAL_ASSIGNMENT_FITS(&gid, py_gid)) return PyErr_Format(PyExc_OverflowError, "gid too large for gid_t"); - struct group grp, *result_grp; - char *buf = PyMem_Malloc(getgr_buf_size); - if (buf == NULL) - return NULL; - - int rc = getgrgid_r(gid, &grp, buf, getgr_buf_size, &result_grp); - PyObject *result = grp_struct_to_py(result_grp, rc); - PyMem_Free(buf); - return result; + errno = 0; + struct group *grp = getgrgid(gid); + if (!grp && errno) + return appropriate_errno_ex(); + return grp_struct_to_py(grp); } static PyObject *bup_getgrnam(PyObject *self, PyObject *args) @@ -1877,18 +1871,15 @@ static PyObject *bup_getgrnam(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "S", &py_name)) return NULL; - struct group grp, *result_grp; - char *buf = PyMem_Malloc(getgr_buf_size); - if (buf == NULL) - return NULL; - char *name = PyBytes_AS_STRING(py_name); - int rc = getgrnam_r(name, &grp, buf, getgr_buf_size, &result_grp); - PyObject *result = grp_struct_to_py(result_grp, rc); - PyMem_Free(buf); - return result; + errno = 0; + struct group *grp = getgrnam(name); + if (!grp && errno) + return appropriate_errno_ex(); + return grp_struct_to_py(grp); } + static PyObject *bup_gethostname(PyObject *mod, PyObject *ignore) { #ifdef HOST_NAME_MAX @@ -2419,8 +2410,6 @@ static int setup_module(PyObject *m) } char *e; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-compare" // For INTEGER_TO_PY(). { PyObject *value; value = INTEGER_TO_PY(INT_MAX); @@ -2452,15 +2441,6 @@ static int setup_module(PyObject *m) Py_DECREF(value); } #endif -#pragma clang diagnostic pop // ignored "-Wtautological-compare" - - getpw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX); - if (getpw_buf_size == -1) - getpw_buf_size = 16384; - - getgr_buf_size = sysconf(_SC_GETGR_R_SIZE_MAX); - if (getgr_buf_size == -1) - getgr_buf_size = 16384; e = getenv("BUP_FORCE_TTY"); get_state(m)->istty2 = isatty(2) || (atoi(e ? e : "0") & 2);