Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <string.h>
5 : :
6 : : #include "sd-device.h"
7 : :
8 : : #include "alloc-util.h"
9 : : #include "device-enumerator-private.h"
10 : : #include "locale-util.h"
11 : : #include "path-util.h"
12 : : #include "string-util.h"
13 : : #include "sysfs-show.h"
14 : : #include "terminal-util.h"
15 : : #include "util.h"
16 : :
17 : 0 : static int show_sysfs_one(
18 : : const char *seat,
19 : : sd_device **dev_list,
20 : : size_t *i_dev,
21 : : size_t n_dev,
22 : : const char *sub,
23 : : const char *prefix,
24 : : unsigned n_columns,
25 : : OutputFlags flags) {
26 : :
27 : : size_t max_width;
28 : : int r;
29 : :
30 [ # # ]: 0 : assert(seat);
31 [ # # ]: 0 : assert(dev_list);
32 [ # # ]: 0 : assert(i_dev);
33 [ # # ]: 0 : assert(prefix);
34 : :
35 [ # # ]: 0 : if (flags & OUTPUT_FULL_WIDTH)
36 : 0 : max_width = (size_t) -1;
37 [ # # ]: 0 : else if (n_columns < 10)
38 : 0 : max_width = 10;
39 : : else
40 : 0 : max_width = n_columns;
41 : :
42 [ # # ]: 0 : while (*i_dev < n_dev) {
43 : 0 : const char *sysfs, *sn, *name = NULL, *subsystem, *sysname;
44 [ # # # # : 0 : _cleanup_free_ char *k = NULL, *l = NULL;
# # ]
45 : : size_t lookahead;
46 : : bool is_master;
47 : :
48 [ # # ]: 0 : if (sd_device_get_syspath(dev_list[*i_dev], &sysfs) < 0 ||
49 [ # # ]: 0 : !path_startswith(sysfs, sub))
50 : 0 : return 0;
51 : :
52 [ # # # # ]: 0 : if (sd_device_get_property_value(dev_list[*i_dev], "ID_SEAT", &sn) < 0 || isempty(sn))
53 : 0 : sn = "seat0";
54 : :
55 : : /* Explicitly also check for tag 'seat' here */
56 [ # # # # ]: 0 : if (!streq(seat, sn) ||
57 [ # # ]: 0 : sd_device_has_tag(dev_list[*i_dev], "seat") <= 0 ||
58 [ # # ]: 0 : sd_device_get_subsystem(dev_list[*i_dev], &subsystem) < 0 ||
59 : 0 : sd_device_get_sysname(dev_list[*i_dev], &sysname) < 0) {
60 : 0 : (*i_dev)++;
61 : 0 : continue;
62 : : }
63 : :
64 : 0 : is_master = sd_device_has_tag(dev_list[*i_dev], "master-of-seat") > 0;
65 : :
66 [ # # ]: 0 : if (sd_device_get_sysattr_value(dev_list[*i_dev], "name", &name) < 0)
67 : 0 : (void) sd_device_get_sysattr_value(dev_list[*i_dev], "id", &name);
68 : :
69 : : /* Look if there's more coming after this */
70 [ # # ]: 0 : for (lookahead = *i_dev + 1; lookahead < n_dev; lookahead++) {
71 : : const char *lookahead_sysfs;
72 : :
73 [ # # ]: 0 : if (sd_device_get_syspath(dev_list[lookahead], &lookahead_sysfs) < 0)
74 : 0 : continue;
75 : :
76 [ # # ]: 0 : if (path_startswith(lookahead_sysfs, sub) &&
77 [ # # ]: 0 : !path_startswith(lookahead_sysfs, sysfs)) {
78 : : const char *lookahead_sn;
79 : :
80 [ # # # # ]: 0 : if (sd_device_get_property_value(dev_list[lookahead], "ID_SEAT", &lookahead_sn) < 0 ||
81 : 0 : isempty(lookahead_sn))
82 : 0 : lookahead_sn = "seat0";
83 : :
84 [ # # # # ]: 0 : if (streq(seat, lookahead_sn) && sd_device_has_tag(dev_list[lookahead], "seat") > 0)
85 : 0 : break;
86 : : }
87 : : }
88 : :
89 : 0 : k = ellipsize(sysfs, max_width, 20);
90 [ # # ]: 0 : if (!k)
91 : 0 : return -ENOMEM;
92 : :
93 [ # # ]: 0 : printf("%s%s%s\n", prefix, special_glyph(lookahead < n_dev ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT), k);
94 : :
95 [ # # # # ]: 0 : if (asprintf(&l,
96 : : "%s%s:%s%s%s%s",
97 : : is_master ? "[MASTER] " : "",
98 : : subsystem, sysname,
99 [ # # # # ]: 0 : name ? " \"" : "", strempty(name), name ? "\"" : "") < 0)
100 : 0 : return -ENOMEM;
101 : :
102 : 0 : free(k);
103 : 0 : k = ellipsize(l, max_width, 70);
104 [ # # ]: 0 : if (!k)
105 : 0 : return -ENOMEM;
106 : :
107 [ # # ]: 0 : printf("%s%s%s\n", prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ", k);
108 : :
109 [ # # ]: 0 : if (++(*i_dev) < n_dev) {
110 [ # # ]: 0 : _cleanup_free_ char *p = NULL;
111 : :
112 [ # # ]: 0 : p = strjoin(prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ");
113 [ # # ]: 0 : if (!p)
114 : 0 : return -ENOMEM;
115 : :
116 [ # # ]: 0 : r = show_sysfs_one(seat, dev_list, i_dev, n_dev, sysfs, p,
117 [ # # ]: 0 : n_columns == (unsigned) -1 || n_columns < 2 ? n_columns : n_columns - 2,
118 : : flags);
119 [ # # ]: 0 : if (r < 0)
120 : 0 : return r;
121 : : }
122 : :
123 : : }
124 : :
125 : 0 : return 0;
126 : : }
127 : :
128 : 0 : int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) {
129 : 0 : _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
130 : 0 : size_t n_dev = 0, i = 0;
131 : : sd_device **dev_list;
132 : : int r;
133 : :
134 [ # # ]: 0 : if (n_columns <= 0)
135 : 0 : n_columns = columns();
136 : :
137 : 0 : prefix = strempty(prefix);
138 : :
139 [ # # ]: 0 : if (isempty(seat))
140 : 0 : seat = "seat0";
141 : :
142 : 0 : r = sd_device_enumerator_new(&e);
143 [ # # ]: 0 : if (r < 0)
144 : 0 : return r;
145 : :
146 : 0 : r = sd_device_enumerator_allow_uninitialized(e);
147 [ # # ]: 0 : if (r < 0)
148 : 0 : return r;
149 : :
150 [ # # ]: 0 : r = sd_device_enumerator_add_match_tag(e, streq(seat, "seat0") ? "seat" : seat);
151 [ # # ]: 0 : if (r < 0)
152 : 0 : return r;
153 : :
154 : 0 : r = device_enumerator_scan_devices(e);
155 [ # # ]: 0 : if (r < 0)
156 : 0 : return r;
157 : :
158 : 0 : dev_list = device_enumerator_get_devices(e, &n_dev);
159 : :
160 [ # # # # ]: 0 : if (dev_list && n_dev > 0)
161 : 0 : show_sysfs_one(seat, dev_list, &i, n_dev, "/", prefix, n_columns, flags);
162 : : else
163 : 0 : printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT), "(none)");
164 : :
165 : 0 : return 0;
166 : : }
|