]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
coredumpctl: Add support for the --root option
authorRichard Phibel <richardphibel@fb.com>
Thu, 8 Sep 2022 16:36:35 +0000 (09:36 -0700)
committerRichard Phibel <rphibel@googlemail.com>
Mon, 3 Oct 2022 10:19:28 +0000 (12:19 +0200)
With this option, coredumpctl looks for journal files under the
specified root directory

man/coredumpctl.xml
src/coredump/coredumpctl.c

index d28a177842347ae6fa75c4bf1c434555348cb375..52270a3e0782b9f87ac308336e7dfb12f1aeb78b 100644 (file)
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--root=<replaceable>ROOT</replaceable></option></term>
+
+        <listitem><para>Use root directory <option>ROOT</option> when searching for coredumps.
+        </para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>-q</option></term>
         <term><option>--quiet</option></term>
index da0b591c484f4ff985b412f825cbcebc438598ef..1de9106c8b96a1fcc8fc902f703d1b4bd0457c70 100644 (file)
@@ -14,6 +14,7 @@
 #include "bus-error.h"
 #include "bus-locator.h"
 #include "bus-util.h"
+#include "chase-symlinks.h"
 #include "compress.h"
 #include "def.h"
 #include "fd-util.h"
@@ -49,6 +50,7 @@ static const char* arg_field = NULL;
 static const char *arg_debugger = NULL;
 static char **arg_debugger_args = NULL;
 static const char *arg_directory = NULL;
+static char *arg_root = NULL;
 static char **arg_file = NULL;
 static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 static PagerFlags arg_pager_flags = 0;
@@ -121,6 +123,10 @@ static int acquire_journal(sd_journal **ret, char **matches) {
                 r = sd_journal_open_directory(&j, arg_directory, 0);
                 if (r < 0)
                         return log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
+        } else if (arg_root) {
+                r = sd_journal_open_directory(&j, arg_root, SD_JOURNAL_OS_ROOT);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to open journals in root directory: %s: %m", arg_root);
         } else if (arg_file) {
                 r = sd_journal_open_files(&j, (const char**)arg_file, 0);
                 if (r < 0)
@@ -205,6 +211,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_JSON,
                 ARG_DEBUGGER,
                 ARG_FILE,
+                ARG_ROOT,
                 ARG_ALL,
         };
 
@@ -226,6 +233,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "until",              required_argument, NULL, 'U'           },
                 { "quiet",              no_argument,       NULL, 'q'           },
                 { "json",               required_argument, NULL, ARG_JSON      },
+                { "root",               required_argument, NULL, ARG_ROOT      },
                 { "all",                no_argument,       NULL, ARG_ALL       },
                 {}
         };
@@ -316,6 +324,12 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_directory = optarg;
                         break;
 
+                case ARG_ROOT:
+                        r = parse_path_argument(optarg, false, &arg_root);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case 'r':
                         arg_reverse = true;
                         break;
@@ -347,6 +361,9 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "--since= must be before --until=.");
 
+        if ((!!arg_directory + !!arg_root) > 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or -D/--directory=, the combination of these options is not supported.");
+
         return 1;
 }
 
@@ -467,6 +484,26 @@ error:
         *ret_size = UINT64_MAX;
 }
 
+static int resolve_filename(const char *path, const char *root, char **ret) {
+        char *resolved = NULL;
+        int r;
+
+        if (!path)
+                return 0;
+
+        r = chase_symlinks(path, root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to resolve \"%s%s\": %m", strempty(root), path);
+
+        free_and_replace(*ret, resolved);
+
+        /* chase_symlinks() witth flag CHASE_NONEXISTENT
+         * will return 0 if the file doesn't exist and 1 if it does.
+         * Return that to the caller
+         */
+        return r;
+}
+
 static int print_list(FILE* file, sd_journal *j, Table *t) {
         _cleanup_free_ char
                 *mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL,
@@ -515,9 +552,13 @@ static int print_list(FILE* file, sd_journal *j, Table *t) {
 
         normal_coredump = streq_ptr(mid, SD_MESSAGE_COREDUMP_STR);
 
-        if (filename)
+        if (filename) {
+                r = resolve_filename(filename, arg_root, &filename);
+                if (r < 0)
+                        return r;
+
                 analyze_coredump_file(filename, &present, &color, &size);
-        else if (coredump)
+        else if (coredump)
                 present = "journal";
         else if (normal_coredump) {
                 present = "none";
@@ -701,6 +742,10 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
                 fprintf(file, "      Hostname: %s\n", hostname);
 
         if (filename) {
+                r = resolve_filename(filename, arg_root, &filename);
+                if (r < 0)
+                        return r;
+
                 const char *state = NULL, *color = NULL;
                 uint64_t size = UINT64_MAX;
 
@@ -915,13 +960,18 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp)
         /* Look for a coredump on disk first. */
         r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len);
         if (r == 0) {
+                _cleanup_free_ char *resolved = NULL;
+
                 r = retrieve(data, len, "COREDUMP_FILENAME", &filename);
                 if (r < 0)
                         return r;
                 assert(r > 0);
 
-                if (access(filename, R_OK) < 0)
-                        return log_error_errno(errno, "File \"%s\" is not readable: %m", filename);
+                r = chase_symlinks_and_access(filename, arg_root, CHASE_PREFIX_ROOT, F_OK, &resolved, NULL);
+                if (r < 0)
+                        return log_error_errno(r, "Cannot access \"%s%s\": %m", strempty(arg_root), filename);
+
+                free_and_replace(filename, resolved);
 
                 if (path && !ENDSWITH_SET(filename, ".xz", ".lz4", ".zst")) {
                         *path = TAKE_PTR(filename);
@@ -1142,6 +1192,10 @@ static int run_debug(int argc, char **argv, void *userdata) {
                 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
                                        "Binary is not an absolute path.");
 
+        r = resolve_filename(exe, arg_root, &exe);
+        if (r < 0)
+                return r;
+
         r = save_core(j, NULL, &path, &unlink_path);
         if (r < 0)
                 return r;
@@ -1150,6 +1204,24 @@ static int run_debug(int argc, char **argv, void *userdata) {
         if (r < 0)
                 return log_oom();
 
+        if (arg_root) {
+                if (streq(arg_debugger, "gdb")) {
+                        const char *sysroot_cmd;
+                        sysroot_cmd = strjoina("set sysroot ", arg_root);
+
+                        r = strv_extend_strv(&debugger_call, STRV_MAKE("-iex", sysroot_cmd), false);
+                        if (r < 0)
+                                return log_oom();
+                } else if (streq(arg_debugger, "lldb")) {
+                        const char *sysroot_cmd;
+                        sysroot_cmd = strjoina("platform select --sysroot ", arg_root, " host");
+
+                        r = strv_extend_strv(&debugger_call, STRV_MAKE("-O", sysroot_cmd), false);
+                        if (r < 0)
+                                return log_oom();
+                }
+        }
+
         /* Don't interfere with gdb and its handling of SIGINT. */
         (void) ignore_signals(SIGINT);