From 456aa87906252169ecd3df9a44d0663f8bca5744 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Nov 2019 12:11:24 +0100 Subject: [PATCH] journal: allow opening journal files specific to some namespace --- src/journal/journal-internal.h | 1 + src/journal/sd-journal.c | 106 ++++++++++++++++++++++++++++----- src/libsystemd/libsystemd.sym | 1 + src/systemd/sd-journal.h | 13 ++-- 4 files changed, 102 insertions(+), 19 deletions(-) diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index 80a69da4d8..1454df602b 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -69,6 +69,7 @@ struct sd_journal { char *path; char *prefix; + char *namespace; OrderedHashmap *files; IteratedCache *files_cache; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index d2df5ee3b3..622fe04209 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -39,6 +39,7 @@ #include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "syslog-util.h" #define JOURNAL_FILES_MAX 7168 @@ -1435,22 +1436,63 @@ static void remove_file_real(sd_journal *j, JournalFile *f) { static int dirname_is_machine_id(const char *fn) { sd_id128_t id, machine; + const char *e; int r; + /* Returns true if the specified directory name matches the local machine ID */ + r = sd_id128_get_machine(&machine); if (r < 0) return r; - r = sd_id128_from_string(fn, &id); + e = strchr(fn, '.'); + if (e) { + const char *k; + + /* Looks like it has a namespace suffix. Verify that. */ + if (!log_namespace_name_valid(e + 1)) + return false; + + k = strndupa(fn, e - fn); + r = sd_id128_from_string(k, &id); + } else + r = sd_id128_from_string(fn, &id); if (r < 0) return r; return sd_id128_equal(id, machine); } +static int dirname_has_namespace(const char *fn, const char *namespace) { + const char *e; + + /* Returns true if the specified directory name matches the specified namespace */ + + e = strchr(fn, '.'); + if (e) { + const char *k; + + if (!namespace) + return false; + + if (!streq(e + 1, namespace)) + return false; + + k = strndupa(fn, e - fn); + return id128_is_valid(k); + } + + if (namespace) + return false; + + return id128_is_valid(fn); +} + static bool dirent_is_journal_file(const struct dirent *de) { assert(de); + /* Returns true if the specified directory entry looks like a journal file we might be interested in */ + if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN)) return false; @@ -1458,13 +1500,26 @@ static bool dirent_is_journal_file(const struct dirent *de) { endswith(de->d_name, ".journal~"); } -static bool dirent_is_id128_subdir(const struct dirent *de) { +static bool dirent_is_journal_subdir(const struct dirent *de) { + const char *e, *n; assert(de); + /* returns true if the specified directory entry looks like a directory that might contain journal + * files we might be interested in, i.e. is either a 128bit ID or a 128bit ID suffixed by a + * namespace. */ + if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN)) return false; - return id128_is_valid(de->d_name); + e = strchr(de->d_name, '.'); + if (!e) + return id128_is_valid(de->d_name); /* No namespace */ + + n = strndupa(de->d_name, e - de->d_name); + if (!id128_is_valid(n)) + return false; + + return log_namespace_name_valid(e + 1); } static int directory_open(sd_journal *j, const char *path, DIR **ret) { @@ -1501,7 +1556,7 @@ static void directory_enumerate(sd_journal *j, Directory *m, DIR *d) { if (dirent_is_journal_file(de)) (void) add_file_by_name(j, m->path, de->d_name); - if (m->is_root && dirent_is_id128_subdir(de)) + if (m->is_root && dirent_is_journal_subdir(de)) (void) add_directory(j, m->path, de->d_name); } @@ -1541,7 +1596,11 @@ static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) } } -static int add_directory(sd_journal *j, const char *prefix, const char *dirname) { +static int add_directory( + sd_journal *j, + const char *prefix, + const char *dirname) { + _cleanup_free_ char *path = NULL; _cleanup_closedir_ DIR *d = NULL; Directory *m; @@ -1566,6 +1625,11 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname) !((dirname && dirname_is_machine_id(dirname) > 0) || path_has_prefix(j, path, "/run"))) return 0; + if (!(FLAGS_SET(j->flags, SD_JOURNAL_ALL_NAMESPACES) || + dirname_has_namespace(dirname, j->namespace) > 0 || + (FLAGS_SET(j->flags, SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE) && dirname_has_namespace(dirname, NULL) > 0))) + return 0; + r = directory_open(j, path, &d); if (r < 0) { log_debug_errno(r, "Failed to open directory '%s': %m", path); @@ -1806,7 +1870,7 @@ static int allocate_inotify(sd_journal *j) { return hashmap_ensure_allocated(&j->directories_by_wd, NULL); } -static sd_journal *journal_new(int flags, const char *path) { +static sd_journal *journal_new(int flags, const char *path, const char *namespace) { _cleanup_(sd_journal_closep) sd_journal *j = NULL; j = new0(sd_journal, 1); @@ -1832,6 +1896,12 @@ static sd_journal *journal_new(int flags, const char *path) { j->path = t; } + if (namespace) { + j->namespace = strdup(namespace); + if (!j->namespace) + return NULL; + } + j->files = ordered_hashmap_new(&path_hash_ops); if (!j->files) return NULL; @@ -1848,16 +1918,19 @@ static sd_journal *journal_new(int flags, const char *path) { #define OPEN_ALLOWED_FLAGS \ (SD_JOURNAL_LOCAL_ONLY | \ SD_JOURNAL_RUNTIME_ONLY | \ - SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER) + SD_JOURNAL_SYSTEM | \ + SD_JOURNAL_CURRENT_USER | \ + SD_JOURNAL_ALL_NAMESPACES | \ + SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE) -_public_ int sd_journal_open(sd_journal **ret, int flags) { +_public_ int sd_journal_open_namespace(sd_journal **ret, const char *namespace, int flags) { _cleanup_(sd_journal_closep) sd_journal *j = NULL; int r; assert_return(ret, -EINVAL); assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL); - j = journal_new(flags, NULL); + j = journal_new(flags, NULL, namespace); if (!j) return -ENOMEM; @@ -1869,6 +1942,10 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) { return 0; } +_public_ int sd_journal_open(sd_journal **ret, int flags) { + return sd_journal_open_namespace(ret, NULL, flags); +} + #define OPEN_CONTAINER_ALLOWED_FLAGS \ (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM) @@ -1900,7 +1977,7 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in if (!streq_ptr(class, "container")) return -EIO; - j = journal_new(flags, root); + j = journal_new(flags, root, NULL); if (!j) return -ENOMEM; @@ -1924,7 +2001,7 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f assert_return(path, -EINVAL); assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL); - j = journal_new(flags, path); + j = journal_new(flags, path, NULL); if (!j) return -ENOMEM; @@ -1947,7 +2024,7 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla assert_return(ret, -EINVAL); assert_return(flags == 0, -EINVAL); - j = journal_new(flags, NULL); + j = journal_new(flags, NULL, NULL); if (!j) return -ENOMEM; @@ -1982,7 +2059,7 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { if (!S_ISDIR(st.st_mode)) return -EBADFD; - j = journal_new(flags, NULL); + j = journal_new(flags, NULL, NULL); if (!j) return -ENOMEM; @@ -2010,7 +2087,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd assert_return(n_fds > 0, -EBADF); assert_return(flags == 0, -EINVAL); - j = journal_new(flags, NULL); + j = journal_new(flags, NULL, NULL); if (!j) return -ENOMEM; @@ -2082,6 +2159,7 @@ _public_ void sd_journal_close(sd_journal *j) { free(j->path); free(j->prefix); + free(j->namespace); free(j->unique_field); free(j->fields_buffer); free(j); diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index a3dd9f68b7..17a39e1d0f 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -693,4 +693,5 @@ global: sd_event_source_get_child_process_own; sd_event_source_set_child_process_own; sd_event_source_send_child_signal; + sd_journal_open_namespace; } LIBSYSTEMD_243; diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index dbca4ebce2..29ff40ab26 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -64,11 +64,13 @@ typedef struct sd_journal sd_journal; /* Open flags */ enum { - SD_JOURNAL_LOCAL_ONLY = 1 << 0, - SD_JOURNAL_RUNTIME_ONLY = 1 << 1, - SD_JOURNAL_SYSTEM = 1 << 2, - SD_JOURNAL_CURRENT_USER = 1 << 3, - SD_JOURNAL_OS_ROOT = 1 << 4, + SD_JOURNAL_LOCAL_ONLY = 1 << 0, + SD_JOURNAL_RUNTIME_ONLY = 1 << 1, + SD_JOURNAL_SYSTEM = 1 << 2, + SD_JOURNAL_CURRENT_USER = 1 << 3, + SD_JOURNAL_OS_ROOT = 1 << 4, + SD_JOURNAL_ALL_NAMESPACES = 1 << 5, /* Show all namespaces, not just the default or specified one */ + SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE = 1 << 6, /* Show default namespace in addition to specified one */ SD_JOURNAL_SYSTEM_ONLY _sd_deprecated_ = SD_JOURNAL_SYSTEM /* deprecated name */ }; @@ -81,6 +83,7 @@ enum { }; int sd_journal_open(sd_journal **ret, int flags); +int sd_journal_open_namespace(sd_journal **ret, const char *name_space, int flags); int sd_journal_open_directory(sd_journal **ret, const char *path, int flags); int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags); int sd_journal_open_files(sd_journal **ret, const char **paths, int flags);