]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/journal/coredumpctl.c
tree-wide: make use of log_error_errno() return value in more cases
[thirdparty/systemd.git] / src / journal / coredumpctl.c
index 81b5462a41ac4618832b54ad5eeae5ca552af899..0546290318985a1ab910966c26bbf20cd78d68dc 100644 (file)
@@ -26,8 +26,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "systemd/sd-journal.h"
-
+#include "sd-journal.h"
 #include "build.h"
 #include "set.h"
 #include "util.h"
 #include "pager.h"
 #include "macro.h"
 #include "journal-internal.h"
-#include "copy.h"
 #include "compress.h"
+#include "sigbus.h"
+#include "process-util.h"
+#include "terminal-util.h"
+#include "signal-util.h"
 
 static enum {
         ACTION_NONE,
@@ -47,11 +49,11 @@ static enum {
         ACTION_GDB,
 } arg_action = ACTION_LIST;
 static const char* arg_field = NULL;
+static const char *arg_directory = NULL;
 static int arg_no_pager = false;
 static int arg_no_legend = false;
 static int arg_one = false;
-
-static FILE* output = NULL;
+static FILE* arg_output = NULL;
 
 static Set *new_matches(void) {
         Set *set;
@@ -73,7 +75,7 @@ static Set *new_matches(void) {
 
         r = set_consume(set, tmp);
         if (r < 0) {
-                log_error_errno(-r, "failed to add to set: %m");
+                log_error_errno(r, "failed to add to set: %m");
                 set_free(set);
                 return NULL;
         }
@@ -110,14 +112,13 @@ static int add_match(Set *set, const char *match) {
         log_debug("Adding pattern: %s", pattern);
         r = set_consume(set, pattern);
         if (r < 0) {
-                log_error_errno(-r, "Failed to add pattern: %m");
+                log_error_errno(r, "Failed to add pattern: %m");
                 goto fail;
         }
 
         return 0;
 fail:
-        log_error_errno(-r, "Failed to add match: %m");
-        return r;
+        return log_error_errno(r, "Failed to add match: %m");
 }
 
 static void help(void) {
@@ -131,6 +132,7 @@ static void help(void) {
                "  -1                 Show information about most recent entry only\n"
                "  -F --field=FIELD   List all values a certain field takes\n"
                "  -o --output=FILE   Write output to FILE\n\n"
+               "  -D --directory=DIR Use journal files from directory\n\n"
 
                "Commands:\n"
                "  list [MATCHES...]  List available coredumps (default)\n"
@@ -156,13 +158,14 @@ static int parse_argv(int argc, char *argv[], Set *matches) {
                 { "no-legend",    no_argument,       NULL, ARG_NO_LEGEND },
                 { "output",       required_argument, NULL, 'o'           },
                 { "field",        required_argument, NULL, 'F'           },
+                { "directory",    required_argument, NULL, 'D'           },
                 {}
         };
 
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "ho:F:1", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "ho:F:1D:", options, NULL)) >= 0)
                 switch(c) {
 
                 case 'h':
@@ -185,16 +188,14 @@ static int parse_argv(int argc, char *argv[], Set *matches) {
                         break;
 
                 case 'o':
-                        if (output) {
+                        if (arg_output) {
                                 log_error("cannot set output more than once");
                                 return -EINVAL;
                         }
 
-                        output = fopen(optarg, "we");
-                        if (!output) {
-                                log_error("writing to '%s': %m", optarg);
-                                return -errno;
-                        }
+                        arg_output = fopen(optarg, "we");
+                        if (!arg_output)
+                                return log_error_errno(errno, "writing to '%s': %m", optarg);
 
                         break;
 
@@ -210,6 +211,10 @@ static int parse_argv(int argc, char *argv[], Set *matches) {
                         arg_one = true;
                         break;
 
+                case 'D':
+                        arg_directory = optarg;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -326,10 +331,8 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) {
         }
 
         r = sd_journal_get_realtime_usec(j, &t);
-        if (r < 0) {
-                log_error_errno(-r, "Failed to get realtime timestamp: %m");
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to get realtime timestamp: %m");
 
         format_timestamp(buf, sizeof(buf), t);
         present = filename && access(filename, F_OK) == 0;
@@ -521,10 +524,8 @@ static int focus(sd_journal *j) {
         r = sd_journal_seek_tail(j);
         if (r == 0)
                 r = sd_journal_previous(j);
-        if (r < 0) {
-                log_error_errno(-r, "Failed to search journal: %m");
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to search journal: %m");
         if (r == 0) {
                 log_error("No match found.");
                 return -ESRCH;
@@ -586,15 +587,14 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
          * compressed file (probably uncached). */
         r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len);
         if (r < 0 && r != -ENOENT)
-                log_warning_errno(-r, "Failed to retrieve COREDUMP_FILENAME: %m");
+                log_warning_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m");
         else if (r == 0)
                 retrieve(data, len, "COREDUMP_FILENAME", &filename);
 
         if (filename && access(filename, R_OK) < 0) {
                 log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
                          "File %s is not readable: %m", filename);
-                free(filename);
-                filename = NULL;
+                filename = mfree(filename);
         }
 
         if (filename && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) {
@@ -614,10 +614,8 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
                                 return log_oom();
 
                         fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
-                        if (fdt < 0) {
-                                log_error("Failed to create temporary file: %m");
-                                return -errno;
-                        }
+                        if (fdt < 0)
+                                return log_error_errno(errno, "Failed to create temporary file: %m");
                         log_debug("Created temporary file %s", temp);
 
                         fd = fdt;
@@ -633,8 +631,8 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
 
                         sz = write(fdt, data, len);
                         if (sz < 0) {
-                                log_error("Failed to write temporary file: %m");
-                                r = -errno;
+                                r = log_error_errno(errno,
+                                                    "Failed to write temporary file: %m");
                                 goto error;
                         }
                         if (sz != (ssize_t) len) {
@@ -648,26 +646,27 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
 
                         fdf = open(filename, O_RDONLY | O_CLOEXEC);
                         if (fdf < 0) {
-                                log_error("Failed to open %s: %m", filename);
-                                r = -errno;
+                                r = log_error_errno(errno,
+                                                    "Failed to open %s: %m",
+                                                    filename);
                                 goto error;
                         }
 
                         r = decompress_stream(filename, fdf, fd, -1);
                         if (r < 0) {
-                                log_error_errno(-r, "Failed to decompress %s: %m", filename);
+                                log_error_errno(r, "Failed to decompress %s: %m", filename);
                                 goto error;
                         }
 #else
                         log_error("Cannot decompress file. Compiled without compression support.");
-                        r = -ENOTSUP;
+                        r = -EOPNOTSUPP;
                         goto error;
 #endif
                 } else {
                         if (r == -ENOENT)
                                 log_error("Cannot retrieve coredump from journal nor disk.");
                         else
-                                log_error_errno(-r, "Failed to retrieve COREDUMP field: %m");
+                                log_error_errno(r, "Failed to retrieve COREDUMP field: %m");
                         goto error;
                 }
 
@@ -696,18 +695,16 @@ static int dump_core(sd_journal* j) {
         if (r < 0)
                 return r;
 
-        print_info(output ? stdout : stderr, j, false);
+        print_info(arg_output ? stdout : stderr, j, false);
 
-        if (on_tty() && !output) {
+        if (on_tty() && !arg_output) {
                 log_error("Refusing to dump core to tty.");
                 return -ENOTTY;
         }
 
-        r = save_core(j, output ? fileno(output) : STDOUT_FILENO, NULL, NULL);
-        if (r < 0) {
-                log_error_errno(-r, "Coredump retrieval failed: %m");
-                return r;
-        }
+        r = save_core(j, arg_output ? fileno(arg_output) : STDOUT_FILENO, NULL, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Coredump retrieval failed: %m");
 
         r = sd_journal_previous(j);
         if (r >= 0)
@@ -735,10 +732,8 @@ static int run_gdb(sd_journal *j) {
         fputs("\n", stdout);
 
         r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len);
-        if (r < 0) {
-                log_error_errno(-r, "Failed to retrieve COREDUMP_EXE field: %m");
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m");
 
         assert(len > strlen("COREDUMP_EXE="));
         data += strlen("COREDUMP_EXE=");
@@ -759,27 +754,27 @@ static int run_gdb(sd_journal *j) {
         }
 
         r = save_core(j, -1, &path, &unlink_path);
-        if (r < 0) {
-                log_error_errno(-r, "Failed to retrieve core: %m");
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to retrieve core: %m");
 
         pid = fork();
         if (pid < 0) {
-                log_error("Failed to fork(): %m");
-                r = -errno;
+                r = log_error_errno(errno, "Failed to fork(): %m");
                 goto finish;
         }
         if (pid == 0) {
+                (void) reset_all_signal_handlers();
+                (void) reset_signal_mask();
+
                 execlp("gdb", "gdb", exe, path, NULL);
 
-                log_error("Failed to invoke gdb: %m");
+                log_error_errno(errno, "Failed to invoke gdb: %m");
                 _exit(1);
         }
 
         r = wait_for_terminate(pid, &st);
         if (r < 0) {
-                log_error("Failed to wait for gdb: %m");
+                log_error_errno(errno, "Failed to wait for gdb: %m");
                 goto finish;
         }
 
@@ -818,10 +813,20 @@ int main(int argc, char *argv[]) {
         if (arg_action == ACTION_NONE)
                 goto end;
 
-        r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
-        if (r < 0) {
-                log_error_errno(-r, "Failed to open journal: %m");
-                goto end;
+        sigbus_install();
+
+        if (arg_directory) {
+                r = sd_journal_open_directory(&j, arg_directory, 0);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
+                        goto end;
+                }
+        } else {
+                r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to open journal: %m");
+                        goto end;
+                }
         }
 
         /* We want full data, nothing truncated. */
@@ -830,13 +835,13 @@ int main(int argc, char *argv[]) {
         SET_FOREACH(match, matches, it) {
                 r = sd_journal_add_match(j, match, strlen(match));
                 if (r != 0) {
-                        log_error("Failed to add match '%s': %s",
-                                  match, strerror(-r));
+                        log_error_errno(r, "Failed to add match '%s': %m",
+                                        match);
                         goto end;
                 }
         }
 
-        if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
+        if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
                 _cleanup_free_ char *filter;
 
                 filter = journal_make_match_string(j);
@@ -868,8 +873,8 @@ int main(int argc, char *argv[]) {
 end:
         pager_close();
 
-        if (output)
-                fclose(output);
+        if (arg_output)
+                fclose(arg_output);
 
         return r >= 0 ? r : EXIT_FAILURE;
 }