blob: 0a8c02a2a26a964c11559e434319761764329c6f [file] [log] [blame]
/* 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 "glyph-util.h"
#include "path-util.h"
#include "string-util.h"
#include "sysfs-show.h"
#include "terminal-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;
}