Merge pull request #24595 from rphibel/support-image-option-in-systemctl-and-coredumpctl

systemctl/coredumpctl: add support for --root and --image options
This commit is contained in:
Daan De Meyer
2022-10-10 11:35:20 +02:00
committed by GitHub
2 changed files with 128 additions and 4 deletions

View File

@@ -248,6 +248,26 @@
</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>--image=<replaceable>image</replaceable></option></term>
<listitem><para>Takes a path to a disk image file or block device node. If specified, all operations
are applied to file system in the indicated disk image. This option is similar to
<option>--root=</option>, but operates on file systems stored in disk images or block devices. The
disk image should either contain just a file system or a set of file systems within a GPT partition
table, following the <ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions
Specification</ulink>. For further information on supported disk images, see
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
switch of the same name.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-q</option></term>
<term><option>--quiet</option></term>

View File

@@ -14,8 +14,10 @@
#include "bus-error.h"
#include "bus-locator.h"
#include "bus-util.h"
#include "chase-symlinks.h"
#include "compress.h"
#include "def.h"
#include "dissect-image.h"
#include "fd-util.h"
#include "format-table.h"
#include "fs-util.h"
@@ -25,6 +27,7 @@
#include "log.h"
#include "macro.h"
#include "main-func.h"
#include "mount-util.h"
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
@@ -49,6 +52,8 @@ 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_image = NULL;
static char **arg_file = NULL;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
@@ -121,6 +126,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 +214,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_JSON,
ARG_DEBUGGER,
ARG_FILE,
ARG_ROOT,
ARG_IMAGE,
ARG_ALL,
};
@@ -226,6 +237,8 @@ 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 },
{ "image", required_argument, NULL, ARG_IMAGE },
{ "all", no_argument, NULL, ARG_ALL },
{}
};
@@ -316,6 +329,18 @@ 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 ARG_IMAGE:
r = parse_path_argument(optarg, false, &arg_image);
if (r < 0)
return r;
break;
case 'r':
arg_reverse = true;
break;
@@ -347,6 +372,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_image + !!arg_root) > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root=, --image= or -D/--directory=, the combination of these options is not supported.");
return 1;
}
@@ -467,6 +495,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 +563,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 +753,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 +971,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 +1203,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 +1215,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);
@@ -1252,6 +1335,8 @@ static int coredumpctl_main(int argc, char *argv[]) {
}
static int run(int argc, char *argv[]) {
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
int r, units_active;
setlocale(LC_ALL, "");
@@ -1268,6 +1353,25 @@ static int run(int argc, char *argv[]) {
units_active = check_units_active(); /* error is treated the same as 0 */
if (arg_image) {
assert(!arg_root);
r = mount_image_privately_interactively(
arg_image,
DISSECT_IMAGE_GENERIC_ROOT |
DISSECT_IMAGE_REQUIRE_ROOT |
DISSECT_IMAGE_RELAX_VAR_CHECK |
DISSECT_IMAGE_VALIDATE_OS,
&mounted_dir,
&loop_device);
if (r < 0)
return r;
arg_root = strdup(mounted_dir);
if (!arg_root)
return log_oom();
}
r = coredumpctl_main(argc, argv);
if (units_active > 0)