2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2011-07-09 00:04:27 +02:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
#include "sd-device.h"
|
2015-11-17 06:52:45 +01:00
|
|
|
|
|
|
|
#include "alloc-util.h"
|
2018-08-22 07:59:03 +02:00
|
|
|
#include "device-enumerator-private.h"
|
2015-10-26 23:01:30 +01:00
|
|
|
#include "locale-util.h"
|
2012-05-07 21:36:12 +02:00
|
|
|
#include "path-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
|
|
|
#include "sysfs-show.h"
|
2015-04-10 23:15:59 +02:00
|
|
|
#include "terminal-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "util.h"
|
2011-07-09 00:04:27 +02:00
|
|
|
|
|
|
|
static int show_sysfs_one(
|
|
|
|
const char *seat,
|
2018-08-22 07:59:03 +02:00
|
|
|
sd_device **dev_list,
|
|
|
|
size_t *i_dev,
|
|
|
|
size_t n_dev,
|
2011-07-09 00:04:27 +02:00
|
|
|
const char *sub,
|
|
|
|
const char *prefix,
|
2017-11-10 21:44:29 +01:00
|
|
|
unsigned n_columns,
|
|
|
|
OutputFlags flags) {
|
|
|
|
|
|
|
|
size_t max_width;
|
2018-08-22 07:59:03 +02:00
|
|
|
int r;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
|
|
|
assert(seat);
|
2018-08-22 07:59:03 +02:00
|
|
|
assert(dev_list);
|
|
|
|
assert(i_dev);
|
2011-07-09 00:04:27 +02:00
|
|
|
assert(prefix);
|
|
|
|
|
2017-11-10 21:44:29 +01:00
|
|
|
if (flags & OUTPUT_FULL_WIDTH)
|
|
|
|
max_width = (size_t) -1;
|
|
|
|
else if (n_columns < 10)
|
|
|
|
max_width = 10;
|
|
|
|
else
|
|
|
|
max_width = n_columns;
|
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
while (*i_dev < n_dev) {
|
2018-09-01 16:13:54 +02:00
|
|
|
const char *sysfs, *sn, *name = NULL, *subsystem, *sysname;
|
2013-12-18 17:13:42 +01:00
|
|
|
_cleanup_free_ char *k = NULL, *l = NULL;
|
2018-08-22 07:59:03 +02:00
|
|
|
size_t lookahead;
|
2013-01-25 04:48:34 +01:00
|
|
|
bool is_master;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
if (sd_device_get_syspath(dev_list[*i_dev], &sysfs) < 0 ||
|
|
|
|
!path_startswith(sysfs, sub))
|
2011-07-09 00:04:27 +02:00
|
|
|
return 0;
|
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
if (sd_device_get_property_value(dev_list[*i_dev], "ID_SEAT", &sn) < 0 || isempty(sn))
|
2011-07-09 00:04:27 +02:00
|
|
|
sn = "seat0";
|
|
|
|
|
2013-01-24 05:47:37 +01:00
|
|
|
/* Explicitly also check for tag 'seat' here */
|
2018-09-01 16:13:54 +02:00
|
|
|
if (!streq(seat, sn) ||
|
2018-12-13 18:36:57 +01:00
|
|
|
sd_device_has_current_tag(dev_list[*i_dev], "seat") <= 0 ||
|
2018-09-01 16:13:54 +02:00
|
|
|
sd_device_get_subsystem(dev_list[*i_dev], &subsystem) < 0 ||
|
|
|
|
sd_device_get_sysname(dev_list[*i_dev], &sysname) < 0) {
|
2018-08-22 07:59:03 +02:00
|
|
|
(*i_dev)++;
|
2011-07-09 00:04:27 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-12-13 18:36:57 +01:00
|
|
|
is_master = sd_device_has_current_tag(dev_list[*i_dev], "master-of-seat") > 0;
|
2018-08-22 07:59:03 +02:00
|
|
|
|
|
|
|
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);
|
2013-01-24 05:47:37 +01:00
|
|
|
|
2011-07-09 00:04:27 +02:00
|
|
|
/* Look if there's more coming after this */
|
2018-08-22 07:59:03 +02:00
|
|
|
for (lookahead = *i_dev + 1; lookahead < n_dev; lookahead++) {
|
2011-07-09 00:04:27 +02:00
|
|
|
const char *lookahead_sysfs;
|
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
if (sd_device_get_syspath(dev_list[lookahead], &lookahead_sysfs) < 0)
|
|
|
|
continue;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
|
|
|
if (path_startswith(lookahead_sysfs, sub) &&
|
|
|
|
!path_startswith(lookahead_sysfs, sysfs)) {
|
2018-08-22 07:59:03 +02:00
|
|
|
const char *lookahead_sn;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
if (sd_device_get_property_value(dev_list[lookahead], "ID_SEAT", &lookahead_sn) < 0 ||
|
|
|
|
isempty(lookahead_sn))
|
|
|
|
lookahead_sn = "seat0";
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-12-13 18:36:57 +01:00
|
|
|
if (streq(seat, lookahead_sn) && sd_device_has_current_tag(dev_list[lookahead], "seat") > 0)
|
2018-08-22 07:59:03 +02:00
|
|
|
break;
|
2011-07-09 00:04:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-10 21:44:29 +01:00
|
|
|
k = ellipsize(sysfs, max_width, 20);
|
2013-12-18 17:13:42 +01:00
|
|
|
if (!k)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2018-12-13 22:11:32 +01:00
|
|
|
printf("%s%s%s\n", prefix, special_glyph(lookahead < n_dev ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT), k);
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2011-07-09 02:58:05 +02:00
|
|
|
if (asprintf(&l,
|
2013-01-25 04:48:34 +01:00
|
|
|
"%s%s:%s%s%s%s",
|
|
|
|
is_master ? "[MASTER] " : "",
|
2011-07-09 02:58:05 +02:00
|
|
|
subsystem, sysname,
|
2015-09-25 13:36:54 +02:00
|
|
|
name ? " \"" : "", strempty(name), name ? "\"" : "") < 0)
|
2011-07-09 02:58:05 +02:00
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
free(k);
|
2017-11-10 21:44:29 +01:00
|
|
|
k = ellipsize(l, max_width, 70);
|
2013-12-18 17:13:42 +01:00
|
|
|
if (!k)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2018-12-13 22:11:32 +01:00
|
|
|
printf("%s%s%s\n", prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ", k);
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
if (++(*i_dev) < n_dev) {
|
2013-12-18 17:13:42 +01:00
|
|
|
_cleanup_free_ char *p = NULL;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2019-07-11 19:14:16 +02:00
|
|
|
p = strjoin(prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ");
|
2013-12-18 17:13:42 +01:00
|
|
|
if (!p)
|
|
|
|
return -ENOMEM;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
r = show_sysfs_one(seat, dev_list, i_dev, n_dev, sysfs, p,
|
|
|
|
n_columns == (unsigned) -1 || n_columns < 2 ? n_columns : n_columns - 2,
|
|
|
|
flags);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-12-18 17:13:42 +01:00
|
|
|
}
|
2018-08-22 07:59:03 +02:00
|
|
|
|
2011-07-09 00:04:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-10 21:44:29 +01:00
|
|
|
int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) {
|
2018-08-22 07:59:03 +02:00
|
|
|
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
2018-08-28 09:05:20 +02:00
|
|
|
size_t n_dev = 0, i = 0;
|
|
|
|
sd_device **dev_list;
|
2011-07-09 00:04:27 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
if (n_columns <= 0)
|
|
|
|
n_columns = columns();
|
|
|
|
|
2017-11-10 21:44:29 +01:00
|
|
|
prefix = strempty(prefix);
|
2011-07-09 00:04:27 +02:00
|
|
|
|
|
|
|
if (isempty(seat))
|
|
|
|
seat = "seat0";
|
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
r = sd_device_enumerator_new(&e);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
r = sd_device_enumerator_allow_uninitialized(e);
|
2013-12-18 17:12:15 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
r = sd_device_enumerator_add_match_tag(e, streq(seat, "seat0") ? "seat" : seat);
|
2011-09-23 02:39:54 +02:00
|
|
|
if (r < 0)
|
2013-10-13 02:28:21 +02:00
|
|
|
return r;
|
2011-09-23 02:39:54 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
r = device_enumerator_scan_devices(e);
|
2011-07-09 00:04:27 +02:00
|
|
|
if (r < 0)
|
2013-10-13 02:28:21 +02:00
|
|
|
return r;
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-28 09:05:20 +02:00
|
|
|
dev_list = device_enumerator_get_devices(e, &n_dev);
|
2018-08-22 07:59:03 +02:00
|
|
|
|
2018-08-28 09:05:20 +02:00
|
|
|
if (dev_list && n_dev > 0)
|
2018-08-22 07:59:03 +02:00
|
|
|
show_sysfs_one(seat, dev_list, &i, n_dev, "/", prefix, n_columns, flags);
|
2013-12-18 17:16:33 +01:00
|
|
|
else
|
2018-12-13 22:11:32 +01:00
|
|
|
printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT), "(none)");
|
2011-07-09 00:04:27 +02:00
|
|
|
|
2018-08-22 07:59:03 +02:00
|
|
|
return 0;
|
2011-07-09 00:04:27 +02:00
|
|
|
}
|