]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/coredump/coredumpctl.c
build-sys: use #if Y instead of #ifdef Y everywhere
[thirdparty/systemd.git] / src / coredump / coredumpctl.c
index 4ac98d8163d5fd2aa3ea3682ca63b513990755ee..0380df10d1be5206c2f0fa3867402ef736764a7b 100644 (file)
@@ -36,6 +36,7 @@
 #include "fileio.h"
 #include "fs-util.h"
 #include "journal-internal.h"
+#include "journal-util.h"
 #include "log.h"
 #include "macro.h"
 #include "pager.h"
@@ -50,6 +51,8 @@
 #include "user-util.h"
 #include "util.h"
 
+#define SHORT_BUS_CALL_TIMEOUT_USEC (3 * USEC_PER_SEC)
+
 static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY;
 
 static enum {
@@ -67,6 +70,7 @@ static int arg_one = false;
 static FILE* arg_output = NULL;
 static bool arg_reverse = false;
 static char** arg_matches = NULL;
+static bool arg_quiet = false;
 
 static int add_match(sd_journal *j, const char *match) {
         _cleanup_free_ char *p = NULL;
@@ -136,6 +140,7 @@ static void help(void) {
                "  -F --field=FIELD   List all values a certain field takes\n"
                "  -o --output=FILE   Write output to FILE\n"
                "  -D --directory=DIR Use journal files from directory\n\n"
+               "  -q --quiet         Do not show info messages and privilege warning\n"
                "Commands:\n"
                "  list [MATCHES...]  List available coredumps (default)\n"
                "  info [MATCHES...]  Show detailed information about one or more coredumps\n"
@@ -164,13 +169,14 @@ static int parse_argv(int argc, char *argv[]) {
                 { "reverse",      no_argument,       NULL, 'r'           },
                 { "since",        required_argument, NULL, 'S'           },
                 { "until",        required_argument, NULL, 'U'           },
+                { "quiet",        no_argument,       NULL, 'q'           },
                 {}
         };
 
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "ho:F:1D:S:U:r", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "ho:F:1D:rS:U:q", options, NULL)) >= 0)
                 switch(c) {
                 case 'h':
                         arg_action = ACTION_NONE;
@@ -233,6 +239,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_reverse = true;
                         break;
 
+                case 'q':
+                        arg_quiet = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -343,7 +353,7 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) {
         _cleanup_free_ char
                 *mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL,
                 *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
-                *filename = NULL, *coredump = NULL;
+                *filename = NULL, *truncated = NULL, *coredump = NULL;
         const void *d;
         size_t l;
         usec_t t;
@@ -365,6 +375,7 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) {
                 RETRIEVE(d, l, "COREDUMP_COMM", comm);
                 RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline);
                 RETRIEVE(d, l, "COREDUMP_FILENAME", filename);
+                RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated);
                 RETRIEVE(d, l, "COREDUMP", coredump);
         }
 
@@ -380,13 +391,13 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) {
         format_timestamp(buf, sizeof(buf), t);
 
         if (!had_legend && !arg_no_legend)
-                fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n",
+                fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n",
                         FORMAT_TIMESTAMP_WIDTH, "TIME",
                         6, "PID",
                         5, "UID",
                         5, "GID",
                         3, "SIG",
-                        8, "COREFILE",
+                        9, "COREFILE",
                            "EXE");
 
         normal_coredump = streq_ptr(mid, SD_MESSAGE_COREDUMP_STR);
@@ -405,13 +416,16 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) {
         else
                 present = "-";
 
+        if (STR_IN_SET(present, "present", "journal") && truncated && parse_boolean(truncated) > 0)
+                present = "truncated";
+
         fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n",
                 FORMAT_TIMESTAMP_WIDTH, buf,
                 6, strna(pid),
                 5, strna(uid),
                 5, strna(gid),
                 3, normal_coredump ? strna(sgnl) : "-",
-                8, present,
+                9, present,
                 strna(exe ?: (comm ?: cmdline)));
 
         return 0;
@@ -425,7 +439,7 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
                 *boot_id = NULL, *machine_id = NULL, *hostname = NULL,
                 *slice = NULL, *cgroup = NULL, *owner_uid = NULL,
                 *message = NULL, *timestamp = NULL, *filename = NULL,
-                *coredump = NULL;
+                *truncated = NULL, *coredump = NULL;
         const void *d;
         size_t l;
         bool normal_coredump;
@@ -451,6 +465,7 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
                 RETRIEVE(d, l, "COREDUMP_CGROUP", cgroup);
                 RETRIEVE(d, l, "COREDUMP_TIMESTAMP", timestamp);
                 RETRIEVE(d, l, "COREDUMP_FILENAME", filename);
+                RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated);
                 RETRIEVE(d, l, "COREDUMP", coredump);
                 RETRIEVE(d, l, "_BOOT_ID", boot_id);
                 RETRIEVE(d, l, "_MACHINE_ID", machine_id);
@@ -569,9 +584,24 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
         if (hostname)
                 fprintf(file, "      Hostname: %s\n", hostname);
 
-        if (filename)
-                fprintf(file, "       Storage: %s%s\n", filename,
-                        access(filename, R_OK) < 0 ? " (inaccessible)" : "");
+        if (filename) {
+                bool inacc, trunc;
+
+                inacc = access(filename, R_OK) < 0;
+                trunc = truncated && parse_boolean(truncated) > 0;
+
+                if (inacc || trunc)
+                        fprintf(file, "       Storage: %s%s (%s%s%s)%s\n",
+                                ansi_highlight_red(),
+                                filename,
+                                inacc ? "inaccessible" : "",
+                                inacc && trunc ? ", " : "",
+                                trunc ? "truncated" : "",
+                                ansi_normal());
+                else
+                        fprintf(file, "       Storage: %s\n", filename);
+        }
+
         else if (coredump)
                 fprintf(file, "       Storage: journal\n");
         else
@@ -681,7 +711,8 @@ static int dump_list(sd_journal *j) {
                 }
 
                 if (!arg_field && n_found <= 0) {
-                        log_notice("No coredumps found.");
+                        if (!arg_quiet)
+                                log_notice("No coredumps found.");
                         return -ESRCH;
                 }
         }
@@ -768,7 +799,7 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp)
         }
 
         if (filename) {
-#if defined(HAVE_XZ) || defined(HAVE_LZ4)
+#if HAVE_XZ || HAVE_LZ4
                 _cleanup_close_ int fdf;
 
                 fdf = open(filename, O_RDONLY | O_CLOEXEC);
@@ -843,8 +874,8 @@ static int dump_core(sd_journal* j) {
                 return r;
 
         r = sd_journal_previous(j);
-        if (r > 0)
-                log_warning("More than one entry matches, ignoring rest.");
+        if (r > 0 && !arg_quiet)
+                log_notice("More than one entry matches, ignoring rest.");
 
         return 0;
 }
@@ -936,7 +967,10 @@ static int check_units_active(void) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int c = 0, r;
-        const char *state;
+        const char *id, *state, *substate;
+
+        if (arg_quiet)
+                return false;
 
         r = sd_bus_default_system(&bus);
         if (r < 0)
@@ -960,7 +994,7 @@ static int check_units_active(void) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_call(bus, m, 0, &error, &reply);
+        r = sd_bus_call(bus, m, SHORT_BUS_CALL_TIMEOUT_USEC, &error, &reply);
         if (r < 0)
                 return log_error_errno(r, "Failed to check if any systemd-coredump@.service units are running: %s",
                                        bus_error_message(&error, r));
@@ -971,11 +1005,12 @@ static int check_units_active(void) {
 
         while ((r = sd_bus_message_read(
                                 reply, "(ssssssouso)",
-                                NULL,  NULL,  NULL,  &state,  NULL,
-                                NULL,  NULL,  NULL,  NULL,  NULL)) > 0)
-                if (!STR_IN_SET(state, "dead", "failed"))
-                        c++;
-
+                                &id,  NULL,  NULL,  &state,  &substate,
+                                NULL,  NULL,  NULL,  NULL,  NULL)) > 0) {
+                bool found = !STR_IN_SET(state, "inactive", "dead", "failed");
+                log_debug("Unit %s is %s/%s, %scounting it.", id, state, substate, found ? "" : "not ");
+                c += found;
+        }
         if (r < 0)
                 return bus_log_parse_error(r);
 
@@ -1017,6 +1052,10 @@ int main(int argc, char *argv[]) {
                 }
         }
 
+        r = journal_access_check_and_warn(j, arg_quiet);
+        if (r < 0)
+                goto end;
+
         r = add_matches(j);
         if (r < 0)
                 goto end;