From 32fe4284c6bf591b3770cb3971d8f9279da2f12b Mon Sep 17 00:00:00 2001 From: Nolan Lum Date: Tue, 7 Dec 2010 06:03:30 +0000 Subject: [PATCH] devattr - a tool to expose the libdevattr functionality --- sbin/Makefile | 1 + sbin/devattr/Makefile | 7 ++ sbin/devattr/devattr.8 | 121 ++++++++++++++++++++ sbin/devattr/devattr.c | 249 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 378 insertions(+) create mode 100644 sbin/devattr/Makefile create mode 100644 sbin/devattr/devattr.8 create mode 100644 sbin/devattr/devattr.c diff --git a/sbin/Makefile b/sbin/Makefile index b6ba284937..0b9f004021 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -13,6 +13,7 @@ SUBDIR= adjkerntz \ clri \ comcontrol \ cryptdisks \ + devattr \ devd \ devfsctl \ dhclient \ diff --git a/sbin/devattr/Makefile b/sbin/devattr/Makefile new file mode 100644 index 0000000000..897aee4d59 --- /dev/null +++ b/sbin/devattr/Makefile @@ -0,0 +1,7 @@ +PROG= devattr +MAN= devattr.8 +WARNS?= 6 + +LDADD= -ldevattr -lprop + +.include diff --git a/sbin/devattr/devattr.8 b/sbin/devattr/devattr.8 new file mode 100644 index 0000000000..2c372b77f7 --- /dev/null +++ b/sbin/devattr/devattr.8 @@ -0,0 +1,121 @@ +.\" +.\" Copyright (c) 2010 The DragonFly Project. All rights reserved. +.\" +.\" This code is derived from software contributed to The DragonFly Project +.\" by Nolan Lum +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" 3. Neither the name of The DragonFly Project nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific, prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, +.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.Dd December 6, 2010 +.Os +.Dt DEVATTR 8 +.Sh NAME +.Nm devattr +.Nd tool for displaying devices and their associated properties +.Sh SYNOPSIS +.Nm +.Op Fl Ah +.Op Fl p Ar property +.Op Fl d Ar device +.Op Fl m Ar key:value +.Op Fl r Ar key:value +.Sh DESCRIPTION +The +.Nm +tool is for displaying a list of devices and some +associated properties such as their name. This tool exposes the +same functionality provided by the +.Xr devattr 3 +library, namely the filtering capabilites offered. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl A +Excludes aliases from the listing. +.\" +.It Fl h +Displays a help message. +.\" +.It Fl p +Only display property +.Fl p . +This can be can be specified multiple times and combined +with all other options. +.\" +.It Fl d +Only display devices with name +.Fl d . +When used with +.Fl p , +only properties +.Fl p +of device +.Fl d +are listed. Can be specified multiple times. Allows wildcards. +.\" +.It Fl m +Only display devices whose property +.I key +matches with wildcards value +.I value +unless the key\-value pair starts with ~, in which case +the match is inverted. Stacks with +.Fl p , +.Fl d , +.Fl m . +Can be specified multiple times. +.\" +.It Fl r +Behaves similarly to +.Fl m , +but matches with regex. +.Sh EXAMPLES +List all devices named 'pts/0'. +.Bd -ragged -offset indent +.Nm Fl d +pts/0 +.Ed +.Pp +List all devices whose major number is 64. +.Bd -ragged -offset indent +.Nm Fl m +major:64 +.Ed +.Pp +List all devices whose name is 'pts/0' and major number is not 64. +.Bd -ragged -offset indent +.Nm Fl d +pts/0 +.Fl m +~major:64 +.Ed +.Sh SEE ALSO +.Xr devattr 3 , +.Xr udevd 8 +.Sh AUTHORS +.An Nolan Lum + diff --git a/sbin/devattr/devattr.c b/sbin/devattr/devattr.c new file mode 100644 index 0000000000..78982f9c6d --- /dev/null +++ b/sbin/devattr/devattr.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2010 + * The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Nolan Lum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static SLIST_HEAD(, sl_entry) props = SLIST_HEAD_INITIALIZER(props); +struct sl_entry { + char *val; + SLIST_ENTRY(sl_entry) entries; +} *ent; + +static void +usage(const char* name) { + fprintf(stderr, "Usage: %s [-Ah] [-p property] [-d device] [-m key:value] [-r key:value]\n" + "Valid options are:\n" + " -A\n" + " Don't display aliases.\n" + " -h\n" + " Print this help message.\n\n" + + "Valid options with their arguments are:\n" + " -p \n" + " Only display property; can be specified multiple times and\n" + " combined with all other options.\n" + " -d \n" + " Only display devices with name `device'. When used with\n" + " -p, only properties `-p' of device `-d' are listed. Can be\n" + " specified multiple times. Allows wildcards.\n" + " -m \n" + " Only display devices whose property `key' matches with wildcards\n" + " value `value' unless the key-value pair starts with ~, in which\n" + " case the match is inverted. Stacks with -p, -d, and -m.\n" + " Can be specified multiple times.\n" + " -r \n" + " Behaves similarly to `-m', but matches with regex.\n" + , name); +} + +static int +parse_args(int argc, char* argv[], struct udev_enumerate *enumerate) { + int ch, invert; + char *colon; + + SLIST_INIT(&props); + + /* A = no aliases */ + /* p = properties to list (defaults to all) */ + /* d = devices to list (defaults to all) */ + /* m = display only devices in d that match these prop values */ + /* r = display only devices in d that match these prop values (regex) */ + while ((ch = getopt(argc, argv, "Ap:d:m:r:h")) != -1) { + invert = false; + + switch (ch) { + case 'A': + udev_enumerate_add_match_property(enumerate, "alias", "0"); + break; + case 'p': + ent = malloc(sizeof(struct sl_entry)); + ent->val = optarg; + SLIST_INSERT_HEAD(&props, ent, entries); + break; + case 'd': + udev_enumerate_add_match_expr(enumerate, "name", optarg); + break; + case 'm': + case 'r': + /* Check for exclusion. */ + invert = *optarg == '~'; + + /* Split into key/value. */ + colon = strchr(optarg, ':'); + if (colon == NULL) { + fprintf(stderr, + "Invalid property key/value pair `%s'.\n", + optarg); + return (0); + } + + *colon = '\0'; + if (invert) { + if (ch == 'r') + udev_enumerate_add_nomatch_regex(enumerate, + optarg + 1, colon + 1); + else + udev_enumerate_add_nomatch_expr(enumerate, + optarg + 1, colon + 1); + } else { + if (ch == 'r') + udev_enumerate_add_match_regex(enumerate, + optarg, colon + 1); + else + udev_enumerate_add_match_expr(enumerate, + optarg, colon + 1); + } + break; + case 'h': + usage(argv[0]); + return (-1); + case '?': + usage(argv[0]); + return (-1); + } + } + return (0); +} + +static void +print_prop(const char* key, prop_object_t value) { + char *val_str; + + printf("\t%s = ", key); + + prop_type_t val_type = prop_object_type(value); + switch (val_type) { + case PROP_TYPE_BOOL: + printf("%s\n", prop_bool_true((prop_bool_t) value) ? "true" : "false"); + break; + case PROP_TYPE_NUMBER: + if (prop_number_unsigned((prop_number_t) value)) + printf("%1$"PRIu64" (0x%1$"PRIx64")\n", + prop_number_unsigned_integer_value((prop_number_t) value)); + else + printf("%"PRId64"\n", + prop_number_integer_value((prop_number_t) value)); + break; + case PROP_TYPE_STRING: + val_str = prop_string_cstring(value); + printf("%s\n", val_str); + free(val_str); + break; + default: + break; + } +} + +int +main(int argc, char* argv[]) { + struct udev *ctx; + struct udev_enumerate *enumerate; + struct udev_list_entry *current; + struct udev_device *dev; + prop_object_t key_val; + prop_dictionary_t dict; + prop_dictionary_keysym_t cur_key; + prop_object_iterator_t iter; + const char *key_str; + char *dev_name; + int ret; + + ctx = udev_new(); + if (ctx == NULL) + err(EX_UNAVAILABLE, "udev_new"); + + enumerate = udev_enumerate_new(ctx); + if (enumerate == NULL) + err(EX_UNAVAILABLE, "udev_enumerate_new"); + + ret = parse_args(argc, argv, enumerate); + if (ret != 0) + return (EX_USAGE); + + ret = udev_enumerate_scan_devices(enumerate); + if (ret != 0) + err(EX_UNAVAILABLE, "udev_enumerate_scan_devices ret = %d", ret); + + current = udev_enumerate_get_list_entry(enumerate); + if (current == NULL) { + printf("No devices found.\n"); + } else { + udev_list_entry_foreach (current, current) { + dev = udev_list_entry_get_device(current); + if (dev == NULL) + continue; + dict = udev_device_get_dictionary(dev); + if (dict == NULL) + continue; + iter = prop_dictionary_iterator(dict); + cur_key = NULL; + + dev_name = prop_string_cstring(prop_dictionary_get(dict, "name")); + printf("Device %s:\n", dev_name); + free(dev_name); + + if (!SLIST_EMPTY(&props)) { + SLIST_FOREACH(ent, &props, entries) { + key_val = prop_dictionary_get(dict, ent->val); + if (key_val != NULL) + print_prop(ent->val, key_val); + } + } else { + while ((cur_key = (prop_dictionary_keysym_t) prop_object_iterator_next(iter)) != NULL) { + key_str = prop_dictionary_keysym_cstring_nocopy(cur_key); + key_val = prop_dictionary_get_keysym(dict, cur_key); + print_prop(key_str, key_val); + } + } + + printf("\n"); + } + } + + udev_enumerate_unref(enumerate); + udev_unref(ctx); + + return (0); +} -- 2.41.0