diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-02-21 10:25:36 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2022-02-21 17:22:23 +0100 |
commit | 08e36480d4ad218a5caf5dd14d2b2fad68d220ff (patch) | |
tree | b7328bb4757f430d802f90d8e0a234b082726a95 | |
parent | analyze: split out calendar verb into own .c/.h file (diff) | |
download | systemd-08e36480d4ad218a5caf5dd14d2b2fad68d220ff.tar.xz systemd-08e36480d4ad218a5caf5dd14d2b2fad68d220ff.zip |
analyze: split out "filesystems" verb into its own .c/.h file pair
-rw-r--r-- | src/analyze/analyze-filesystems.c | 230 | ||||
-rw-r--r-- | src/analyze/analyze-filesystems.h | 4 | ||||
-rw-r--r-- | src/analyze/analyze.c | 225 | ||||
-rw-r--r-- | src/analyze/analyze.h | 3 | ||||
-rw-r--r-- | src/analyze/meson.build | 2 |
5 files changed, 242 insertions, 222 deletions
diff --git a/src/analyze/analyze-filesystems.c b/src/analyze/analyze-filesystems.c new file mode 100644 index 0000000000..bdb64e7823 --- /dev/null +++ b/src/analyze/analyze-filesystems.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "analyze.h" +#include "analyze-filesystems.h" +#include "fileio.h" +#include "filesystems.h" +#include "set.h" +#include "strv.h" +#include "terminal-util.h" + +static int load_available_kernel_filesystems(Set **ret) { + _cleanup_set_free_ Set *filesystems = NULL; + _cleanup_free_ char *t = NULL; + int r; + + assert(ret); + + /* Let's read the available filesystems */ + + r = read_virtual_file("/proc/filesystems", SIZE_MAX, &t, NULL); + if (r < 0) + return r; + + for (int i = 0;;) { + _cleanup_free_ char *line = NULL; + const char *p; + + r = string_extract_line(t, i++, &line); + if (r < 0) + return log_oom(); + if (r == 0) + break; + + if (!line) + line = t; + + p = strchr(line, '\t'); + if (!p) + continue; + + p += strspn(p, WHITESPACE); + + r = set_put_strdup(&filesystems, p); + if (r < 0) + return log_error_errno(r, "Failed to add filesystem to list: %m"); + } + + *ret = TAKE_PTR(filesystems); + return 0; +} + +static void filesystem_set_remove(Set *s, const FilesystemSet *set) { + const char *filesystem; + + NULSTR_FOREACH(filesystem, set->value) { + if (filesystem[0] == '@') + continue; + + free(set_remove(s, filesystem)); + } +} + +static void dump_filesystem_set(const FilesystemSet *set) { + const char *filesystem; + int r; + + if (!set) + return; + + printf("%s%s%s\n" + " # %s\n", + ansi_highlight(), + set->name, + ansi_normal(), + set->help); + + NULSTR_FOREACH(filesystem, set->value) { + const statfs_f_type_t *magic; + + if (filesystem[0] == '@') { + printf(" %s%s%s\n", ansi_underline(), filesystem, ansi_normal()); + continue; + } + + r = fs_type_from_string(filesystem, &magic); + assert_se(r >= 0); + + printf(" %s", filesystem); + + for (size_t i = 0; magic[i] != 0; i++) { + const char *primary; + if (i == 0) + printf(" %s(magic: ", ansi_grey()); + else + printf(", "); + + printf("0x%llx", (unsigned long long) magic[i]); + + primary = fs_type_to_string(magic[i]); + if (primary && !streq(primary, filesystem)) + printf("[%s]", primary); + + if (magic[i+1] == 0) + printf(")%s", ansi_normal()); + } + + printf("\n"); + } +} + +int dump_filesystems(int argc, char *argv[], void *userdata) { + bool first = true; + +#if ! HAVE_LIBBPF + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Not compiled with libbpf support, sorry."); +#endif + + pager_open(arg_pager_flags); + + if (strv_isempty(strv_skip(argv, 1))) { + _cleanup_set_free_ Set *kernel = NULL, *known = NULL; + const char *fs; + int k; + + NULSTR_FOREACH(fs, filesystem_sets[FILESYSTEM_SET_KNOWN].value) + if (set_put_strdup(&known, fs) < 0) + return log_oom(); + + k = load_available_kernel_filesystems(&kernel); + + for (FilesystemGroups i = 0; i < _FILESYSTEM_SET_MAX; i++) { + const FilesystemSet *set = filesystem_sets + i; + if (!first) + puts(""); + + dump_filesystem_set(set); + filesystem_set_remove(kernel, set); + if (i != FILESYSTEM_SET_KNOWN) + filesystem_set_remove(known, set); + first = false; + } + + if (arg_quiet) /* Let's not show the extra stuff in quiet mode */ + return 0; + + if (!set_isempty(known)) { + _cleanup_free_ char **l = NULL; + char **filesystem; + + printf("\n" + "# %sUngrouped filesystems%s (known but not included in any of the groups except @known):\n", + ansi_highlight(), ansi_normal()); + + l = set_get_strv(known); + if (!l) + return log_oom(); + + strv_sort(l); + + STRV_FOREACH(filesystem, l) { + const statfs_f_type_t *magic; + bool is_primary = false; + + assert_se(fs_type_from_string(*filesystem, &magic) >= 0); + + for (size_t i = 0; magic[i] != 0; i++) { + const char *primary; + + primary = fs_type_to_string(magic[i]); + assert(primary); + + if (streq(primary, *filesystem)) + is_primary = true; + } + + if (!is_primary) { + log_debug("Skipping ungrouped file system '%s', because it's an alias for another one.", *filesystem); + continue; + } + + printf("# %s\n", *filesystem); + } + } + + if (k < 0) { + fputc('\n', stdout); + fflush(stdout); + log_notice_errno(k, "# Not showing unlisted filesystems, couldn't retrieve kernel filesystem list: %m"); + } else if (!set_isempty(kernel)) { + _cleanup_free_ char **l = NULL; + char **filesystem; + + printf("\n" + "# %sUnlisted filesystems%s (available to the local kernel, but not included in any of the groups listed above):\n", + ansi_highlight(), ansi_normal()); + + l = set_get_strv(kernel); + if (!l) + return log_oom(); + + strv_sort(l); + + STRV_FOREACH(filesystem, l) + printf("# %s\n", *filesystem); + } + } else { + char **name; + + STRV_FOREACH(name, strv_skip(argv, 1)) { + const FilesystemSet *set; + + if (!first) + puts(""); + + set = filesystem_set_find(*name); + if (!set) { + /* make sure the error appears below normal output */ + fflush(stdout); + + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "Filesystem set \"%s\" not found.", *name); + } + + dump_filesystem_set(set); + first = false; + } + } + + return 0; +} diff --git a/src/analyze/analyze-filesystems.h b/src/analyze/analyze-filesystems.h new file mode 100644 index 0000000000..04606c2ea4 --- /dev/null +++ b/src/analyze/analyze-filesystems.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +int dump_filesystems(int argc, char *argv[], void *userdata); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index a051a48a5d..2af62f48c4 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -16,6 +16,7 @@ #include "analyze-calendar.h" #include "analyze-condition.h" #include "analyze-elf.h" +#include "analyze-filesystems.h" #include "analyze-security.h" #include "analyze-timespan.h" #include "analyze-timestamp.h" @@ -93,7 +94,7 @@ static enum dot { static char **arg_dot_from_patterns = NULL; static char **arg_dot_to_patterns = NULL; static usec_t arg_fuzz = 0; -static PagerFlags arg_pager_flags = 0; +PagerFlags arg_pager_flags = 0; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static const char *arg_host = NULL; static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; @@ -109,7 +110,7 @@ unsigned arg_iterations = 1; usec_t arg_base_time = USEC_INFINITY; static char *arg_unit = NULL; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; -static bool arg_quiet = false; +bool arg_quiet = false; static char *arg_profile = NULL; STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep); @@ -1811,226 +1812,6 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) { } #endif -static int load_available_kernel_filesystems(Set **ret) { - _cleanup_set_free_ Set *filesystems = NULL; - _cleanup_free_ char *t = NULL; - int r; - - assert(ret); - - /* Let's read the available filesystems */ - - r = read_virtual_file("/proc/filesystems", SIZE_MAX, &t, NULL); - if (r < 0) - return r; - - for (int i = 0;;) { - _cleanup_free_ char *line = NULL; - const char *p; - - r = string_extract_line(t, i++, &line); - if (r < 0) - return log_oom(); - if (r == 0) - break; - - if (!line) - line = t; - - p = strchr(line, '\t'); - if (!p) - continue; - - p += strspn(p, WHITESPACE); - - r = set_put_strdup(&filesystems, p); - if (r < 0) - return log_error_errno(r, "Failed to add filesystem to list: %m"); - } - - *ret = TAKE_PTR(filesystems); - return 0; -} - -static void filesystem_set_remove(Set *s, const FilesystemSet *set) { - const char *filesystem; - - NULSTR_FOREACH(filesystem, set->value) { - if (filesystem[0] == '@') - continue; - - free(set_remove(s, filesystem)); - } -} - -static void dump_filesystem_set(const FilesystemSet *set) { - const char *filesystem; - int r; - - if (!set) - return; - - printf("%s%s%s\n" - " # %s\n", - ansi_highlight(), - set->name, - ansi_normal(), - set->help); - - NULSTR_FOREACH(filesystem, set->value) { - const statfs_f_type_t *magic; - - if (filesystem[0] == '@') { - printf(" %s%s%s\n", ansi_underline(), filesystem, ansi_normal()); - continue; - } - - r = fs_type_from_string(filesystem, &magic); - assert_se(r >= 0); - - printf(" %s", filesystem); - - for (size_t i = 0; magic[i] != 0; i++) { - const char *primary; - if (i == 0) - printf(" %s(magic: ", ansi_grey()); - else - printf(", "); - - printf("0x%llx", (unsigned long long) magic[i]); - - primary = fs_type_to_string(magic[i]); - if (primary && !streq(primary, filesystem)) - printf("[%s]", primary); - - if (magic[i+1] == 0) - printf(")%s", ansi_normal()); - } - - printf("\n"); - } -} - -static int dump_filesystems(int argc, char *argv[], void *userdata) { - bool first = true; - -#if ! HAVE_LIBBPF - return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Not compiled with libbpf support, sorry."); -#endif - - pager_open(arg_pager_flags); - - if (strv_isempty(strv_skip(argv, 1))) { - _cleanup_set_free_ Set *kernel = NULL, *known = NULL; - const char *fs; - int k; - - NULSTR_FOREACH(fs, filesystem_sets[FILESYSTEM_SET_KNOWN].value) - if (set_put_strdup(&known, fs) < 0) - return log_oom(); - - k = load_available_kernel_filesystems(&kernel); - - for (FilesystemGroups i = 0; i < _FILESYSTEM_SET_MAX; i++) { - const FilesystemSet *set = filesystem_sets + i; - if (!first) - puts(""); - - dump_filesystem_set(set); - filesystem_set_remove(kernel, set); - if (i != FILESYSTEM_SET_KNOWN) - filesystem_set_remove(known, set); - first = false; - } - - if (arg_quiet) /* Let's not show the extra stuff in quiet mode */ - return 0; - - if (!set_isempty(known)) { - _cleanup_free_ char **l = NULL; - char **filesystem; - - printf("\n" - "# %sUngrouped filesystems%s (known but not included in any of the groups except @known):\n", - ansi_highlight(), ansi_normal()); - - l = set_get_strv(known); - if (!l) - return log_oom(); - - strv_sort(l); - - STRV_FOREACH(filesystem, l) { - const statfs_f_type_t *magic; - bool is_primary = false; - - assert_se(fs_type_from_string(*filesystem, &magic) >= 0); - - for (size_t i = 0; magic[i] != 0; i++) { - const char *primary; - - primary = fs_type_to_string(magic[i]); - assert(primary); - - if (streq(primary, *filesystem)) - is_primary = true; - } - - if (!is_primary) { - log_debug("Skipping ungrouped file system '%s', because it's an alias for another one.", *filesystem); - continue; - } - - printf("# %s\n", *filesystem); - } - } - - if (k < 0) { - fputc('\n', stdout); - fflush(stdout); - log_notice_errno(k, "# Not showing unlisted filesystems, couldn't retrieve kernel filesystem list: %m"); - } else if (!set_isempty(kernel)) { - _cleanup_free_ char **l = NULL; - char **filesystem; - - printf("\n" - "# %sUnlisted filesystems%s (available to the local kernel, but not included in any of the groups listed above):\n", - ansi_highlight(), ansi_normal()); - - l = set_get_strv(kernel); - if (!l) - return log_oom(); - - strv_sort(l); - - STRV_FOREACH(filesystem, l) - printf("# %s\n", *filesystem); - } - } else { - char **name; - - STRV_FOREACH(name, strv_skip(argv, 1)) { - const FilesystemSet *set; - - if (!first) - puts(""); - - set = filesystem_set_find(*name); - if (!set) { - /* make sure the error appears below normal output */ - fflush(stdout); - - return log_error_errno(SYNTHETIC_ERRNO(ENOENT), - "Filesystem set \"%s\" not found.", *name); - } - - dump_filesystem_set(set); - first = false; - } - } - - return 0; -} void time_parsing_hint(const char *p, bool calendar, bool timestamp, bool timespan) { if (calendar && calendar_spec_from_string(p, NULL) >= 0) diff --git a/src/analyze/analyze.h b/src/analyze/analyze.h index ff4e7b4acd..062314a389 100644 --- a/src/analyze/analyze.h +++ b/src/analyze/analyze.h @@ -3,9 +3,12 @@ #include <stdbool.h> +#include "pager.h" #include "time-util.h" +extern PagerFlags arg_pager_flags; extern unsigned arg_iterations; extern usec_t arg_base_time; +extern bool arg_quiet; void time_parsing_hint(const char *p, bool calendar, bool timestamp, bool timespan); diff --git a/src/analyze/meson.build b/src/analyze/meson.build index 287a43c319..f5950c1feb 100644 --- a/src/analyze/meson.build +++ b/src/analyze/meson.build @@ -7,6 +7,8 @@ systemd_analyze_sources = files(''' analyze-condition.h analyze-elf.c analyze-elf.h + analyze-filesystems.c + analyze-filesystems.h analyze-security.c analyze-security.h analyze-timespan.c |