diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index 65f77e4cc9..cbcf2a4be2 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -6,6 +6,7 @@ #include #include "alloc-util.h" +#include "chase.h" #include "color-util.h" #include "conf-files.h" #include "constants.h" @@ -13,6 +14,7 @@ #include "errno-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "log.h" #include "path-util.h" #include "pretty-print.h" @@ -184,12 +186,15 @@ int terminal_urlify_man(const char *page, const char *section, char **ret) { return terminal_urlify(url, text, ret); } -static int cat_file(const char *filename, bool *newline, CatFlags flags) { +static int cat_file(const ConfFile *c, bool *newline, CatFlags flags) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *urlified = NULL, *section = NULL, *old_section = NULL; int r; - assert(filename); + assert(c); + assert(c->original_path); + assert(c->resolved_path); + assert(c->fd >= 0); if (newline) { if (*newline) @@ -197,25 +202,29 @@ static int cat_file(const char *filename, bool *newline, CatFlags flags) { *newline = true; } - r = terminal_urlify_path(filename, NULL, &urlified); - if (r < 0) - return log_error_errno(r, "Failed to urlify path \"%s\": %m", filename); + bool resolved = !path_equal(c->original_path, c->resolved_path); - printf("%s# %s%s\n", + r = terminal_urlify_path(c->resolved_path, NULL, &urlified); + if (r < 0) + return log_error_errno(r, "Failed to urlify path \"%s\": %m", c->resolved_path); + + printf("%s# %s%s%s%s\n", ansi_highlight_blue(), + resolved ? c->original_path : "", + resolved ? " -> " : "", urlified, ansi_normal()); - f = fopen(filename, "re"); + f = fopen(FORMAT_PROC_FD_PATH(c->fd), "re"); if (!f) - return log_error_errno(errno, "Failed to open \"%s\": %m", filename); + return log_error_errno(errno, "Failed to open \"%s\": %m", c->resolved_path); for (bool continued = false;;) { _cleanup_free_ char *line = NULL; r = read_line(f, LONG_LINE_MAX, &line); if (r < 0) - return log_error_errno(r, "Failed to read \"%s\": %m", filename); + return log_error_errno(r, "Failed to read \"%s\": %m", c->resolved_path); if (r == 0) break; @@ -296,15 +305,43 @@ static int cat_file(const char *filename, bool *newline, CatFlags flags) { return 0; } +int cat_files_full(const ConfFile *file, ConfFile * const *dropins, size_t n_dropins, CatFlags flags) { + bool newline = false; + int ret = 0; + + assert(dropins || n_dropins == 0); + + if (file) + ret = cat_file(file, &newline, flags); + + FOREACH_ARRAY(i, dropins, n_dropins) + RET_GATHER(ret, cat_file(*i, &newline, flags)); + + return ret; +} + +static int cat_file_by_path(const char *p, bool *newline, CatFlags flags) { + _cleanup_(conf_file_freep) ConfFile *c = NULL; + int r; + + assert(p); + + r = conf_file_new(p, /* root = */ NULL, CHASE_MUST_BE_REGULAR, &c); + if (r < 0) + return log_error_errno(r, "Failed to chase '%s': %m", p); + + return cat_file(c, newline, flags); +} + int cat_files(const char *file, char **dropins, CatFlags flags) { bool newline = false; int ret = 0; if (file) - ret = cat_file(file, &newline, flags); + ret = cat_file_by_path(file, &newline, flags); STRV_FOREACH(path, dropins) - RET_GATHER(ret, cat_file(*path, &newline, flags)); + RET_GATHER(ret, cat_file_by_path(*path, &newline, flags)); return ret; } @@ -384,8 +421,7 @@ static int guess_type(const char **name, char ***ret_prefixes, bool *ret_is_coll } int conf_files_cat(const char *root, const char *name, CatFlags flags) { - _cleanup_strv_free_ char **dirs = NULL, **files = NULL; - _cleanup_free_ char *path = NULL; + _cleanup_strv_free_ char **dirs = NULL; char **prefixes = NULL; /* explicit initialization to appease gcc */ bool is_collection; const char *extension; @@ -416,17 +452,18 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) { } /* First locate the main config file, if any */ + _cleanup_(conf_file_freep) ConfFile *c = NULL; if (!is_collection) { STRV_FOREACH(prefix, prefixes) { - path = path_join(root, *prefix, name); - if (!path) + _cleanup_free_ char *p = path_join(*prefix, name); + if (!p) return log_oom(); - if (access(path, F_OK) == 0) + + if (conf_file_new(p, root, CHASE_MUST_BE_REGULAR, &c) >= 0) break; - path = mfree(path); } - if (!path) + if (!c) printf("%s# Main configuration file %s not found%s\n", ansi_highlight_magenta(), name, @@ -434,7 +471,10 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) { } /* Then locate the drop-ins, if any */ - r = conf_files_list_strv(&files, extension, root, 0, (const char* const*) dirs); + ConfFile **dropins = NULL; + size_t n_dropins = 0; + CLEANUP_ARRAY(dropins, n_dropins, conf_file_free_many); + r = conf_files_list_strv_full(extension, root, CONF_FILES_REGULAR | CONF_FILES_FILTER_MASKED, (const char* const*) dirs, &dropins, &n_dropins); if (r < 0) return log_error_errno(r, "Failed to query file list: %m"); @@ -442,7 +482,7 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) { if (is_collection) flags |= CAT_FORMAT_HAS_SECTIONS; - return cat_files(path, files, flags); + return cat_files_full(c, dropins, n_dropins, flags); } int terminal_tint_color(double hue, char **ret) { diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h index fc0ba5355f..56491886fa 100644 --- a/src/shared/pretty-print.h +++ b/src/shared/pretty-print.h @@ -30,6 +30,7 @@ typedef enum CatFlags { CAT_TLDR = 1 << 2, /* Only print comments and relevant section headers */ } CatFlags; +int cat_files_full(const ConfFile *file, ConfFile * const *dropins, size_t n_dropins, CatFlags flags); int cat_files(const char *file, char **dropins, CatFlags flags); int conf_files_cat(const char *root, const char *name, CatFlags flags); diff --git a/test/units/TEST-65-ANALYZE.sh b/test/units/TEST-65-ANALYZE.sh index 7fd4543e76..5a5a9ba206 100755 --- a/test/units/TEST-65-ANALYZE.sh +++ b/test/units/TEST-65-ANALYZE.sh @@ -313,6 +313,7 @@ if [[ ! -v ASAN_OPTIONS ]]; then # check that systemd-analyze cat-config paths work in a chroot mkdir -p /tmp/root mount --bind / /tmp/root + mount -t proc proc /tmp/root/proc if mountpoint -q /usr; then mount --bind /usr /tmp/root/usr fi