2 * udevinfo - fetches attributes for a device
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include "libsysfs/sysfs/libsysfs.h"
30 #include "udev_libc_wrapper.h"
32 #include "udev_utils.h"
33 #include "udev_version.h"
39 void log_message (int priority, const char *format, ...)
43 if (priority > udev_log_priority)
46 va_start(args, format);
47 vsyslog(priority, format, args);
52 static void print_all_attributes(struct dlist *attr_list)
54 struct sysfs_attribute *attr;
55 char value[VALUE_SIZE];
58 dlist_for_each_data(attr_list, attr, struct sysfs_attribute) {
59 if (attr->value == NULL)
61 len = strlcpy(value, attr->value, sizeof(value));
62 if (len >= sizeof(value)) {
63 dbg("attribute value of '%s' too long, skip", attr->name);
67 /* remove trailing newlines */
68 while (len && value[len-1] == '\n')
70 /* skip nonprintable attributes */
71 while (len && isprint(value[len-1]))
74 dbg("attribute value of '%s' non-printable, skip", attr->name);
77 replace_untrusted_chars(value);
78 printf(" SYSFS{%s}==\"%s\"\n", attr->name, value);
83 static int print_record(struct udevice *udev)
85 struct name_entry *name_loop;
87 printf("P: %s\n", udev->devpath);
88 printf("N: %s\n", udev->name);
89 list_for_each_entry(name_loop, &udev->symlink_list, node)
90 printf("S: %s\n", name_loop->name);
103 static int print_device_chain(const char *path)
105 struct sysfs_class_device *class_dev;
106 struct sysfs_class_device *class_dev_parent;
107 struct sysfs_attribute *attr;
108 struct sysfs_device *sysfs_dev;
109 struct dlist *attr_list;
112 /* get the class dev */
113 class_dev = sysfs_open_class_device_path(path);
114 if (class_dev == NULL) {
115 fprintf(stderr, "couldn't get the class device\n");
119 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
120 "device chain, to print for every device found, all possibly useful attributes\n"
121 "in the udev key format.\n"
122 "Only attributes within one device section may be used together in one rule,\n"
123 "to match the device for which the node will be created.\n"
126 /* look for the 'dev' file */
127 attr = sysfs_get_classdev_attr(class_dev, "dev");
129 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
131 /* open sysfs class device directory and print all attributes */
132 printf(" looking at class device '%s':\n", class_dev->path);
133 printf(" SUBSYSTEM==\"%s\"\n", class_dev->classname);
135 attr_list = sysfs_get_classdev_attributes(class_dev);
136 if (attr_list == NULL) {
137 fprintf(stderr, "couldn't open class device directory\n");
141 print_all_attributes(attr_list);
143 /* get the device link (if parent exists look here) */
144 class_dev_parent = sysfs_get_classdev_parent(class_dev);
145 if (class_dev_parent != NULL)
146 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
148 sysfs_dev = sysfs_get_classdev_device(class_dev);
150 if (sysfs_dev != NULL)
151 printf("follow the \"device\"-link to the physical device:\n");
153 /* look the device chain upwards */
154 while (sysfs_dev != NULL) {
155 attr_list = sysfs_get_device_attributes(sysfs_dev);
156 if (attr_list == NULL) {
157 fprintf(stderr, "couldn't open device directory\n");
162 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
163 printf(" BUS==\"%s\"\n", sysfs_dev->bus);
164 printf(" ID==\"%s\"\n", sysfs_dev->bus_id);
165 printf(" DRIVER==\"%s\"\n", sysfs_dev->driver_name);
167 print_all_attributes(attr_list);
169 sysfs_dev = sysfs_get_device_parent(sysfs_dev);
170 if (sysfs_dev == NULL)
175 sysfs_close_class_device(class_dev);
179 static int print_dump(const char *devpath, const char *name) {
180 printf("%s=%s/%s\n", devpath, udev_root, name);
184 int main(int argc, char *argv[], char *envp[])
186 static const char short_options[] = "adn:p:q:rVh";
191 enum query_type query = NONE;
192 char path[PATH_SIZE] = "";
193 char name[PATH_SIZE] = "";
194 char temp[PATH_SIZE];
195 struct name_entry *name_loop;
199 logging_init("udevinfo");
202 udev_init_device(&udev, NULL, NULL, NULL);
204 /* get command line options */
206 option = getopt(argc, argv, short_options);
210 dbg("option '%c'", option);
213 dbg("udev name: %s\n", optarg);
214 strlcpy(name, optarg, sizeof(name));
218 dbg("udev path: %s\n", optarg);
219 strlcpy(path, optarg, sizeof(path));
223 dbg("udev query: %s\n", optarg);
225 if (strcmp(optarg, "name") == 0) {
230 if (strcmp(optarg, "symlink") == 0) {
235 if (strcmp(optarg, "path") == 0) {
240 if (strcmp(optarg, "all") == 0) {
245 fprintf(stderr, "unknown query type\n");
258 udev_db_dump_names(print_dump);
262 printf("udevinfo, version %s\n", UDEV_VERSION);
273 /* process options */
275 if (path[0] != '\0') {
276 /* remove sysfs_path if given */
277 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
278 pos = path + strlen(sysfs_path);
280 if (path[0] != '/') {
281 /* prepend '/' if missing */
283 strlcpy(temp, path, sizeof(temp));
289 retval = udev_db_get_device(&udev, pos);
291 fprintf(stderr, "device not found in database\n");
297 if (name[0] != '\0') {
298 char devpath[PATH_SIZE];
301 /* remove udev_root if given */
302 len = strlen(udev_root);
303 if (strncmp(name, udev_root, len) == 0) {
308 retval = udev_db_search_name(devpath, sizeof(devpath), pos);
310 fprintf(stderr, "device not found in database\n");
313 udev_db_get_device(&udev, devpath);
317 fprintf(stderr, "query needs device path(-p) or node name(-n) specified\n");
325 printf("%s/%s\n", udev_root, udev.name);
327 printf("%s\n", udev.name);
330 if (list_empty(&udev.symlink_list))
333 list_for_each_entry(name_loop, &udev.symlink_list, node)
334 printf("%s/%s ", udev_root, name_loop->name);
336 list_for_each_entry(name_loop, &udev.symlink_list, node)
337 printf("%s ", name_loop->name);
341 printf("%s\n", udev.devpath);
352 if (path[0] == '\0') {
353 fprintf(stderr, "attribute walk on device chain needs path(-p) specified\n");
357 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
358 /* prepend sysfs mountpoint if not given */
359 snprintf(temp, sizeof(temp), "%s%s", sysfs_path, path);
360 temp[sizeof(temp)-1] = '\0';
361 strlcpy(path, temp, sizeof(temp));
363 print_device_chain(path);
369 printf("%s\n", udev_root);
374 fprintf(stderr, "Usage: udevinfo [-anpqrVh]\n"
375 " -q TYPE query database for the specified value:\n"
376 " 'name' name of device node\n"
377 " 'symlink' pointing to node\n"
378 " 'path' sysfs device path\n"
379 " 'all' all values\n"
381 " -p PATH sysfs device path used for query or chain\n"
382 " -n NAME node/symlink name used for query\n"
384 " -r print udev root\n"
385 " -a print all SYSFS_attributes along the device chain\n"
386 " -d print the relationship of devpath and the node name for all\n"
387 " devices available in the database\n"
388 " -V print udev version\n"
389 " -h print this help text\n"
393 udev_cleanup_device(&udev);