Skip to content

Commit 02b9432

Browse files
committed
reader: add SD_JOURNAL_OS_ROOT and rework flag passing
Let's pass any flags through to the journal functions without checking validity. Those functions do their own checking, so there's no need to second-guess. The semantics for _Reader(flags=0) are a bit changed: before, this would be transformed into sd_journal_open(SD_J_LOCAL_ONLY). Now, this results in sd_journal_open(0). Previous behaviour should be achieved by not specifying the flags at all. This change is necessary, because previously it was not possible to pass flags=0 to sd_journal_open(0), i.e. it was not possible to "merge" journals through the Python interface. Similarly, Reader(flags=0) now means to open all journals, and Reader(flags=None) is the same as Reader(flags=LOCAL_ONLY).
1 parent 89badf5 commit 02b9432

File tree

4 files changed

+51
-24
lines changed

4 files changed

+51
-24
lines changed

docs/journal.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Journal access types
8989
.. autoattribute:: systemd.journal.RUNTIME_ONLY
9090
.. autoattribute:: systemd.journal.SYSTEM
9191
.. autoattribute:: systemd.journal.CURRENT_USER
92+
.. autoattribute:: systemd.journal.OS_ROOT
9293

9394
Journal event types
9495
~~~~~~~~~~~~~~~~~~~

systemd/_reader.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
#if defined(LIBSYSTEMD_VERSION) || LIBSYSTEMD_JOURNAL_VERSION > 204
3535
# define HAVE_JOURNAL_OPEN_FILES
3636
#else
37-
# define SD_JOURNAL_SYSTEM 4
38-
# define SD_JOURNAL_CURRENT_USER 8
37+
# define SD_JOURNAL_SYSTEM (1 << 2)
38+
# define SD_JOURNAL_CURRENT_USER (1 << 3)
3939
#endif
4040

4141
#if LIBSYSTEMD_VERSION >= 229
@@ -46,6 +46,8 @@
4646

4747
#if LIBSYSTEMD_VERSION >= 230
4848
# define HAVE_JOURNAL_OPEN_DIRECTORY_FD
49+
#else
50+
# define SD_JOURNAL_OS_ROOT (1 << 4)
4951
#endif
5052

5153
typedef struct {
@@ -225,7 +227,9 @@ PyDoc_STRVAR(Reader__doc__,
225227
"Argument `flags` sets open flags of the journal, which can be one of, or an ORed\n"
226228
"combination of constants: LOCAL_ONLY (default) opens journal on local machine only;\n"
227229
"RUNTIME_ONLY opens only volatile journal files; and SYSTEM opens journal files of\n"
228-
"system services and the kernel, and CURRENT_USER opens file of the current user.\n"
230+
"system services and the kernel, CURRENT_USER opens files of the current user; and\n"
231+
"OS_ROOT is used to open the journal from directories relative to the specified\n"
232+
"directory path or file descriptor.\n"
229233
"\n"
230234
"Instead of opening the system journal, argument `path` may specify a directory\n"
231235
"which contains the journal. It maybe be either a file system path (a string), or\n"
@@ -235,8 +239,9 @@ PyDoc_STRVAR(Reader__doc__,
235239
"_Reader implements the context manager protocol: the journal will be closed when\n"
236240
"exiting the block.");
237241
static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
238-
int flags = 0, r;
242+
unsigned flags = SD_JOURNAL_LOCAL_ONLY;
239243
PyObject *_path = NULL, *_files = NULL;
244+
int r;
240245

241246
static const char* const kwlist[] = {"flags", "path", "files", NULL};
242247
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iO&O&:__init__", (char**) kwlist,
@@ -245,9 +250,9 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
245250
null_converter, &_files))
246251
return -1;
247252

248-
if (!!flags + !!_path + !!_files > 1) {
253+
if (!!_path + !!_files > 1) {
249254
PyErr_SetString(PyExc_ValueError,
250-
"cannot use more than one of flags, path, and files");
255+
"path and files cannot be specified simultaneously");
251256
return -1;
252257
}
253258

@@ -260,7 +265,7 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
260265

261266
#ifdef HAVE_JOURNAL_OPEN_DIRECTORY_FD
262267
Py_BEGIN_ALLOW_THREADS
263-
r = sd_journal_open_directory_fd(&self->j, (int) fd, 0);
268+
r = sd_journal_open_directory_fd(&self->j, (int) fd, flags);
264269
Py_END_ALLOW_THREADS
265270
#else
266271
r = -ENOSYS;
@@ -274,7 +279,7 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
274279
return -1;
275280

276281
Py_BEGIN_ALLOW_THREADS
277-
r = sd_journal_open_directory(&self->j, path, 0);
282+
r = sd_journal_open_directory(&self->j, path, flags);
278283
Py_END_ALLOW_THREADS
279284
}
280285
} else if (_files) {
@@ -289,7 +294,7 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
289294
return -1;
290295

291296
Py_BEGIN_ALLOW_THREADS
292-
r = sd_journal_open_files(&self->j, (const char**) files, 0);
297+
r = sd_journal_open_files(&self->j, (const char**) files, flags);
293298
Py_END_ALLOW_THREADS
294299
} else {
295300
_cleanup_free_ int *fds = NULL;
@@ -299,16 +304,13 @@ static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
299304
return -1;
300305

301306
Py_BEGIN_ALLOW_THREADS
302-
r = sd_journal_open_files_fd(&self->j, fds, n_fds, 0);
307+
r = sd_journal_open_files_fd(&self->j, fds, n_fds, flags);
303308
Py_END_ALLOW_THREADS
304309
}
305310
#else
306311
r = -ENOSYS;
307312
#endif
308313
} else {
309-
if (!flags)
310-
flags = SD_JOURNAL_LOCAL_ONLY;
311-
312314
Py_BEGIN_ALLOW_THREADS
313315
r = sd_journal_open(&self->j, flags);
314316
Py_END_ALLOW_THREADS
@@ -1332,6 +1334,7 @@ init_reader(void)
13321334
PyModule_AddIntConstant(m, "SYSTEM", SD_JOURNAL_SYSTEM) ||
13331335
PyModule_AddIntConstant(m, "SYSTEM_ONLY", SD_JOURNAL_SYSTEM_ONLY) ||
13341336
PyModule_AddIntConstant(m, "CURRENT_USER", SD_JOURNAL_CURRENT_USER) ||
1337+
PyModule_AddIntConstant(m, "OS_ROOT", SD_JOURNAL_OS_ROOT) ||
13351338
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
13361339
#if PY_MAJOR_VERSION >= 3
13371340
Py_DECREF(m);

systemd/journal.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from ._reader import (_Reader, NOP, APPEND, INVALIDATE,
3535
LOCAL_ONLY, RUNTIME_ONLY,
3636
SYSTEM, SYSTEM_ONLY, CURRENT_USER,
37+
OS_ROOT,
3738
_get_catalog)
3839
from . import id128 as _id128
3940

@@ -131,7 +132,7 @@ class Reader(_Reader):
131132
journal.
132133
133134
"""
134-
def __init__(self, flags=0, path=None, files=None, converters=None):
135+
def __init__(self, flags=None, path=None, files=None, converters=None):
135136
"""Create a new Reader.
136137
137138
Argument `flags` defines the open flags of the journal, which can be one
@@ -155,6 +156,13 @@ def __init__(self, flags=0, path=None, files=None, converters=None):
155156
Reader implements the context manager protocol: the journal will be
156157
closed when exiting the block.
157158
"""
159+
if flags is None:
160+
if path is None and files is None:
161+
# This mimics journalctl behaviour of default to local journal only
162+
flags = LOCAL_ONLY
163+
else:
164+
flags = 0
165+
158166
super(Reader, self).__init__(flags, path, files)
159167
if _sys.version_info >= (3,3):
160168
self.converters = _ChainMap()

systemd/test/test_journal.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,25 @@ def test_reader_init_flags():
4343
j2 = journal.Reader(journal.LOCAL_ONLY)
4444
j3 = journal.Reader(journal.RUNTIME_ONLY)
4545
j4 = journal.Reader(journal.SYSTEM_ONLY)
46-
j5 = journal.Reader(journal.LOCAL_ONLY|
47-
journal.RUNTIME_ONLY|
48-
journal.SYSTEM_ONLY)
46+
j5 = journal.Reader(journal.LOCAL_ONLY | journal.RUNTIME_ONLY | journal.SYSTEM_ONLY)
4947
j6 = journal.Reader(0)
5048

51-
def test_reader_init_path(tmpdir):
52-
j = journal.Reader(path=tmpdir.strpath)
49+
def test_reader_os_root(tmpdir):
5350
with pytest.raises(ValueError):
54-
journal.Reader(journal.LOCAL_ONLY, path=tmpdir.strpath)
51+
journal.Reader(journal.OS_ROOT)
52+
j1 = journal.Reader(path=tmpdir.strpath,
53+
flags=journal.OS_ROOT)
54+
j2 = journal.Reader(path=tmpdir.strpath,
55+
flags=journal.OS_ROOT | journal.CURRENT_USER)
56+
j3 = journal.Reader(path=tmpdir.strpath,
57+
flags=journal.OS_ROOT | journal.SYSTEM_ONLY)
58+
59+
def test_reader_init_path(tmpdir):
60+
j1 = journal.Reader(path=tmpdir.strpath)
61+
journal.Reader(0, path=tmpdir.strpath)
62+
63+
j2 = journal.Reader(path=tmpdir.strpath)
64+
journal.Reader(path=tmpdir.strpath)
5565

5666
def test_reader_init_path_invalid_fd():
5767
with pytest.raises(OSError):
@@ -63,10 +73,15 @@ def test_reader_init_path_nondirectory_fd():
6373

6474
def test_reader_init_path_fd(tmpdir):
6575
fd = os.open(tmpdir.strpath, os.O_RDONLY)
66-
j = journal.Reader(path=fd)
67-
with pytest.raises(ValueError):
68-
journal.Reader(journal.LOCAL_ONLY, path=fd)
69-
assert list(j) == []
76+
77+
j1 = journal.Reader(path=fd)
78+
assert list(j1) == []
79+
80+
j2 = journal.Reader(journal.SYSTEM, path=fd)
81+
assert list(j2) == []
82+
83+
j3 = journal.Reader(journal.CURRENT_USER, path=fd)
84+
assert list(j3) == []
7085

7186
def test_reader_as_cm(tmpdir):
7287
j = journal.Reader(path=tmpdir.strpath)

0 commit comments

Comments
 (0)