diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2016-09-27 10:52:10 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2016-09-28 23:49:01 +0200 |
commit | 062b99e8be63ba49b80d988da9b00a1d39255496 (patch) | |
tree | d54288a43cc1a71af9bbc24fdaa2e77f19fcf7db | |
parent | 04de587942054c414beda54af303880851b0fa4c (diff) |
coredumpctl: tighten print_field() code
Propagate errors properly, so that if we hit oom or an error in the
journal, the whole command will fail. This is important when using
the output in scripts.
Support the output of multiple values for the same field with -F.
The journal supports that, and our official commands should too, as
far as it makes sense. -F can be used to print user-defined fields
(e.g. somebody could use a TAG field with multiple occurences), so
we should support that too. That seems better than silently printing
the last value found as was done before.
We would iterate trying to match the same field with all possible
field names. Once we find something, cut the loop short, since we
know that nothing else can match.
-rw-r--r-- | src/coredump/coredumpctl.c | 109 |
1 files changed, 66 insertions, 43 deletions
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 57d18006a4..a408adf169 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -280,11 +280,10 @@ static int retrieve(const void *data, free(*var); *var = v; - return 0; + return 1; } -static void print_field(FILE* file, sd_journal *j) { - _cleanup_free_ char *value = NULL; +static int print_field(FILE* file, sd_journal *j) { const void *d; size_t l; @@ -293,13 +292,34 @@ static void print_field(FILE* file, sd_journal *j) { assert(arg_field); - SD_JOURNAL_FOREACH_DATA(j, d, l) - retrieve(d, l, arg_field, &value); + /* A (user-specified) field may appear more than once for a given entry. + * We will print all of the occurences. + * This is different below for fields that systemd-coredump uses, + * because they cannot meaningfully appear more than once. + */ + SD_JOURNAL_FOREACH_DATA(j, d, l) { + _cleanup_free_ char *value = NULL; + int r; + + r = retrieve(d, l, arg_field, &value); + if (r < 0) + return r; + if (r > 0) + fprintf(file, "%s\n", value); + } - if (value) - fprintf(file, "%s\n", value); + return 0; } +#define RETRIEVE(d, l, name, arg) \ + { \ + int _r = retrieve(d, l, name, &arg); \ + if (_r < 0) \ + return _r; \ + if (_r > 0) \ + continue; \ + } + static int print_list(FILE* file, sd_journal *j, int had_legend) { _cleanup_free_ char *pid = NULL, *uid = NULL, *gid = NULL, @@ -316,15 +336,15 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { - retrieve(d, l, "COREDUMP_PID", &pid); - retrieve(d, l, "COREDUMP_UID", &uid); - retrieve(d, l, "COREDUMP_GID", &gid); - retrieve(d, l, "COREDUMP_SIGNAL", &sgnl); - retrieve(d, l, "COREDUMP_EXE", &exe); - retrieve(d, l, "COREDUMP_COMM", &comm); - retrieve(d, l, "COREDUMP_CMDLINE", &cmdline); - retrieve(d, l, "COREDUMP_FILENAME", &filename); - retrieve(d, l, "COREDUMP", &coredump); + RETRIEVE(d, l, "COREDUMP_PID", pid); + RETRIEVE(d, l, "COREDUMP_UID", uid); + RETRIEVE(d, l, "COREDUMP_GID", gid); + RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl); + RETRIEVE(d, l, "COREDUMP_EXE", exe); + RETRIEVE(d, l, "COREDUMP_COMM", comm); + RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline); + RETRIEVE(d, l, "COREDUMP_FILENAME", filename); + RETRIEVE(d, l, "COREDUMP", coredump); } if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) { @@ -389,26 +409,26 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { - retrieve(d, l, "COREDUMP_PID", &pid); - retrieve(d, l, "COREDUMP_UID", &uid); - retrieve(d, l, "COREDUMP_GID", &gid); - retrieve(d, l, "COREDUMP_SIGNAL", &sgnl); - retrieve(d, l, "COREDUMP_EXE", &exe); - retrieve(d, l, "COREDUMP_COMM", &comm); - retrieve(d, l, "COREDUMP_CMDLINE", &cmdline); - retrieve(d, l, "COREDUMP_UNIT", &unit); - retrieve(d, l, "COREDUMP_USER_UNIT", &user_unit); - retrieve(d, l, "COREDUMP_SESSION", &session); - retrieve(d, l, "COREDUMP_OWNER_UID", &owner_uid); - retrieve(d, l, "COREDUMP_SLICE", &slice); - retrieve(d, l, "COREDUMP_CGROUP", &cgroup); - retrieve(d, l, "COREDUMP_TIMESTAMP", ×tamp); - retrieve(d, l, "COREDUMP_FILENAME", &filename); - retrieve(d, l, "COREDUMP", &coredump); - retrieve(d, l, "_BOOT_ID", &boot_id); - retrieve(d, l, "_MACHINE_ID", &machine_id); - retrieve(d, l, "_HOSTNAME", &hostname); - retrieve(d, l, "MESSAGE", &message); + RETRIEVE(d, l, "COREDUMP_PID", pid); + RETRIEVE(d, l, "COREDUMP_UID", uid); + RETRIEVE(d, l, "COREDUMP_GID", gid); + RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl); + RETRIEVE(d, l, "COREDUMP_EXE", exe); + RETRIEVE(d, l, "COREDUMP_COMM", comm); + RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline); + RETRIEVE(d, l, "COREDUMP_UNIT", unit); + RETRIEVE(d, l, "COREDUMP_USER_UNIT", user_unit); + RETRIEVE(d, l, "COREDUMP_SESSION", session); + RETRIEVE(d, l, "COREDUMP_OWNER_UID", owner_uid); + RETRIEVE(d, l, "COREDUMP_SLICE", slice); + RETRIEVE(d, l, "COREDUMP_CGROUP", cgroup); + RETRIEVE(d, l, "COREDUMP_TIMESTAMP", timestamp); + RETRIEVE(d, l, "COREDUMP_FILENAME", filename); + RETRIEVE(d, l, "COREDUMP", coredump); + RETRIEVE(d, l, "_BOOT_ID", boot_id); + RETRIEVE(d, l, "_MACHINE_ID", machine_id); + RETRIEVE(d, l, "_HOSTNAME", hostname); + RETRIEVE(d, l, "MESSAGE", message); } if (need_space) @@ -553,15 +573,15 @@ static int focus(sd_journal *j) { return r; } -static void print_entry(sd_journal *j, unsigned n_found) { +static int print_entry(sd_journal *j, unsigned n_found) { assert(j); if (arg_action == ACTION_INFO) - print_info(stdout, j, n_found); + return print_info(stdout, j, n_found); else if (arg_field) - print_field(stdout, j); + return print_field(stdout, j); else - print_list(stdout, j, n_found); + return print_list(stdout, j, n_found); } static int dump_list(sd_journal *j) { @@ -580,10 +600,13 @@ static int dump_list(sd_journal *j) { if (r < 0) return r; - print_entry(j, 0); + return print_entry(j, 0); } else { - SD_JOURNAL_FOREACH(j) - print_entry(j, n_found++); + SD_JOURNAL_FOREACH(j) { + r = print_entry(j, n_found++); + if (r < 0) + return r; + } if (!arg_field && n_found <= 0) { log_notice("No coredumps found."); |