/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ #include <errno.h> #include <string.h> #include <libudev.h> #include "util.h" #include "sysfs-show.h" static int show_sysfs_one( struct udev *udev, const char *seat, struct udev_list_entry **item, const char *sub, const char *prefix, unsigned n_columns) { assert(udev); assert(seat); assert(item); assert(prefix); while (*item) { struct udev_list_entry *next, *lookahead; struct udev_device *d; const char *sn, *name, *sysfs, *subsystem, *sysname; char *l, *k; sysfs = udev_list_entry_get_name(*item); if (!path_startswith(sysfs, sub)) return 0; d = udev_device_new_from_syspath(udev, sysfs); if (!d) { *item = udev_list_entry_get_next(*item); continue; } sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(sn)) sn = "seat0"; /* fixme, also check for tag 'seat' here */ if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) { udev_device_unref(d); *item = udev_list_entry_get_next(*item); continue; } name = udev_device_get_sysattr_value(d, "name"); if (!name) name = udev_device_get_sysattr_value(d, "id"); subsystem = udev_device_get_subsystem(d); sysname = udev_device_get_sysname(d); /* Look if there's more coming after this */ lookahead = next = udev_list_entry_get_next(*item); while (lookahead) { const char *lookahead_sysfs; lookahead_sysfs = udev_list_entry_get_name(lookahead); if (path_startswith(lookahead_sysfs, sub) && !path_startswith(lookahead_sysfs, sysfs)) { struct udev_device *lookahead_d; lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs); if (lookahead_d) { const char *lookahead_sn; bool found; lookahead_sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(lookahead_sn)) lookahead_sn = "seat0"; found = streq(seat, lookahead_sn) && udev_device_has_tag(lookahead_d, "seat"); udev_device_unref(lookahead_d); if (found) break; } } lookahead = udev_list_entry_get_next(lookahead); } k = ellipsize(sysfs, n_columns, 20); printf("%s%s %s\n", prefix, lookahead ? "\342\224\234" : "\342\224\224", k ? k : sysfs); free(k); if (asprintf(&l, "(%s:%s)%s%s%s", subsystem, sysname, name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) { udev_device_unref(d); return -ENOMEM; } k = ellipsize(l, n_columns, 70); printf("%s%s %s\n", prefix, lookahead ? "\342\224\202" : " ", k ? k : l); free(k); free(l); *item = next; if (*item) { char *p; p = strappend(prefix, lookahead ? "\342\224\202 " : " "); show_sysfs_one(udev, seat, item, sysfs, p ? p : prefix, n_columns - 2); free(p); } udev_device_unref(d); } return 0; } int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) { struct udev *udev; struct udev_list_entry *first = NULL; struct udev_enumerate *e; int r; if (n_columns <= 0) n_columns = columns(); if (!prefix) prefix = ""; if (isempty(seat)) seat = "seat0"; udev = udev_new(); if (!udev) return -ENOMEM; e = udev_enumerate_new(udev); if (!e) { r = -ENOMEM; goto finish; } if (!streq(seat, "seat0")) r = udev_enumerate_add_match_tag(e, seat); else r = udev_enumerate_add_match_tag(e, "seat"); r = udev_enumerate_scan_devices(e); if (r < 0) goto finish; first = udev_enumerate_get_list_entry(e); if (first) show_sysfs_one(udev, seat, &first, "/", prefix, n_columns); finish: if (e) udev_enumerate_unref(e); if (udev) udev_unref(udev); return r; }