X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fpython-systemd%2F_reader.c;h=c6f29f5e33de5d6bdebc392fd6b503f8bc3e036b;hb=118bf4bad88366fc210a92561b3bf056630a3592;hp=9d7ce2da2738a43086818f7cae0dfb6ec25eea5e;hpb=d2dd0265b5140ce849cfc3821ad595df2d4c9eb7;p=elogind.git diff --git a/src/python-systemd/_reader.c b/src/python-systemd/_reader.c index 9d7ce2da2..c6f29f5e3 100644 --- a/src/python-systemd/_reader.c +++ b/src/python-systemd/_reader.c @@ -24,12 +24,43 @@ #include #include +#if PY_MAJOR_VERSION >=3 +# define unicode_FromStringAndSize PyUnicode_FromStringAndSize +# define unicode_FromString PyUnicode_FromString +# define long_FromLong PyLong_FromLong +# define long_FromSize_t PyLong_FromSize_t +# define long_Check PyLong_Check +# define long_AsLong PyLong_AsLong +#else +/* Python 3 type naming convention is used */ +# define unicode_FromStringAndSize PyString_FromStringAndSize +# define unicode_FromString PyString_FromString +# define long_FromLong PyInt_FromLong +# define long_FromSize_t PyInt_FromSize_t +# define long_Check PyInt_Check +# define long_AsLong PyInt_AsLong +#endif + typedef struct { PyObject_HEAD sd_journal *j; } Journal; static PyTypeObject JournalType; +static int set_error(int r, const char* path, const char* invalid_message) { + if (r >= 0) + return r; + if (r == -EINVAL && invalid_message) + PyErr_SetString(PyExc_ValueError, invalid_message); + else if (r == -ENOMEM) + PyErr_SetString(PyExc_MemoryError, "Not enough memory"); + else { + errno = -r; + PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); + } + return 1; +} + static void Journal_dealloc(Journal* self) { @@ -53,12 +84,12 @@ PyDoc_STRVAR(Journal__doc__, static int Journal_init(Journal *self, PyObject *args, PyObject *keywds) { - int flags=SD_JOURNAL_LOCAL_ONLY; - char *path=NULL; + int flags = SD_JOURNAL_LOCAL_ONLY; + char *path = NULL; - static char *kwlist[] = {"flags", "path", NULL}; - if (! PyArg_ParseTupleAndKeywords(args, keywds, "|is", kwlist, - &flags, &path)) + static const char* const kwlist[] = {"flags", "path", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iz", (char**) kwlist, + &flags, &path)) return 1; int r; @@ -69,16 +100,8 @@ Journal_init(Journal *self, PyObject *args, PyObject *keywds) r = sd_journal_open(&self->j, flags); } Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyObject *errtype = r == -EINVAL ? PyExc_ValueError : - r == -ENOMEM ? PyExc_MemoryError : - PyExc_OSError; - PyErr_SetFromErrnoWithFilename(errtype, path); - return -1; - } - return 0; + return set_error(r, path, "Invalid flags or path"); } PyDoc_STRVAR(Journal_get_next__doc__, @@ -97,7 +120,7 @@ Journal_get_next(Journal *self, PyObject *args) return NULL; } - int r; + int r = -EINVAL; Py_BEGIN_ALLOW_THREADS if (skip == 1LL) { r = sd_journal_next(self->j); @@ -110,13 +133,11 @@ Journal_get_next(Journal *self, PyObject *args) } Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); + set_error(r, NULL, NULL); + if (r < 0) return NULL; - }else if ( r == 0) { //EOF + else if (r == 0) /* EOF */ return PyDict_New(); - } PyObject *dict; dict = PyDict_New(); @@ -128,11 +149,7 @@ Journal_get_next(Journal *self, PyObject *args) SD_JOURNAL_FOREACH_DATA(self->j, msg, msg_len) { delim_ptr = memchr(msg, '=', msg_len); -#if PY_MAJOR_VERSION >=3 - key = PyUnicode_FromStringAndSize(msg, delim_ptr - (const char*) msg); -#else - key = PyString_FromStringAndSize(msg, delim_ptr - (const char*) msg); -#endif + key = unicode_FromStringAndSize(msg, delim_ptr - (const char*) msg); value = PyBytes_FromStringAndSize(delim_ptr + 1, (const char*) msg + msg_len - (delim_ptr + 1) ); if (PyDict_Contains(dict, key)) { cur_value = PyDict_GetItem(dict, key); @@ -156,12 +173,7 @@ Journal_get_next(Journal *self, PyObject *args) if (sd_journal_get_realtime_usec(self->j, &realtime) == 0) { char realtime_str[20]; sprintf(realtime_str, "%llu", (long long unsigned) realtime); - -#if PY_MAJOR_VERSION >=3 - key = PyUnicode_FromString("__REALTIME_TIMESTAMP"); -#else - key = PyString_FromString("__REALTIME_TIMESTAMP"); -#endif + key = unicode_FromString("__REALTIME_TIMESTAMP"); value = PyBytes_FromString(realtime_str); PyDict_SetItem(dict, key, value); Py_DECREF(key); @@ -173,11 +185,7 @@ Journal_get_next(Journal *self, PyObject *args) if (sd_journal_get_monotonic_usec(self->j, &monotonic, &sd_id) == 0) { char monotonic_str[20]; sprintf(monotonic_str, "%llu", (long long unsigned) monotonic); -#if PY_MAJOR_VERSION >=3 - key = PyUnicode_FromString("__MONOTONIC_TIMESTAMP"); -#else - key = PyString_FromString("__MONOTONIC_TIMESTAMP"); -#endif + key = unicode_FromString("__MONOTONIC_TIMESTAMP"); value = PyBytes_FromString(monotonic_str); PyDict_SetItem(dict, key, value); @@ -187,11 +195,7 @@ Journal_get_next(Journal *self, PyObject *args) char *cursor; if (sd_journal_get_cursor(self->j, &cursor) > 0) { //Should return 0... -#if PY_MAJOR_VERSION >=3 - key = PyUnicode_FromString("__CURSOR"); -#else - key = PyString_FromString("__CURSOR"); -#endif + key = unicode_FromString("__CURSOR"); value = PyBytes_FromString(cursor); PyDict_SetItem(dict, key, value); free(cursor); @@ -213,120 +217,29 @@ Journal_get_previous(Journal *self, PyObject *args) if (! PyArg_ParseTuple(args, "|L", &skip)) return NULL; - return PyObject_CallMethod((PyObject *)self, "get_next", "L", -skip); + return PyObject_CallMethod((PyObject *)self, (char*) "get_next", + (char*) "L", -skip); } PyDoc_STRVAR(Journal_add_match__doc__, -"add_match(match, ..., field=value, ...) -> None\n\n" +"add_match(match) -> None\n\n" "Add a match to filter journal log entries. All matches of different\n" -"field are combined in logical AND, and matches of the same field\n" +"fields are combined in logical AND, and matches of the same field\n" "are automatically combined in logical OR.\n" -"Matches can be passed as strings \"field=value\", or keyword\n" -"arguments field=\"value\"."); +"Match is string of form \"field=value\"."); static PyObject * Journal_add_match(Journal *self, PyObject *args, PyObject *keywds) { - Py_ssize_t arg_match_len; - char *arg_match; - int i, r; - for (i = 0; i < PySequence_Size(args); i++) { -#if PY_MAJOR_VERSION >=3 - PyObject *arg; - arg = PySequence_Fast_GET_ITEM(args, i); - if (PyUnicode_Check(arg)) { -#if PY_MINOR_VERSION >=3 - arg_match = PyUnicode_AsUTF8AndSize(arg, &arg_match_len); -#else - PyObject *temp; - temp = PyUnicode_AsUTF8String(arg); - PyBytes_AsStringAndSize(temp, &arg_match, &arg_match_len); - Py_DECREF(temp); -#endif - }else if (PyBytes_Check(arg)) { - PyBytes_AsStringAndSize(arg, &arg_match, &arg_match_len); - }else{ - PyErr_SetString(PyExc_TypeError, "expected bytes or string"); - } -#else - PyString_AsStringAndSize(PySequence_Fast_GET_ITEM(args, i), &arg_match, &arg_match_len); -#endif - if (PyErr_Occurred()) - return NULL; - r = sd_journal_add_match(self->j, arg_match, arg_match_len); - if (r < 0) { - errno = -r; - PyObject *errtype = r == -EINVAL ? PyExc_ValueError : - r == -ENOMEM ? PyExc_MemoryError : - PyExc_OSError; - PyErr_SetFromErrno(errtype); - return NULL; - } - } - - if (! keywds) - Py_RETURN_NONE; - - PyObject *key, *value; - Py_ssize_t pos=0, match_key_len, match_value_len; + char *match; int match_len; - char *match_key, *match_value; - void *match; - while (PyDict_Next(keywds, &pos, &key, &value)) { -#if PY_MAJOR_VERSION >=3 - if (PyUnicode_Check(key)) { -#if PY_MINOR_VERSION >=3 - match_key = PyUnicode_AsUTF8AndSize(key, &match_key_len); -#else - PyObject *temp2; - temp2 = PyUnicode_AsUTF8String(key); - PyBytes_AsStringAndSize(temp2, &match_key, &match_key_len); - Py_DECREF(temp2); -#endif - }else if (PyBytes_Check(key)) { - PyBytes_AsStringAndSize(key, &match_key, &match_key_len); - }else{ - PyErr_SetString(PyExc_TypeError, "expected bytes or string"); - } - if (PyUnicode_Check(value)) { -#if PY_MINOR_VERSION >=3 - match_value = PyUnicode_AsUTF8AndSize(value, &match_value_len); -#else - PyObject *temp3; - temp3 = PyUnicode_AsUTF8String(value); - PyBytes_AsStringAndSize(temp3, &match_value, &match_value_len); - Py_DECREF(temp3); -#endif - }else if (PyBytes_Check(value)) { - PyBytes_AsStringAndSize(value, &match_value, &match_value_len); - }else{ - PyErr_SetString(PyExc_TypeError, "expected bytes or string"); - } -#else - PyString_AsStringAndSize(key, &match_key, &match_key_len); - PyString_AsStringAndSize(value, &match_value, &match_value_len); -#endif - if (PyErr_Occurred()) - return NULL; - - match_len = match_key_len + 1 + match_value_len; - match = malloc(match_len); - memcpy(match, match_key, match_key_len); - memcpy(match + match_key_len, "=", 1); - memcpy(match + match_key_len + 1, match_value, match_value_len); + if (! PyArg_ParseTuple(args, "s#", &match, &match_len)) + return NULL; - r = sd_journal_add_match(self->j, match, match_len); - free(match); - if (r == -EINVAL) { - PyErr_SetString(PyExc_ValueError, "Invalid match"); - return NULL; - }else if (r == -ENOMEM) { - PyErr_SetString(PyExc_MemoryError, "Not enough memory"); - return NULL; - }else if (r < 0) { - PyErr_SetString(PyExc_RuntimeError, "Error adding match"); + int r; + r = sd_journal_add_match(self->j, match, match_len); + set_error(r, NULL, "Invalid match"); + if (r < 0) return NULL; - } - } Py_RETURN_NONE; } @@ -340,13 +253,9 @@ Journal_add_disjunction(Journal *self, PyObject *args) { int r; r = sd_journal_add_disjunction(self->j); - if (r < 0) { - errno = -r; - PyObject *errtype = r == -ENOMEM ? PyExc_MemoryError : - PyExc_OSError; - PyErr_SetFromErrno(errtype); + set_error(r, NULL, NULL); + if (r < 0) return NULL; - } Py_RETURN_NONE; } @@ -372,10 +281,10 @@ Journal_seek(Journal *self, PyObject *args, PyObject *keywds) { int64_t offset; int whence=SEEK_SET; - static char *kwlist[] = {"offset", "whence", NULL}; - if (! PyArg_ParseTupleAndKeywords(args, keywds, "L|i", kwlist, - &offset, &whence)) + static const char* const kwlist[] = {"offset", "whence", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, keywds, "L|i", (char**) kwlist, + &offset, &whence)) return NULL; PyObject *result=NULL; @@ -384,37 +293,36 @@ Journal_seek(Journal *self, PyObject *args, PyObject *keywds) Py_BEGIN_ALLOW_THREADS r = sd_journal_seek_head(self->j); Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); + if (set_error(r, NULL, NULL)) return NULL; - } + if (offset > 0LL) { - result = PyObject_CallMethod((PyObject *)self, "get_next", "L", offset); + result = PyObject_CallMethod((PyObject *)self, (char*) "get_next", + (char*) "L", offset); } }else if (whence == SEEK_CUR){ - result = PyObject_CallMethod((PyObject *)self, "get_next", "L", offset); + result = PyObject_CallMethod((PyObject *)self, (char*) "get_next", + (char*) "L", offset); }else if (whence == SEEK_END){ int r; Py_BEGIN_ALLOW_THREADS r = sd_journal_seek_tail(self->j); Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); + if (set_error(r, NULL, NULL)) return NULL; - } + if (offset < 0LL) { - result = PyObject_CallMethod((PyObject *)self, "get_next", "L", offset); + result = PyObject_CallMethod((PyObject *)self, (char*) "get_next", + (char*) "L", offset); }else{ - result = PyObject_CallMethod((PyObject *)self, "get_next", "L", -1LL); + result = PyObject_CallMethod((PyObject *)self, (char*) "get_next", + (char*) "L", -1LL); } }else{ PyErr_SetString(PyExc_ValueError, "Invalid value for whence"); } - if (result) - Py_DECREF(result); + Py_XDECREF(result); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; @@ -423,15 +331,17 @@ Journal_seek(Journal *self, PyObject *args, PyObject *keywds) PyDoc_STRVAR(Journal_seek_realtime__doc__, "seek_realtime(realtime) -> None\n\n" "Seek to nearest matching journal entry to `realtime`. Argument\n" -"`realtime` can be an integer unix timestamp in usecs or a " -"datetime instance."); +"`realtime` can must be an integer unix timestamp."); static PyObject * Journal_seek_realtime(Journal *self, PyObject *args) { - uint64_t timestamp; - if (! PyArg_ParseTuple(args, "K", ×tamp)) + double timedouble; + if (! PyArg_ParseTuple(args, "d", &timedouble)) return NULL; + uint64_t timestamp; + timestamp = (uint64_t) (timedouble * 1.0E6); + if ((int64_t) timestamp < 0LL) { PyErr_SetString(PyExc_ValueError, "Time must be positive integer"); return NULL; @@ -441,19 +351,15 @@ Journal_seek_realtime(Journal *self, PyObject *args) Py_BEGIN_ALLOW_THREADS r = sd_journal_seek_realtime_usec(self->j, timestamp); Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); + if (set_error(r, NULL, NULL)) return NULL; - } Py_RETURN_NONE; } PyDoc_STRVAR(Journal_seek_monotonic__doc__, "seek_monotonic(monotonic[, bootid]) -> None\n\n" "Seek to nearest matching journal entry to `monotonic`. Argument\n" -"`monotonic` is an timestamp from boot in secs, or a\n" -"timedelta instance.\n" +"`monotonic` is an timestamp from boot in seconds.\n" "Argument `bootid` is a string representing which boot the\n" "monotonic time is reference to. Defaults to current bootid."); static PyObject * @@ -476,37 +382,24 @@ Journal_seek_monotonic(Journal *self, PyObject *args) int r; if (bootid) { r = sd_id128_from_string(bootid, &sd_id); - if (r == -EINVAL) { - PyErr_SetString(PyExc_ValueError, "Invalid bootid"); + if (set_error(r, NULL, "Invalid bootid")) return NULL; - }else if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - }else{ + } else { + Py_BEGIN_ALLOW_THREADS r = sd_id128_get_boot(&sd_id); - if (r == -EIO) { - PyErr_SetString(PyExc_IOError, "Error getting current boot ID"); - return NULL; - }else if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); + Py_END_ALLOW_THREADS + if (set_error(r, NULL, NULL)) return NULL; - } } Py_BEGIN_ALLOW_THREADS r = sd_journal_seek_monotonic_usec(self->j, sd_id, timestamp); Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); + if (set_error(r, NULL, NULL)) return NULL; - } Py_RETURN_NONE; } - + PyDoc_STRVAR(Journal_wait__doc__, "wait([timeout]) -> Change state (integer)\n\n" "Waits until there is a change in the journal. Argument `timeout`\n" @@ -519,30 +412,19 @@ PyDoc_STRVAR(Journal_wait__doc__, static PyObject * Journal_wait(Journal *self, PyObject *args, PyObject *keywds) { - int64_t timeout=0LL; - if (! PyArg_ParseTuple(args, "|L", &timeout)) + int r; + int64_t timeout = 0LL; + + if (!PyArg_ParseTuple(args, "|L", &timeout)) return NULL; - int r; Py_BEGIN_ALLOW_THREADS - if ( timeout == 0LL) { - r = sd_journal_wait(self->j, (uint64_t) -1); - }else{ - r = sd_journal_wait(self->j, timeout * 1E6); - } + r = sd_journal_wait(self->j, timeout ==0 ? (uint64_t) -1 : timeout * 1E6); Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyObject *errtype = r == -ENOMEM ? PyExc_MemoryError : - PyExc_OSError; - PyErr_SetFromErrno(errtype); + if (set_error(r, NULL, NULL)) return NULL; - } -#if PY_MAJOR_VERSION >=3 - return PyLong_FromLong(r); -#else - return PyInt_FromLong(r); -#endif + + return long_FromLong(r); } PyDoc_STRVAR(Journal_seek_cursor__doc__, @@ -559,14 +441,8 @@ Journal_seek_cursor(Journal *self, PyObject *args) Py_BEGIN_ALLOW_THREADS r = sd_journal_seek_cursor(self->j, cursor); Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyObject *errtype = r == -EINVAL ? PyExc_ValueError : - r == -ENOMEM ? PyExc_MemoryError : - PyExc_OSError; - PyErr_SetFromErrno(errtype); + if (set_error(r, NULL, "Invalid cursor")) return NULL; - } Py_RETURN_NONE; } @@ -583,7 +459,9 @@ Journal_iternext(PyObject *self) PyObject *dict; Py_ssize_t dict_size; - dict = PyObject_CallMethod(self, "get_next", ""); + dict = PyObject_CallMethod(self, (char*) "get_next", (char*) ""); + if (PyErr_Occurred()) + return NULL; dict_size = PyDict_Size(dict); if ((int64_t) dict_size > 0LL) { return dict; @@ -594,7 +472,6 @@ Journal_iternext(PyObject *self) } } -#ifdef SD_JOURNAL_FOREACH_UNIQUE PyDoc_STRVAR(Journal_query_unique__doc__, "query_unique(field) -> a set of values\n\n" "Returns a set of unique values in journal for given `field`.\n" @@ -610,26 +487,15 @@ Journal_query_unique(Journal *self, PyObject *args) Py_BEGIN_ALLOW_THREADS r = sd_journal_query_unique(self->j, query); Py_END_ALLOW_THREADS - if (r < 0) { - errno = -r; - PyObject *errtype = r == -EINVAL ? PyExc_ValueError : - r == -ENOMEM ? PyExc_MemoryError : - PyExc_OSError; - PyErr_SetFromErrno(errtype); + if (set_error(r, NULL, "Invalid field name")) return NULL; - } const void *uniq; size_t uniq_len; const char *delim_ptr; PyObject *value_set, *key, *value; value_set = PySet_New(0); - -#if PY_MAJOR_VERSION >=3 - key = PyUnicode_FromString(query); -#else - key = PyString_FromString(query); -#endif + key = unicode_FromString(query); SD_JOURNAL_FOREACH_UNIQUE(self->j, uniq, uniq_len) { delim_ptr = memchr(uniq, '=', uniq_len); @@ -640,28 +506,18 @@ Journal_query_unique(Journal *self, PyObject *args) Py_DECREF(key); return value_set; } -#endif //def SD_JOURNAL_FOREACH_UNIQUE static PyObject * Journal_get_data_threshold(Journal *self, void *closure) { size_t cvalue; - PyObject *value; int r; r = sd_journal_get_data_threshold(self->j, &cvalue); - if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); + if (set_error(r, NULL, NULL)) return NULL; - } -#if PY_MAJOR_VERSION >=3 - value = PyLong_FromSize_t(cvalue); -#else - value = PyInt_FromSize_t(cvalue); -#endif - return value; + return long_FromSize_t(cvalue); } static int @@ -671,34 +527,21 @@ Journal_set_data_threshold(Journal *self, PyObject *value, void *closure) PyErr_SetString(PyExc_TypeError, "Cannot delete data threshold"); return -1; } -#if PY_MAJOR_VERSION >=3 - if (! PyLong_Check(value)){ -#else - if (! PyInt_Check(value)){ -#endif + if (!long_Check(value)){ PyErr_SetString(PyExc_TypeError, "Data threshold must be int"); return -1; } int r; -#if PY_MAJOR_VERSION >=3 - r = sd_journal_set_data_threshold(self->j, (size_t) PyLong_AsLong(value)); -#else - r = sd_journal_set_data_threshold(self->j, (size_t) PyInt_AsLong(value)); -#endif - if (r < 0) { - errno = -r; - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - return 0; + r = sd_journal_set_data_threshold(self->j, (size_t) long_AsLong(value)); + return set_error(r, NULL, NULL); } static PyGetSetDef Journal_getseters[] = { - {"data_threshold", - (getter)Journal_get_data_threshold, - (setter)Journal_set_data_threshold, - "data threshold", - NULL}, + {(char*) "data_threshold", + (getter)Journal_get_data_threshold, + (setter)Journal_set_data_threshold, + (char*) "data threshold", + NULL}, {NULL} }; @@ -723,16 +566,14 @@ static PyMethodDef Journal_methods[] = { Journal_wait__doc__}, {"seek_cursor", (PyCFunction)Journal_seek_cursor, METH_VARARGS, Journal_seek_cursor__doc__}, -#ifdef SD_JOURNAL_FOREACH_UNIQUE {"query_unique", (PyCFunction)Journal_query_unique, METH_VARARGS, Journal_query_unique__doc__}, -#endif {NULL} /* Sentinel */ }; static PyTypeObject JournalType = { PyVarObject_HEAD_INIT(NULL, 0) - "_reader.Journal", /*tp_name*/ + "_reader._Journal", /*tp_name*/ sizeof(Journal), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Journal_dealloc, /*tp_dealloc*/ @@ -781,11 +622,14 @@ static PyModuleDef _reader_module = { }; #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + PyMODINIT_FUNC #if PY_MAJOR_VERSION >= 3 PyInit__reader(void) #else -init_reader(void) +init_reader(void) #endif { PyObject* m; @@ -823,3 +667,5 @@ init_reader(void) return m; #endif } + +#pragma GCC diagnostic pop