diff --git a/Makefile-man.am b/Makefile-man.am index a31427e9b9..807ad783fb 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -148,6 +148,7 @@ MANPAGES_ALIAS += \ man/sd_journal_get_timeout.3 \ man/sd_journal_next_skip.3 \ man/sd_journal_open_directory.3 \ + man/sd_journal_open_files.3 \ man/sd_journal_perror.3 \ man/sd_journal_previous.3 \ man/sd_journal_previous_skip.3 \ @@ -248,6 +249,7 @@ man/sd_journal_get_monotonic_usec.3: man/sd_journal_get_realtime_usec.3 man/sd_journal_get_timeout.3: man/sd_journal_get_fd.3 man/sd_journal_next_skip.3: man/sd_journal_next.3 man/sd_journal_open_directory.3: man/sd_journal_open.3 +man/sd_journal_open_files.3: man/sd_journal_open.3 man/sd_journal_perror.3: man/sd_journal_print.3 man/sd_journal_previous.3: man/sd_journal_next.3 man/sd_journal_previous_skip.3: man/sd_journal_next.3 @@ -452,6 +454,9 @@ man/sd_journal_next_skip.html: man/sd_journal_next.html man/sd_journal_open_directory.html: man/sd_journal_open.html $(html-alias) +man/sd_journal_open_files.html: man/sd_journal_open.html + $(html-alias) + man/sd_journal_perror.html: man/sd_journal_print.html $(html-alias) diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml index dd2f32d81a..4ac94c4ce3 100644 --- a/man/sd_journal_open.xml +++ b/man/sd_journal_open.xml @@ -45,6 +45,7 @@ sd_journal_open sd_journal_open_directory + sd_journal_open_files sd_journal_close sd_journal SD_JOURNAL_LOCAL_ONLY @@ -71,6 +72,13 @@ int flags + + int sd_journal_open_files + sd_journal** ret + const char** paths + int flags + + void sd_journal_close sd_journal* j @@ -111,6 +119,14 @@ flags argument, but it must be passed as 0 as no flags are currently understood for this call. + sd_journal_open_files() + is similar to sd_journal_open() + but takes a NULL-terminated list + of file paths to open. All files will be opened and + interleaved automatically. This call also takes a + flags argument, but it must be passed as 0 as no flags + are currently understood for this call. + sd_journal_close() will close the journal context allocated with sd_journal_open() or @@ -188,9 +204,10 @@ sd_journal_open_directory() was added in systemd-187. - SD_JOURNAL_SYSTEM and - SD_JOURNAL_CURRENT_USER were added - in systemd-205. + SD_JOURNAL_SYSTEM, + SD_JOURNAL_CURRENT_USER, + and sd_journal_open_files() + were added in systemd-205. SD_JOURNAL_SYSTEM_ONLY was deprecated. diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index f576a0073d..5b717f86f7 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -123,6 +123,7 @@ struct sd_journal { uint64_t unique_offset; bool on_network; + bool no_new_files; size_t data_threshold; diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index 449f37c4da..4eb15910d2 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -104,3 +104,8 @@ LIBSYSTEMD_JOURNAL_202 { global: sd_journal_add_conjunction; } LIBSYSTEMD_JOURNAL_201; + +LIBSYSTEMD_JOURNAL_205 { +global: + sd_journal_open_files; +} LIBSYSTEMD_JOURNAL_202; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 8986763e4d..3aa9ed4b32 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -33,6 +33,7 @@ #include "journal-file.h" #include "hashmap.h" #include "list.h" +#include "strv.h" #include "path-util.h" #include "lookup3.h" #include "compress.h" @@ -1278,37 +1279,24 @@ static bool file_type_wanted(int flags, const char *filename) { return false; } -static int add_file(sd_journal *j, const char *prefix, const char *filename) { - _cleanup_free_ char *path = NULL; - int r; +static int add_any_file(sd_journal *j, const char *path) { JournalFile *f; + int r; assert(j); - assert(prefix); - assert(filename); - - if (!file_type_wanted(j->flags, filename)) - return 0; - - path = strjoin(prefix, "/", filename, NULL); - if (!path) - return -ENOMEM; + assert(path); if (hashmap_get(j->files, path)) return 0; if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) { - log_debug("Too many open journal files, not adding %s, ignoring.", path); + log_warning("Too many open journal files, not adding %s.", path); return set_put_error(j, -ETOOMANYREFS); } r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f); - if (r < 0) { - if (errno == ENOENT) - return 0; - + if (r < 0) return r; - } /* journal_file_dump(f); */ @@ -1327,6 +1315,28 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) { return 0; } +static int add_file(sd_journal *j, const char *prefix, const char *filename) { + _cleanup_free_ char *path = NULL; + int r; + + assert(j); + assert(prefix); + assert(filename); + + if (j->no_new_files || + !file_type_wanted(j->flags, filename)) + return 0; + + path = strjoin(prefix, "/", filename, NULL); + if (!path) + return -ENOMEM; + + r = add_any_file(j, path); + if (r == -ENOENT) + return 0; + return 0; +} + static int remove_file(sd_journal *j, const char *prefix, const char *filename) { char *path; JournalFile *f; @@ -1507,6 +1517,9 @@ static int add_root_directory(sd_journal *j, const char *p) { inotify_rm_watch(j->inotify_fd, m->wd); } + if (j->no_new_files) + return 0; + for (;;) { struct dirent *de; union dirent_storage buf; @@ -1587,6 +1600,36 @@ static int add_search_paths(sd_journal *j) { return 0; } +static int add_current_paths(sd_journal *j) { + Iterator i; + JournalFile *f; + + assert(j); + assert(j->no_new_files); + + /* Simply adds all directories for files we have open as + * "root" directories. We don't expect errors here, so we + * treat them as fatal. */ + + HASHMAP_FOREACH(f, j->files, i) { + int r; + _cleanup_free_ char *dir; + + dir = dirname_malloc(f->path); + if (!dir) + return -ENOMEM; + + r = add_root_directory(j, dir); + if (r < 0) { + set_put_error(j, r); + return r; + } + } + + return 0; +} + + static int allocate_inotify(sd_journal *j) { assert(j); @@ -1697,6 +1740,40 @@ fail: return r; } +_public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) { + sd_journal *j; + const char **path; + int r; + + if (!ret) + return -EINVAL; + + if (flags != 0) + return -EINVAL; + + j = journal_new(flags, NULL); + if (!j) + return -ENOMEM; + + STRV_FOREACH(path, paths) { + r = add_any_file(j, *path); + if (r < 0) { + log_error("Failed to open %s: %s", *path, strerror(-r)); + goto fail; + } + } + + j->no_new_files = true; + + *ret = j; + return 0; + +fail: + sd_journal_close(j); + + return r; +} + _public_ void sd_journal_close(sd_journal *j) { Directory *d; JournalFile *f; @@ -2017,7 +2094,9 @@ _public_ int sd_journal_get_fd(sd_journal *j) { /* Iterate through all dirs again, to add them to the * inotify */ - if (j->path) + if (j->no_new_files) + r = add_current_paths(j); + else if (j->path) r = add_root_directory(j, j->path); else r = add_search_paths(j); diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index cf105cde72..72ea328b28 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -100,6 +100,7 @@ enum { int sd_journal_open(sd_journal **ret, int flags); int sd_journal_open_directory(sd_journal **ret, const char *path, int flags); +int sd_journal_open_files(sd_journal **ret, const char **paths, int flags); void sd_journal_close(sd_journal *j); int sd_journal_previous(sd_journal *j);