| /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
| |
| #include <errno.h> |
| |
| #include "sd-device.h" |
| |
| #include "alloc-util.h" |
| #include "device-enumerator-private.h" |
| #include "locale-util.h" |
| #include "path-util.h" |
| #include "string-util.h" |
| #include "sysfs-show.h" |
| #include "terminal-util.h" |
| #include "util.h" |
| |
| static int show_sysfs_one( |
| const char *seat, |
| sd_device **dev_list, |
| size_t *i_dev, |
| size_t n_dev, |
| const char *sub, |
| const char *prefix, |
| unsigned n_columns, |
| OutputFlags flags) { |
| |
| size_t max_width; |
| int r; |
| |
| assert(seat); |
| assert(dev_list); |
| assert(i_dev); |
| assert(prefix); |
| |
| if (flags & OUTPUT_FULL_WIDTH) |
| max_width = SIZE_MAX; |
| else if (n_columns < 10) |
| max_width = 10; |
| else |
| max_width = n_columns; |
| |
| while (*i_dev < n_dev) { |
| const char *sysfs, *sn, *name = NULL, *subsystem, *sysname; |
| _cleanup_free_ char *k = NULL, *l = NULL; |
| size_t lookahead; |
| bool is_master; |
| |
| if (sd_device_get_syspath(dev_list[*i_dev], &sysfs) < 0 || |
| !path_startswith(sysfs, sub)) |
| return 0; |
| |
| if (sd_device_get_property_value(dev_list[*i_dev], "ID_SEAT", &sn) < 0 || isempty(sn)) |
| sn = "seat0"; |
| |
| /* Explicitly also check for tag 'seat' here */ |
| if (!streq(seat, sn) || |
| sd_device_has_current_tag(dev_list[*i_dev], "seat") <= 0 || |
| sd_device_get_subsystem(dev_list[*i_dev], &subsystem) < 0 || |
| sd_device_get_sysname(dev_list[*i_dev], &sysname) < 0) { |
| (*i_dev)++; |
| continue; |
| } |
| |
| is_master = sd_device_has_current_tag(dev_list[*i_dev], "master-of-seat") > 0; |
| |
| if (sd_device_get_sysattr_value(dev_list[*i_dev], "name", &name) < 0) |
| (void) sd_device_get_sysattr_value(dev_list[*i_dev], "id", &name); |
| |
| /* Look if there's more coming after this */ |
| for (lookahead = *i_dev + 1; lookahead < n_dev; lookahead++) { |
| const char *lookahead_sysfs; |
| |
| if (sd_device_get_syspath(dev_list[lookahead], &lookahead_sysfs) < 0) |
| continue; |
| |
| if (path_startswith(lookahead_sysfs, sub) && |
| !path_startswith(lookahead_sysfs, sysfs)) { |
| const char *lookahead_sn; |
| |
| if (sd_device_get_property_value(dev_list[lookahead], "ID_SEAT", &lookahead_sn) < 0 || |
| isempty(lookahead_sn)) |
| lookahead_sn = "seat0"; |
| |
| if (streq(seat, lookahead_sn) && sd_device_has_current_tag(dev_list[lookahead], "seat") > 0) |
| break; |
| } |
| } |
| |
| k = ellipsize(sysfs, max_width, 20); |
| if (!k) |
| return -ENOMEM; |
| |
| printf("%s%s%s\n", prefix, special_glyph(lookahead < n_dev ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT), k); |
| |
| if (asprintf(&l, |
| "%s%s:%s%s%s%s", |
| is_master ? "[MASTER] " : "", |
| subsystem, sysname, |
| name ? " \"" : "", strempty(name), name ? "\"" : "") < 0) |
| return -ENOMEM; |
| |
| free(k); |
| k = ellipsize(l, max_width, 70); |
| if (!k) |
| return -ENOMEM; |
| |
| printf("%s%s%s\n", prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ", k); |
| |
| if (++(*i_dev) < n_dev) { |
| _cleanup_free_ char *p = NULL; |
| |
| p = strjoin(prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " "); |
| if (!p) |
| return -ENOMEM; |
| |
| r = show_sysfs_one(seat, dev_list, i_dev, n_dev, sysfs, p, |
| n_columns == UINT_MAX || n_columns < 2 ? n_columns : n_columns - 2, |
| flags); |
| if (r < 0) |
| return r; |
| } |
| |
| } |
| |
| return 0; |
| } |
| |
| int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) { |
| _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; |
| size_t n_dev = 0, i = 0; |
| sd_device **dev_list; |
| int r; |
| |
| if (n_columns <= 0) |
| n_columns = columns(); |
| |
| prefix = strempty(prefix); |
| |
| if (isempty(seat)) |
| seat = "seat0"; |
| |
| r = sd_device_enumerator_new(&e); |
| if (r < 0) |
| return r; |
| |
| r = sd_device_enumerator_allow_uninitialized(e); |
| if (r < 0) |
| return r; |
| |
| r = sd_device_enumerator_add_match_tag(e, streq(seat, "seat0") ? "seat" : seat); |
| if (r < 0) |
| return r; |
| |
| r = device_enumerator_scan_devices(e); |
| if (r < 0) |
| return r; |
| |
| dev_list = device_enumerator_get_devices(e, &n_dev); |
| |
| if (dev_list && n_dev > 0) |
| show_sysfs_one(seat, dev_list, &i, n_dev, "/", prefix, n_columns, flags); |
| else |
| printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT), "(none)"); |
| |
| return 0; |
| } |