X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fjournalctl.c;h=4c288f3334d66ffeae262a528a67477f9fe3144f;hp=65114b2ff8a219711c56d5d1adc4ba9bf41f5d7e;hb=4468addca6d01a0d2d154371dd72f54307a9c786;hpb=7199aa96ce19468d9ce4cb21a13e32a3792fde41 diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 65114b2ff..4c288f333 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -35,6 +35,10 @@ #include #include +#ifdef HAVE_ACL +#include +#endif + #include #include "log.h" @@ -90,6 +94,7 @@ static enum { ACTION_VERIFY, ACTION_DISK_USAGE, ACTION_LIST_CATALOG, + ACTION_DUMP_CATALOG, ACTION_UPDATE_CATALOG } arg_action = ACTION_SHOW; @@ -131,6 +136,7 @@ static int help(void) { " --disk-usage Show total disk usage\n" " -F --field=FIELD List all values a certain field takes\n" " --list-catalog Show message IDs of all entries in the message catalog\n" + " --dump-catalog Show entries in the message catalog\n" " --update-catalog Update the message catalog database\n" #ifdef HAVE_GCRYPT " --setup-keys Generate new FSS key pair\n" @@ -159,6 +165,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_UNTIL, ARG_USER_UNIT, ARG_LIST_CATALOG, + ARG_DUMP_CATALOG, ARG_UPDATE_CATALOG }; @@ -193,6 +200,7 @@ static int parse_argv(int argc, char *argv[]) { { "field", required_argument, NULL, 'F' }, { "catalog", no_argument, NULL, 'x' }, { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG }, + { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG }, { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG }, { "reverse", no_argument, NULL, 'r' }, { NULL, 0, NULL, 0 } @@ -445,6 +453,10 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_LIST_CATALOG; break; + case ARG_DUMP_CATALOG: + arg_action = ACTION_DUMP_CATALOG; + break; + case ARG_UPDATE_CATALOG: arg_action = ACTION_UPDATE_CATALOG; break; @@ -513,16 +525,16 @@ static int generate_new_id128(void) { static int add_matches(sd_journal *j, char **args) { char **i; - int r; assert(j); STRV_FOREACH(i, args) { + int r; if (streq(*i, "+")) r = sd_journal_add_disjunction(j); else if (path_is_absolute(*i)) { - char *p, *t = NULL; + char _cleanup_free_ *p, *t = NULL; const char *path; struct stat st; @@ -530,7 +542,6 @@ static int add_matches(sd_journal *j, char **args) { path = p ? p : *i; if (stat(path, &st) < 0) { - free(p); log_error("Couldn't stat file: %m"); return -errno; } @@ -542,18 +553,14 @@ static int add_matches(sd_journal *j, char **args) { else if (S_ISBLK(st.st_mode)) asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev)); else { - free(p); log_error("File is not a device node, regular file or is not executable: %s", *i); return -EINVAL; } - free(p); - if (!t) return log_oom(); r = sd_journal_add_match(j, t, 0); - free(t); } else r = sd_journal_add_match(j, *i, 0); @@ -593,7 +600,7 @@ static int add_this_boot(sd_journal *j) { } static int add_unit(sd_journal *j) { - _cleanup_free_ char *m = NULL, *u = NULL; + _cleanup_free_ char *u = NULL; int r; assert(j); @@ -878,13 +885,96 @@ static int verify(sd_journal *j) { static int access_check(void) { #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 can't see messages unless persistent log storage is enabled. Users in the group 'systemd-journal' can always see messages."); return -EACCES; } - if (!arg_quiet && geteuid() != 0 && in_group("systemd-journal") <= 0) - log_warning("Showing user generated messages only. Users in the group 'systemd-journal' can see all messages. Pass -q to turn this notice off."); + /* If /var/log/journal exists, try to pring a nice notice if the user lacks access to it */ + if (!arg_quiet && geteuid() != 0) { + _cleanup_strv_free_ char **g = NULL; + bool have_access; + acl_t acl; + int r; + + have_access = in_group("systemd-journal") > 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 */ + + acl = acl_get_file("/var/log/journal/", ACL_TYPE_DEFAULT); + if (acl) { + acl_entry_t entry; + + r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); + while (r > 0) { + acl_tag_t tag; + gid_t *gid; + char *name; + + r = acl_get_tag_type(entry, &tag); + if (r < 0) + break; + + if (tag != ACL_GROUP) + goto next; + + gid = acl_get_qualifier(entry); + if (!gid) + break; + + if (in_gid(*gid) > 0) { + have_access = true; + break; + } + + name = gid_to_name(*gid); + if (!name) { + acl_free(acl); + return log_oom(); + } + + r = strv_push(&g, name); + if (r < 0) { + free(name); + acl_free(acl); + return log_oom(); + } + + next: + r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); + } + + acl_free(acl); + } + } + + if (!have_access) { + + if (strv_isempty(g)) + log_notice("Hint: You are currently not seeing messages from other users and the system. Users in the group 'systemd-journal' can see all messages. Pass -q to turn this notice off."); + else { + _cleanup_free_ char *s = NULL; + + r = strv_extend(&g, "systemd-journal"); + if (r < 0) + return log_oom(); + + 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. Users in the groups '%s' can see all messages. Pass -q to turn this notice off.", s); + } + } + } #else if (geteuid() != 0 && in_group("systemd-journal") <= 0) { log_error("No access to messages. Only users in the group 'systemd-journal' can see messages."); @@ -897,7 +987,7 @@ static int access_check(void) { int main(int argc, char *argv[]) { int r; - sd_journal *j = NULL; + sd_journal _cleanup_journal_close_ *j = NULL; bool need_seek = false; sd_id128_t previous_boot_id; bool previous_boot_id_valid = false, first_line = true; @@ -923,8 +1013,13 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_action == ACTION_LIST_CATALOG) { - r = catalog_list(stdout); + if (arg_action == ACTION_LIST_CATALOG || + arg_action == ACTION_DUMP_CATALOG) { + bool oneline = arg_action == ACTION_LIST_CATALOG; + if (optind < argc) + r = catalog_list_items(stdout, oneline, argv + optind); + else + r = catalog_list(stdout, oneline); if (r < 0) log_error("Failed to list catalog: %s", strerror(-r)); goto finish; @@ -937,7 +1032,7 @@ int main(int argc, char *argv[]) { r = access_check(); if (r < 0) - goto finish; + return EXIT_FAILURE; if (arg_directory) r = sd_journal_open_directory(&j, arg_directory, 0); @@ -945,7 +1040,7 @@ int main(int argc, char *argv[]) { r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } if (arg_action == ACTION_VERIFY) { @@ -955,8 +1050,7 @@ int main(int argc, char *argv[]) { if (arg_action == ACTION_PRINT_HEADER) { journal_print_header(j); - r = 0; - goto finish; + return EXIT_SUCCESS; } if (arg_action == ACTION_DISK_USAGE) { @@ -965,33 +1059,33 @@ int main(int argc, char *argv[]) { r = sd_journal_get_usage(j, &bytes); if (r < 0) - goto finish; + return EXIT_FAILURE; - printf("Journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes)); - r = 0; - goto finish; + printf("Journals take up %s on disk.\n", + format_bytes(sbytes, sizeof(sbytes), bytes)); + return EXIT_SUCCESS; } r = add_this_boot(j); if (r < 0) - goto finish; + return EXIT_FAILURE; r = add_unit(j); if (r < 0) - goto finish; + return EXIT_FAILURE; r = add_matches(j, argv + optind); if (r < 0) - goto finish; + return EXIT_FAILURE; r = add_priorities(j); if (r < 0) - goto finish; + return EXIT_FAILURE; /* Opening the fd now means the first sd_journal_wait() will actually wait */ r = sd_journal_get_fd(j); if (r < 0) - goto finish; + return EXIT_FAILURE; if (arg_field) { const void *data; @@ -1000,7 +1094,7 @@ int main(int argc, char *argv[]) { r = sd_journal_query_unique(j, arg_field); if (r < 0) { log_error("Failed to query unique data objects: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { @@ -1018,15 +1112,14 @@ int main(int argc, char *argv[]) { n_shown ++; } - r = 0; - goto finish; + return EXIT_SUCCESS; } if (arg_cursor) { r = sd_journal_seek_cursor(j, arg_cursor); if (r < 0) { log_error("Failed to seek to cursor: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } if (!arg_reverse) r = sd_journal_next(j); @@ -1037,7 +1130,7 @@ int main(int argc, char *argv[]) { r = sd_journal_seek_realtime_usec(j, arg_since); if (r < 0) { log_error("Failed to seek to date: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } r = sd_journal_next(j); @@ -1045,7 +1138,7 @@ int main(int argc, char *argv[]) { r = sd_journal_seek_realtime_usec(j, arg_until); if (r < 0) { log_error("Failed to seek to date: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } r = sd_journal_previous(j); @@ -1053,7 +1146,7 @@ int main(int argc, char *argv[]) { r = sd_journal_seek_tail(j); if (r < 0) { log_error("Failed to seek to tail: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } r = sd_journal_previous_skip(j, arg_lines); @@ -1062,7 +1155,7 @@ int main(int argc, char *argv[]) { r = sd_journal_seek_tail(j); if (r < 0) { log_error("Failed to seek to tail: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } r = sd_journal_previous(j); @@ -1071,7 +1164,7 @@ int main(int argc, char *argv[]) { r = sd_journal_seek_head(j); if (r < 0) { log_error("Failed to seek to head: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } r = sd_journal_next(j); @@ -1079,7 +1172,7 @@ int main(int argc, char *argv[]) { if (r < 0) { log_error("Failed to iterate through journal: %s", strerror(-r)); - goto finish; + return EXIT_FAILURE; } if (!arg_no_pager && !arg_follow) @@ -1189,9 +1282,6 @@ int main(int argc, char *argv[]) { } finish: - if (j) - sd_journal_close(j); - pager_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;