Skip to content

Commit 9cbc4e9

Browse files
alexolekeszybz
authored andcommitted
journal: add namespace support
Add log namespace support which is added since systemd v245
1 parent 5dd8afd commit 9cbc4e9

File tree

2 files changed

+41
-19
lines changed

2 files changed

+41
-19
lines changed

systemd/_reader.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
#define HAVE_HAS_RUNTIME_FILES (LIBSYSTEMD_VERSION >= 229)
4949
#define HAVE_HAS_PERSISTENT_FILES (LIBSYSTEMD_VERSION >= 229)
5050

51+
#if LIBSYSTEMD_VERSION >= 245
52+
# define HAVE_JOURNAL_OPEN_NAMESPACE 1
53+
#else
54+
# define HAVE_JOURNAL_OPEN_NAMESPACE 0
55+
#endif
56+
5157
#if LIBSYSTEMD_VERSION >= 230
5258
# define HAVE_JOURNAL_OPEN_DIRECTORY_FD 1
5359
#else
@@ -89,17 +95,17 @@ static PyStructSequence_Desc Monotonic_desc = {
8995
* Convert a str or bytes object into a C-string path.
9096
* Returns NULL on error.
9197
*/
92-
static char* convert_path(PyObject *path, PyObject **bytes) {
98+
static char* str_converter(PyObject *str, PyObject **bytes) {
9399
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
94100
int r;
95101

96-
r = PyUnicode_FSConverter(path, bytes);
102+
r = PyUnicode_FSConverter(str, bytes);
97103
if (r == 0)
98104
return NULL;
99105

100106
return PyBytes_AsString(*bytes);
101107
#else
102-
return PyString_AsString(path);
108+
return PyString_AsString(str);
103109
#endif
104110
}
105111

@@ -146,7 +152,7 @@ static int strv_converter(PyObject* obj, void *_result) {
146152
char *s;
147153

148154
item = PySequence_ITEM(obj, i);
149-
s = convert_path(item, &bytes);
155+
s = str_converter(item, &bytes);
150156
if (!s)
151157
goto cleanup;
152158

@@ -225,7 +231,7 @@ static void Reader_dealloc(Reader* self) {
225231
}
226232

227233
PyDoc_STRVAR(Reader__doc__,
228-
"_Reader([flags | path | files]) -> ...\n\n"
234+
"_Reader([flags | path | files | namespace]) -> ...\n\n"
229235
"_Reader allows filtering and retrieval of Journal entries.\n"
230236
"Note: this is a low-level interface, and probably not what you\n"
231237
"want, use systemd.journal.Reader instead.\n\n"
@@ -236,23 +242,25 @@ PyDoc_STRVAR(Reader__doc__,
236242
"OS_ROOT is used to open the journal from directories relative to the specified\n"
237243
"directory path or file descriptor.\n"
238244
"\n"
239-
"Instead of opening the system journal, argument `path` may specify a directory\n"
240-
"which contains the journal. It maybe be either a file system path (a string), or\n"
241-
"a file descriptor (an integer). Alternatively, argument `files` may specify a list\n"
242-
"of journal file names. Note that `flags`, `path`, `files`, `directory_fd` are\n"
243-
"exclusive.\n\n"
245+
"If `namespace` argument is specified, the specific journal namespace will be open\n"
246+
"(supported since systemd v245). Instead of opening the system journal, argument\n"
247+
"`path` may specify a directory which contains the journal. It maybe be either\n"
248+
"a file system path (a string), or a file descriptor (an integer). Alternatively,\n"
249+
"argument `files` may specify a list of journal file names. Note that `flags`, `path`,\n"
250+
"`files`, `directory_fd`, `namespace` are exclusive.\n\n"
244251
"_Reader implements the context manager protocol: the journal will be closed when\n"
245252
"exiting the block.");
246253
static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
247254
unsigned flags = SD_JOURNAL_LOCAL_ONLY;
248-
PyObject *_path = NULL, *_files = NULL;
255+
PyObject *_path = NULL, *_files = NULL, *_namespace = NULL;
249256
int r;
250257

251-
static const char* const kwlist[] = {"flags", "path", "files", NULL};
252-
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iO&O&:__init__", (char**) kwlist,
258+
static const char* const kwlist[] = {"flags", "path", "files", "namespace", NULL};
259+
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iO&O&O&:__init__", (char**) kwlist,
253260
&flags,
254261
null_converter, &_path,
255-
null_converter, &_files))
262+
null_converter, &_files,
263+
null_converter, &_namespace))
256264
return -1;
257265

258266
if (!!_path + !!_files > 1) {
@@ -279,7 +287,7 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
279287
char *path = NULL;
280288
_cleanup_Py_DECREF_ PyObject *path_bytes = NULL;
281289

282-
path = convert_path(_path, &path_bytes);
290+
path = str_converter(_path, &path_bytes);
283291
if (!path)
284292
return -1;
285293

@@ -319,6 +327,20 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
319327
r = -ENOSYS;
320328
#endif
321329
}
330+
} else if (_namespace) {
331+
#if HAVE_JOURNAL_OPEN_NAMESPACE
332+
char *namespace = NULL;
333+
_cleanup_Py_DECREF_ PyObject *ns_bytes = NULL;
334+
namespace = str_converter(_namespace, &ns_bytes);
335+
if (!namespace)
336+
return -1;
337+
338+
Py_BEGIN_ALLOW_THREADS
339+
r = sd_journal_open_namespace(&self->j, namespace, flags);
340+
Py_END_ALLOW_THREADS
341+
#else
342+
r = -ENOSYS;
343+
#endif
322344
} else {
323345
Py_BEGIN_ALLOW_THREADS
324346
r = sd_journal_open(&self->j, flags);

systemd/journal.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class Reader(_Reader):
140140
journal.
141141
142142
"""
143-
def __init__(self, flags=None, path=None, files=None, converters=None):
143+
def __init__(self, flags=None, path=None, files=None, converters=None, namespace=None):
144144
"""Create a new Reader.
145145
146146
Argument `flags` defines the open flags of the journal, which can be one
@@ -149,8 +149,8 @@ def __init__(self, flags=None, path=None, files=None, converters=None):
149149
and SYSTEM_ONLY opens only journal files of system services and the kernel.
150150
151151
Argument `path` is the directory of journal files, either a file system
152-
path or a file descriptor. Note that `flags`, `path`, and `files` are
153-
exclusive.
152+
path or a file descriptor. Specify `namespace` to read from specific journal
153+
namespace. Note that `flags`, `path`, `files` and `namespace` are exclusive.
154154
155155
Argument `converters` is a dictionary which updates the
156156
DEFAULT_CONVERTERS to convert journal field values. Field names are used
@@ -171,7 +171,7 @@ def __init__(self, flags=None, path=None, files=None, converters=None):
171171
else:
172172
flags = 0
173173

174-
super(Reader, self).__init__(flags, path, files)
174+
super(Reader, self).__init__(flags, path, files, namespace)
175175
if _sys.version_info >= (3, 3):
176176
self.converters = _ChainMap()
177177
if converters is not None:

0 commit comments

Comments
 (0)