]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/journal/journalctl.c
hostname-util: get rid of unused parameter of hostname_cleanup()
[thirdparty/systemd.git] / src / journal / journalctl.c
index 56435ff7b4467455879ab41f7c08356fdc58d8b3..d2c0a03ccb52dabc11b965ac0dea45074d031cfe 100644 (file)
@@ -37,7 +37,6 @@
 
 #include "sd-journal.h"
 #include "sd-bus.h"
-
 #include "log.h"
 #include "logs-show.h"
 #include "util.h"
@@ -60,6 +59,8 @@
 #include "mkdir.h"
 #include "bus-util.h"
 #include "bus-error.h"
+#include "terminal-util.h"
+#include "hostname-util.h"
 
 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
 
@@ -124,11 +125,12 @@ static enum {
         ACTION_VACUUM,
 } arg_action = ACTION_SHOW;
 
-typedef struct boot_id_t {
+typedef struct BootId {
         sd_id128_t id;
         uint64_t first;
         uint64_t last;
-} boot_id_t;
+        LIST_FIELDS(struct BootId, boot_list);
+} BootId;
 
 static void pager_open_if_enabled(void) {
 
@@ -449,7 +451,7 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_boot = true;
 
                         if (optarg) {
-                                r =  parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
+                                r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
                                 if (r < 0) {
                                         log_error("Failed to parse boot descriptor '%s'", optarg);
                                         return -EINVAL;
@@ -576,7 +578,7 @@ static int parse_argv(int argc, char *argv[]) {
                 case ARG_INTERVAL:
                 case ARG_FORCE:
                         log_error("Forward-secure sealing not available.");
-                        return -ENOTSUP;
+                        return -EOPNOTSUPP;
 #endif
 
                 case 'p': {
@@ -732,6 +734,11 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
+        if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && (arg_file || arg_directory || arg_merge)) {
+                log_error("Using --boot or --list-boots with --file, --directory or --merge is not supported.");
+                return -EINVAL;
+        }
+
         return 1;
 }
 
@@ -788,7 +795,7 @@ static int add_matches(sd_journal *j, char **args) {
                         p = canonicalize_file_name(*i);
                         path = p ? p : *i;
 
-                        if (stat(path, &st) < 0)
+                        if (lstat(path, &st) < 0)
                                 return log_error_errno(errno, "Couldn't stat file: %m");
 
                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
@@ -811,17 +818,11 @@ static int add_matches(sd_journal *j, char **args) {
                                         }
                                 } else
                                         t = strappend("_EXE=", path);
-                        } else if (S_ISCHR(st.st_mode)) {
-                                if (asprintf(&t, "_KERNEL_DEVICE=c%u:%u",
-                                             major(st.st_rdev),
-                                             minor(st.st_rdev)) < 0)
-                                        return -ENOMEM;
-                        } else if (S_ISBLK(st.st_mode)) {
-                                if (asprintf(&t, "_KERNEL_DEVICE=b%u:%u",
-                                             major(st.st_rdev),
-                                             minor(st.st_rdev)) < 0)
-                                        return -ENOMEM;
-                        } else {
+                        } else if (S_ISCHR(st.st_mode))
+                                (void) asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
+                        else if (S_ISBLK(st.st_mode))
+                                (void) asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
+                        else {
                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
                                 return -EINVAL;
                         }
@@ -851,111 +852,217 @@ static int add_matches(sd_journal *j, char **args) {
         return 0;
 }
 
-static int boot_id_cmp(const void *a, const void *b) {
-        uint64_t _a, _b;
-
-        _a = ((const boot_id_t *)a)->first;
-        _b = ((const boot_id_t *)b)->first;
+static void boot_id_free_all(BootId *l) {
 
-        return _a < _b ? -1 : (_a > _b ? 1 : 0);
+        while (l) {
+                BootId *i = l;
+                LIST_REMOVE(boot_list, l, i);
+                free(i);
+        }
 }
 
-static int get_boots(sd_journal *j,
-                     boot_id_t **boots,
-                     unsigned int *count,
-                     boot_id_t *query_ref_boot) {
+static int discover_next_boot(
+                sd_journal *j,
+                BootId **boot,
+                bool advance_older,
+                bool read_realtime) {
+
         int r;
-        const void *data;
-        size_t length, allocated = 0;
+        char match[9+32+1] = "_BOOT_ID=";
+        _cleanup_free_ BootId *next_boot = NULL;
 
         assert(j);
-        assert(boots);
-        assert(count);
+        assert(boot);
+
+        /* We expect the journal to be on the last position of a boot
+         * (in relation to the direction we are going), so that the next
+         * invocation of sd_journal_next/previous will be from a different
+         * boot. We then collect any information we desire and then jump
+         * to the last location of the new boot by using a _BOOT_ID match
+         * coming from the other journal direction. */
+
+        /* Make sure we aren't restricted by any _BOOT_ID matches, so that
+         * we can actually advance to a *different* boot. */
+        sd_journal_flush_matches(j);
 
-        r = sd_journal_query_unique(j, "_BOOT_ID");
+        if (advance_older)
+                r = sd_journal_previous(j);
+        else
+                r = sd_journal_next(j);
         if (r < 0)
                 return r;
+        else if (r == 0)
+                return 0; /* End of journal, yay. */
 
-        *count = 0;
-        SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
-                boot_id_t *id;
+        next_boot = new0(BootId, 1);
+        if (!next_boot)
+                return -ENOMEM;
 
-                assert(startswith(data, "_BOOT_ID="));
+        r = sd_journal_get_monotonic_usec(j, NULL, &next_boot->id);
+        if (r < 0)
+                return r;
 
-                if (!GREEDY_REALLOC(*boots, allocated, *count + 1))
-                        return log_oom();
+        if (read_realtime) {
+                r = sd_journal_get_realtime_usec(j, &next_boot->first);
+                if (r < 0)
+                        return r;
+        }
+
+        /* Now seek to the last occurrence of this boot ID. */
+        sd_id128_to_string(next_boot->id, match + 9);
+        r = sd_journal_add_match(j, match, sizeof(match) - 1);
+        if (r < 0)
+                return r;
+
+        if (advance_older)
+                r = sd_journal_seek_head(j);
+        else
+                r = sd_journal_seek_tail(j);
+        if (r < 0)
+                return r;
 
-                id = *boots + *count;
+        if (advance_older)
+                r = sd_journal_next(j);
+        else
+                r = sd_journal_previous(j);
+        if (r < 0)
+                return r;
+        else if (r == 0)
+                return -ENODATA; /* This shouldn't happen. We just came from this very boot ID. */
 
-                r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
+        if (read_realtime) {
+                r = sd_journal_get_realtime_usec(j, &next_boot->last);
                 if (r < 0)
-                        continue;
+                        return r;
+        }
 
-                r = sd_journal_add_match(j, data, length);
+        *boot = next_boot;
+        next_boot = NULL;
+
+        return 0;
+}
+
+static int get_boots(
+                sd_journal *j,
+                BootId **boots,
+                BootId *query_ref_boot,
+                int ref_boot_offset) {
+
+        bool skip_once;
+        int r, count = 0;
+        BootId *head = NULL, *tail = NULL;
+        const bool advance_older = query_ref_boot && ref_boot_offset <= 0;
+
+        assert(j);
+
+        /* Adjust for the asymmetry that offset 0 is
+         * the last (and current) boot, while 1 is considered the
+         * (chronological) first boot in the journal. */
+        skip_once = query_ref_boot && sd_id128_is_null(query_ref_boot->id) && ref_boot_offset < 0;
+
+        /* Advance to the earliest/latest occurrence of our reference
+         * boot ID (taking our lookup direction into account), so that
+         * discover_next_boot() can do its job.
+         * If no reference is given, the journal head/tail will do,
+         * they're "virtual" boots after all. */
+        if (query_ref_boot && !sd_id128_is_null(query_ref_boot->id)) {
+                char match[9+32+1] = "_BOOT_ID=";
+
+                sd_journal_flush_matches(j);
+
+                sd_id128_to_string(query_ref_boot->id, match + 9);
+                r = sd_journal_add_match(j, match, sizeof(match) - 1);
                 if (r < 0)
                         return r;
 
-                r = sd_journal_seek_head(j);
+                if (advance_older)
+                        r = sd_journal_seek_head(j);
+                else
+                        r = sd_journal_seek_tail(j);
                 if (r < 0)
                         return r;
 
-                r = sd_journal_next(j);
+                if (advance_older)
+                        r = sd_journal_next(j);
+                else
+                        r = sd_journal_previous(j);
                 if (r < 0)
                         return r;
                 else if (r == 0)
-                        goto flush;
-
-                r = sd_journal_get_realtime_usec(j, &id->first);
+                        goto finish;
+                else if (ref_boot_offset == 0) {
+                        count = 1;
+                        goto finish;
+                }
+        } else {
+                if (advance_older)
+                        r = sd_journal_seek_tail(j);
+                else
+                        r = sd_journal_seek_head(j);
                 if (r < 0)
                         return r;
 
-                if (query_ref_boot) {
-                        id->last = 0;
-                        if (sd_id128_equal(id->id, query_ref_boot->id))
-                                *query_ref_boot = *id;
-                } else {
-                        r = sd_journal_seek_tail(j);
-                        if (r < 0)
-                                return r;
+                /* No sd_journal_next/previous here. */
+        }
 
-                        r = sd_journal_previous(j);
-                        if (r < 0)
-                                return r;
-                        else if (r == 0)
-                                goto flush;
+        for (;;) {
+                _cleanup_free_ BootId *current = NULL;
 
-                        r = sd_journal_get_realtime_usec(j, &id->last);
-                        if (r < 0)
-                                return r;
+                r = discover_next_boot(j, &current, advance_older, !query_ref_boot);
+                if (r < 0) {
+                        boot_id_free_all(head);
+                        return r;
                 }
 
-                (*count)++;
-        flush:
-                sd_journal_flush_matches(j);
+                if (!current)
+                        break;
+
+                if (query_ref_boot) {
+                        if (!skip_once)
+                                ref_boot_offset += advance_older ? 1 : -1;
+                        skip_once = false;
+
+                        if (ref_boot_offset == 0) {
+                                count = 1;
+                                query_ref_boot->id = current->id;
+                                break;
+                        }
+                } else {
+                        LIST_INSERT_AFTER(boot_list, head, tail, current);
+                        tail = current;
+                        current = NULL;
+                        count++;
+                }
         }
 
-        qsort_safe(*boots, *count, sizeof(boot_id_t), boot_id_cmp);
-        return 0;
+finish:
+        if (boots)
+                *boots = head;
+
+        sd_journal_flush_matches(j);
+
+        return count;
 }
 
 static int list_boots(sd_journal *j) {
-        int r, w, i;
-        unsigned int count;
-        boot_id_t *id;
-        _cleanup_free_ boot_id_t *all_ids = NULL;
+        int w, i, count;
+        BootId *id, *all_ids;
 
         assert(j);
 
-        r = get_boots(j, &all_ids, &count, NULL);
-        if (r < 0)
-                return r;
+        count = get_boots(j, &all_ids, NULL, 0);
+        if (count < 0)
+                return log_error_errno(count, "Failed to determine boots: %m");
+        if (count == 0)
+                return count;
 
         pager_open_if_enabled();
 
         /* numbers are one less, but we need an extra char for the sign */
         w = DECIMAL_STR_WIDTH(count - 1) + 1;
 
-        for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
+        i = 0;
+        LIST_FOREACH(boot_list, id, all_ids) {
                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
 
                 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
@@ -963,40 +1070,10 @@ static int list_boots(sd_journal *j) {
                        SD_ID128_FORMAT_VAL(id->id),
                        format_timestamp_maybe_utc(a, sizeof(a), id->first),
                        format_timestamp_maybe_utc(b, sizeof(b), id->last));
+                i++;
         }
 
-        return 0;
-}
-
-static int get_boot_id_by_offset(sd_journal *j, sd_id128_t *boot_id, int offset) {
-        int r;
-        unsigned int count;
-        boot_id_t ref_boot_id = {}, *id;
-        _cleanup_free_ boot_id_t *all_ids = NULL;
-
-        assert(j);
-        assert(boot_id);
-
-        ref_boot_id.id = *boot_id;
-        r = get_boots(j, &all_ids, &count, &ref_boot_id);
-        if (r < 0)
-                return r;
-
-        if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
-                if (offset > (int) count || offset <= -(int)count)
-                        return -EADDRNOTAVAIL;
-
-                *boot_id = all_ids[(offset <= 0)*count + offset - 1].id;
-        } else {
-                id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
-
-                if (!id ||
-                    offset <= 0 ? (id - all_ids) + offset < 0 :
-                                    (id - all_ids) + offset >= (int) count)
-                        return -EADDRNOTAVAIL;
-
-                *boot_id = (id + offset)->id;
-        }
+        boot_id_free_all(all_ids);
 
         return 0;
 }
@@ -1004,6 +1081,7 @@ static int get_boot_id_by_offset(sd_journal *j, sd_id128_t *boot_id, int offset)
 static int add_boot(sd_journal *j) {
         char match[9+32+1] = "_BOOT_ID=";
         int r;
+        BootId ref_boot_id = {};
 
         assert(j);
 
@@ -1013,17 +1091,22 @@ static int add_boot(sd_journal *j) {
         if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
                 return add_match_this_boot(j, arg_machine);
 
-        r = get_boot_id_by_offset(j, &arg_boot_id, arg_boot_offset);
-        if (r < 0) {
-                if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
-                        log_error_errno(r, "Failed to look up boot %+i: %m", arg_boot_offset);
+        ref_boot_id.id = arg_boot_id;
+        r = get_boots(j, NULL, &ref_boot_id, arg_boot_offset);
+        assert(r <= 1);
+        if (r <= 0) {
+                const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
+
+                if (sd_id128_is_null(arg_boot_id))
+                        log_error("Failed to look up boot %+i: %s", arg_boot_offset, reason);
                 else
                         log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
-                                  SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, strerror(-r));
-                return r;
+                                  SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, reason);
+
+                return r == 0 ? -ENODATA : r;
         }
 
-        sd_id128_to_string(arg_boot_id, match + 9);
+        sd_id128_to_string(ref_boot_id.id, match + 9);
 
         r = sd_journal_add_match(j, match, sizeof(match) - 1);
         if (r < 0)
@@ -1031,7 +1114,7 @@ static int add_boot(sd_journal *j) {
 
         r = sd_journal_add_conjunction(j);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to add conjunction: %m");
 
         return 0;
 }
@@ -1049,22 +1132,24 @@ static int add_dmesg(sd_journal *j) {
 
         r = sd_journal_add_conjunction(j);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to add conjunction: %m");
 
         return 0;
 }
 
-static int get_possible_units(sd_journal *j,
-                              const char *fields,
-                              char **patterns,
-                              Set **units) {
+static int get_possible_units(
+                sd_journal *j,
+                const char *fields,
+                char **patterns,
+                Set **units) {
+
         _cleanup_set_free_free_ Set *found;
         const char *field;
         int r;
 
         found = set_new(&string_hash_ops);
         if (!found)
-                return log_oom();
+                return -ENOMEM;
 
         NULSTR_FOREACH(field, fields) {
                 const void *data;
@@ -1087,7 +1172,7 @@ static int get_possible_units(sd_journal *j,
 
                         u = strndup((char*) data + prefix, size - prefix);
                         if (!u)
-                                return log_oom();
+                                return -ENOMEM;
 
                         STRV_FOREACH(pattern, patterns)
                                 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
@@ -1134,9 +1219,9 @@ static int add_units(sd_journal *j) {
         STRV_FOREACH(i, arg_system_units) {
                 _cleanup_free_ char *u = NULL;
 
-                u = unit_name_mangle(*i, MANGLE_GLOB);
-                if (!u)
-                        return log_oom();
+                r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
+                if (r < 0)
+                        return r;
 
                 if (string_is_glob(u)) {
                         r = strv_push(&patterns, u);
@@ -1180,9 +1265,9 @@ static int add_units(sd_journal *j) {
         STRV_FOREACH(i, arg_user_units) {
                 _cleanup_free_ char *u = NULL;
 
-                u = unit_name_mangle(*i, MANGLE_GLOB);
-                if (!u)
-                        return log_oom();
+                r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
+                if (r < 0)
+                        return r;
 
                 if (string_is_glob(u)) {
                         r = strv_push(&patterns, u);
@@ -1251,7 +1336,7 @@ static int add_priorities(sd_journal *j) {
 
         r = sd_journal_add_conjunction(j);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to add conjunction: %m");
 
         return 0;
 }
@@ -1286,7 +1371,6 @@ static int setup_keys(void) {
 #ifdef HAVE_GCRYPT
         size_t mpk_size, seed_size, state_size, i;
         uint8_t *mpk, *seed, *state;
-        ssize_t l;
         int fd = -1, r;
         sd_id128_t machine, boot;
         char *p = NULL, *k = NULL;
@@ -1316,19 +1400,16 @@ static int setup_keys(void) {
                      SD_ID128_FORMAT_VAL(machine)) < 0)
                 return log_oom();
 
-        if (access(p, F_OK) >= 0) {
-                if (arg_force) {
-                        r = unlink(p);
-                        if (r < 0) {
-                                log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
-                                r = -errno;
-                                goto finish;
-                        }
-                } else {
-                        log_error("Sealing key file %s exists already. (--force to recreate)", p);
-                        r = -EEXIST;
+        if (arg_force) {
+                r = unlink(p);
+                if (r < 0 && errno != ENOENT) {
+                        r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
                         goto finish;
                 }
+        } else if (access(p, F_OK) >= 0) {
+                log_error("Sealing key file %s exists already. Use --force to recreate.", p);
+                r = -EEXIST;
+                goto finish;
         }
 
         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
@@ -1354,10 +1435,9 @@ static int setup_keys(void) {
         }
 
         log_info("Generating seed...");
-        l = loop_read(fd, seed, seed_size, true);
-        if (l < 0 || (size_t) l != seed_size) {
-                log_error_errno(EIO, "Failed to read random seed: %m");
-                r = -EIO;
+        r = loop_read_exact(fd, seed, seed_size, true);
+        if (r < 0) {
+                log_error_errno(r, "Failed to read random seed: %m");
                 goto finish;
         }
 
@@ -1382,7 +1462,7 @@ static int setup_keys(void) {
 
         /* Enable secure remove, exclusion from dump, synchronous
          * writing and in-place updating */
-        r = chattr_fd(fd, true, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL);
+        r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL);
         if (r < 0)
                 log_warning_errno(errno, "Failed to set file attributes: %m");
 
@@ -1447,7 +1527,7 @@ static int setup_keys(void) {
                 hn = gethostname_malloc();
 
                 if (hn) {
-                        hostname_cleanup(hn, false);
+                        hostname_cleanup(hn);
                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
                 } else
                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
@@ -1477,7 +1557,7 @@ finish:
         return r;
 #else
         log_error("Forward-secure sealing not available.");
-        return -ENOTSUP;
+        return -EOPNOTSUPP;
 #endif
 }
 
@@ -1492,7 +1572,7 @@ static int verify(sd_journal *j) {
 
         ORDERED_HASHMAP_FOREACH(f, j->files, i) {
                 int k;
-                usec_t first, validated, last;
+                usec_t first = 0, validated = 0, last = 0;
 
 #ifdef HAVE_GCRYPT
                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
@@ -1528,54 +1608,76 @@ static int verify(sd_journal *j) {
         return r;
 }
 
-#ifdef HAVE_ACL
 static int access_check_var_log_journal(sd_journal *j) {
+#ifdef HAVE_ACL
         _cleanup_strv_free_ char **g = NULL;
-        bool have_access;
+        const char* dir;
+#endif
         int r;
 
         assert(j);
 
-        have_access = in_group("systemd-journal") > 0;
+        if (arg_quiet)
+                return 0;
 
-        if (!have_access) {
-                /* Let's enumerate all groups from the default ACL of
-                 * the directory, which generally should allow access
-                 * to most journal files too */
-                r = search_acl_groups(&g, "/var/log/journal/", &have_access);
-                if (r < 0)
-                        return r;
-        }
+        /* If we are root, we should have access, don't warn. */
+        if (getuid() == 0)
+                return 0;
 
-        if (!have_access) {
+        /* If we are in the 'systemd-journal' group, we should have
+         * access too. */
+        r = in_group("systemd-journal");
+        if (r < 0)
+                return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m");
+        if (r > 0)
+                return 0;
 
-                if (strv_isempty(g))
-                        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
-                                   "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
-                                   "      turn off this notice.");
-                else {
-                        _cleanup_free_ char *s = NULL;
+#ifdef HAVE_ACL
+        if (laccess("/run/log/journal", F_OK) >= 0)
+                dir = "/run/log/journal";
+        else
+                dir = "/var/log/journal";
 
-                        r = strv_extend(&g, "systemd-journal");
-                        if (r < 0)
-                                return log_oom();
+        /* If we are in any of the groups listed in the journal ACLs,
+         * then all is good, too. Let's enumerate all groups from the
+         * default ACL of the directory, which generally should allow
+         * access to most journal files too. */
+        r = acl_search_groups(dir, &g);
+        if (r < 0)
+                return log_error_errno(r, "Failed to search journal ACL: %m");
+        if (r > 0)
+                return 0;
 
-                        strv_sort(g);
-                        strv_uniq(g);
+        /* Print a pretty list, if there were ACLs set. */
+        if (!strv_isempty(g)) {
+                _cleanup_free_ char *s = NULL;
 
-                        s = strv_join(g, "', '");
-                        if (!s)
-                                return log_oom();
+                /* Thre are groups in the ACL, let's list them */
+                r = strv_extend(&g, "systemd-journal");
+                if (r < 0)
+                        return log_oom();
 
-                        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
-                                   "      Users in the groups '%s' can see all messages.\n"
-                                   "      Pass -q to turn off this notice.", s);
-                }
+                strv_sort(g);
+                strv_uniq(g);
+
+                s = strv_join(g, "', '");
+                if (!s)
+                        return log_oom();
+
+                log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
+                           "      Users in groups '%s' can see all messages.\n"
+                           "      Pass -q to turn off this notice.", s);
+                return 1;
         }
+#endif
 
-        return 0;
+        /* If no ACLs were found, print a short version of the message. */
+        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
+                   "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
+                   "      turn off this notice.");
+
+        return 1;
 }
-#endif
 
 static int access_check(sd_journal *j) {
         Iterator it;
@@ -1587,40 +1689,15 @@ static int access_check(sd_journal *j) {
         if (set_isempty(j->errors)) {
                 if (ordered_hashmap_isempty(j->files))
                         log_notice("No journal files were found.");
+
                 return 0;
         }
 
         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
-#ifdef HAVE_ACL
-                /* If /var/log/journal doesn't even exist,
-                 * unprivileged users have no access at all */
-                if (access("/var/log/journal", F_OK) < 0 &&
-                    geteuid() != 0 &&
-                    in_group("systemd-journal") <= 0) {
-                        log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
-                                  "enabled. Users in the 'systemd-journal' group may always access messages.");
-                        return -EACCES;
-                }
+                (void) access_check_var_log_journal(j);
 
-                /* If /var/log/journal exists, try to pring a nice
-                   notice if the user lacks access to it */
-                if (!arg_quiet && geteuid() != 0) {
-                        r = access_check_var_log_journal(j);
-                        if (r < 0)
-                                return r;
-                }
-#else
-                if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
-                        log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
-                                  "group may access messages.");
-                        return -EACCES;
-                }
-#endif
-
-                if (ordered_hashmap_isempty(j->files)) {
-                        log_error("No journal files were opened due to insufficient permissions.");
-                        r = -EACCES;
-                }
+                if (ordered_hashmap_isempty(j->files))
+                        r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
         }
 
         SET_FOREACH(code, j->errors, it) {
@@ -1629,8 +1706,12 @@ static int access_check(sd_journal *j) {
                 err = -PTR_TO_INT(code);
                 assert(err > 0);
 
-                if (err != EACCES)
-                        log_warning_errno(err, "Error was encountered while opening journal files: %m");
+                if (err == EACCES)
+                        continue;
+
+                log_warning_errno(err, "Error was encountered while opening journal files: %m");
+                if (r == 0)
+                        r = -err;
         }
 
         return r;
@@ -1638,7 +1719,7 @@ static int access_check(sd_journal *j) {
 
 static int flush_to_var(void) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
         _cleanup_close_ int watch_fd = -1;
         int r;
 
@@ -1777,12 +1858,12 @@ int main(int argc, char *argv[]) {
         if (r < 0) {
                 log_error_errno(r, "Failed to open %s: %m",
                                 arg_directory ? arg_directory : arg_file ? "files" : "journal");
-                return EXIT_FAILURE;
+                goto finish;
         }
 
         r = access_check(j);
         if (r < 0)
-                return EXIT_FAILURE;
+                goto finish;
 
         if (arg_action == ACTION_VERIFY) {
                 r = verify(j);
@@ -1791,7 +1872,8 @@ int main(int argc, char *argv[]) {
 
         if (arg_action == ACTION_PRINT_HEADER) {
                 journal_print_header(j);
-                return EXIT_SUCCESS;
+                r = 0;
+                goto finish;
         }
 
         if (arg_action == ACTION_DISK_USAGE) {
@@ -1800,11 +1882,11 @@ int main(int argc, char *argv[]) {
 
                 r = sd_journal_get_usage(j, &bytes);
                 if (r < 0)
-                        return EXIT_FAILURE;
+                        goto finish;
 
                 printf("Archived and active journals take up %s on disk.\n",
                        format_bytes(sbytes, sizeof(sbytes), bytes));
-                return EXIT_SUCCESS;
+                goto finish;
         }
 
         if (arg_action == ACTION_VACUUM) {
@@ -1824,7 +1906,7 @@ int main(int argc, char *argv[]) {
                         }
                 }
 
-                return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+                goto finish;
         }
 
         if (arg_action == ACTION_LIST_BOOTS) {
@@ -1836,43 +1918,39 @@ int main(int argc, char *argv[]) {
          * It may need to seek the journal to find parent boot IDs. */
         r = add_boot(j);
         if (r < 0)
-                return EXIT_FAILURE;
+                goto finish;
 
         r = add_dmesg(j);
         if (r < 0)
-                return EXIT_FAILURE;
+                goto finish;
 
         r = add_units(j);
-        strv_free(arg_system_units);
-        strv_free(arg_user_units);
-
         if (r < 0) {
                 log_error_errno(r, "Failed to add filter for units: %m");
-                return EXIT_FAILURE;
+                goto finish;
         }
 
         r = add_syslog_identifier(j);
         if (r < 0) {
                 log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
-                return EXIT_FAILURE;
+                goto finish;
         }
 
         r = add_priorities(j);
-        if (r < 0) {
-                log_error_errno(r, "Failed to add filter for priorities: %m");
-                return EXIT_FAILURE;
-        }
+        if (r < 0)
+                goto finish;
 
         r = add_matches(j, argv + optind);
-        if (r < 0) {
-                log_error_errno(r, "Failed to add filters: %m");
-                return EXIT_FAILURE;
-        }
+        if (r < 0)
+                goto finish;
 
         if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
                 _cleanup_free_ char *filter;
 
                 filter = journal_make_match_string(j);
+                if (!filter)
+                        return log_oom();
+
                 log_debug("Journal filter: %s", filter);
         }
 
@@ -1882,14 +1960,14 @@ int main(int argc, char *argv[]) {
 
                 r = sd_journal_set_data_threshold(j, 0);
                 if (r < 0) {
-                        log_error("Failed to unset data size threshold");
-                        return EXIT_FAILURE;
+                        log_error_errno(r, "Failed to unset data size threshold: %m");
+                        goto finish;
                 }
 
                 r = sd_journal_query_unique(j, arg_field);
                 if (r < 0) {
                         log_error_errno(r, "Failed to query unique data objects: %m");
-                        return EXIT_FAILURE;
+                        goto finish;
                 }
 
                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
@@ -1907,22 +1985,26 @@ int main(int argc, char *argv[]) {
                         n_shown ++;
                 }
 
-                return EXIT_SUCCESS;
+                r = 0;
+                goto finish;
         }
 
         /* Opening the fd now means the first sd_journal_wait() will actually wait */
         if (arg_follow) {
                 r = sd_journal_get_fd(j);
-                if (r < 0)
-                        return EXIT_FAILURE;
+                if (r < 0) {
+                        log_error_errno(r, "Failed to get journal fd: %m");
+                        goto finish;
+                }
         }
 
         if (arg_cursor || arg_after_cursor) {
                 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
                 if (r < 0) {
                         log_error_errno(r, "Failed to seek to cursor: %m");
-                        return EXIT_FAILURE;
+                        goto finish;
                 }
+
                 if (!arg_reverse)
                         r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
                 else
@@ -1940,7 +2022,7 @@ int main(int argc, char *argv[]) {
                 r = sd_journal_seek_realtime_usec(j, arg_since);
                 if (r < 0) {
                         log_error_errno(r, "Failed to seek to date: %m");
-                        return EXIT_FAILURE;
+                        goto finish;
                 }
                 r = sd_journal_next(j);
 
@@ -1948,7 +2030,7 @@ int main(int argc, char *argv[]) {
                 r = sd_journal_seek_realtime_usec(j, arg_until);
                 if (r < 0) {
                         log_error_errno(r, "Failed to seek to date: %m");
-                        return EXIT_FAILURE;
+                        goto finish;
                 }
                 r = sd_journal_previous(j);
 
@@ -1956,7 +2038,7 @@ int main(int argc, char *argv[]) {
                 r = sd_journal_seek_tail(j);
                 if (r < 0) {
                         log_error_errno(r, "Failed to seek to tail: %m");
-                        return EXIT_FAILURE;
+                        goto finish;
                 }
 
                 r = sd_journal_previous_skip(j, arg_lines);
@@ -1965,7 +2047,7 @@ int main(int argc, char *argv[]) {
                 r = sd_journal_seek_tail(j);
                 if (r < 0) {
                         log_error_errno(r, "Failed to seek to tail: %m");
-                        return EXIT_FAILURE;
+                        goto finish;
                 }
 
                 r = sd_journal_previous(j);
@@ -1974,7 +2056,7 @@ int main(int argc, char *argv[]) {
                 r = sd_journal_seek_head(j);
                 if (r < 0) {
                         log_error_errno(r, "Failed to seek to head: %m");
-                        return EXIT_FAILURE;
+                        goto finish;
                 }
 
                 r = sd_journal_next(j);
@@ -1982,7 +2064,11 @@ int main(int argc, char *argv[]) {
 
         if (r < 0) {
                 log_error_errno(r, "Failed to iterate through journal: %m");
-                return EXIT_FAILURE;
+                goto finish;
+        }
+        if (r == 0) {
+                printf("-- No entries --\n");
+                goto finish;
         }
 
         if (!arg_follow)
@@ -2110,5 +2196,9 @@ finish:
 
         strv_free(arg_file);
 
+        strv_free(arg_syslog_identifier);
+        strv_free(arg_system_units);
+        strv_free(arg_user_units);
+
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }