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
227233PyDoc_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." );
246253static 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 );
0 commit comments