2 * udevinfo - fetches attributes for a device
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include "libsysfs/sysfs/libsysfs.h"
31 #include "libsysfs/dlist.h"
33 #include "udev_utils.h"
34 #include "udev_version.h"
39 #define SYSFS_VALUE_SIZE 256
42 void log_message (int level, const char *format, ...)
46 va_start(args, format);
47 vsyslog(level, format, args);
52 static void print_all_attributes(struct dlist *attr_list)
54 struct sysfs_attribute *attr;
55 char value[SYSFS_VALUE_SIZE];
58 dlist_for_each_data(attr_list, attr, struct sysfs_attribute) {
59 if (attr->value != NULL) {
60 strfieldcpy(value, attr->value);
65 /* remove trailing newline */
66 if (value[len-1] == '\n') {
71 /* skip nonprintable values */
73 if (isprint(value[len-1]) == 0)
78 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
84 static int print_record(struct udevice *udev)
86 struct name_entry *name_loop;
88 printf("P: %s\n", udev->devpath);
89 printf("N: %s\n", udev->name);
90 list_for_each_entry(name_loop, &udev->symlink_list, node)
91 printf("S: %s\n", name_loop->name);
104 static int print_device_chain(const char *path)
106 struct sysfs_class_device *class_dev;
107 struct sysfs_class_device *class_dev_parent;
108 struct sysfs_attribute *attr;
109 struct sysfs_device *sysfs_dev;
110 struct sysfs_device *sysfs_dev_parent;
111 struct dlist *attr_list;
114 /* get the class dev */
115 class_dev = sysfs_open_class_device_path(path);
116 if (class_dev == NULL) {
117 printf("couldn't get the class device\n");
121 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
122 "device chain, to print for every device found, all possibly useful attributes\n"
123 "in the udev key format.\n"
124 "Only attributes within one device section may be used together in one rule,\n"
125 "to match the device for which the node will be created.\n"
128 /* look for the 'dev' file */
129 attr = sysfs_get_classdev_attr(class_dev, "dev");
131 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
133 /* open sysfs class device directory and print all attributes */
134 printf(" looking at class device '%s':\n", class_dev->path);
135 printf(" SUBSYSTEM=\"%s\"\n", class_dev->classname);
137 attr_list = sysfs_get_classdev_attributes(class_dev);
138 if (attr_list == NULL) {
139 printf("couldn't open class device directory\n");
143 print_all_attributes(attr_list);
145 /* get the device link (if parent exists look here) */
146 class_dev_parent = sysfs_get_classdev_parent(class_dev);
147 if (class_dev_parent != NULL)
148 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
150 sysfs_dev = sysfs_get_classdev_device(class_dev);
152 if (sysfs_dev != NULL)
153 printf("follow the class device's \"device\"\n");
155 /* look the device chain upwards */
156 while (sysfs_dev != NULL) {
157 attr_list = sysfs_get_device_attributes(sysfs_dev);
158 if (attr_list == NULL) {
159 printf("couldn't open device directory\n");
164 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
165 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
166 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
167 printf(" DRIVER=\"%s\"\n", sysfs_dev->driver_name);
169 /* open sysfs device directory and print all attributes */
170 print_all_attributes(attr_list);
172 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
173 if (sysfs_dev_parent == NULL)
176 sysfs_dev = sysfs_dev_parent;
180 sysfs_close_class_device(class_dev);
184 static int print_dump(const char *devpath, const char *name) {
185 printf("%s:%s/%s\n", devpath, udev_root, name);
189 int main(int argc, char *argv[], char *envp[])
191 static const char short_options[] = "adn:p:q:rVh";
196 enum query_type query = NONE;
197 char path[NAME_SIZE] = "";
198 char name[NAME_SIZE] = "";
199 char temp[NAME_SIZE];
200 struct name_entry *name_loop;
204 logging_init("udevinfo");
207 udev_init_device(&udev, NULL, NULL);
209 /* get command line options */
211 option = getopt(argc, argv, short_options);
215 dbg("option '%c'", option);
218 dbg("udev name: %s\n", optarg);
219 strfieldcpy(name, optarg);
223 dbg("udev path: %s\n", optarg);
224 strfieldcpy(path, optarg);
228 dbg("udev query: %s\n", optarg);
230 if (strcmp(optarg, "name") == 0) {
235 if (strcmp(optarg, "symlink") == 0) {
240 if (strcmp(optarg, "path") == 0) {
245 if (strcmp(optarg, "all") == 0) {
250 printf("unknown query type\n");
263 udev_db_dump_names(print_dump);
267 printf("udevinfo, version %s\n", UDEV_VERSION);
278 /* process options */
280 if (path[0] != '\0') {
281 /* remove sysfs_path if given */
282 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
283 pos = path + strlen(sysfs_path);
285 if (path[0] != '/') {
286 /* prepend '/' if missing */
288 strfieldcat(temp, path);
294 retval = udev_db_get_device(&udev, pos);
296 printf("device not found in database\n");
302 if (name[0] != '\0') {
303 char devpath[NAME_SIZE];
306 /* remove udev_root if given */
307 len = strlen(udev_root);
308 if (strncmp(name, udev_root, len) == 0) {
313 retval = udev_db_search_name(devpath, DEVPATH_SIZE, pos);
315 printf("device not found in database\n");
318 udev_db_get_device(&udev, devpath);
322 printf("query needs device path(-p) or node name(-n) specified\n");
330 printf("%s/%s\n", udev_root, udev.name);
332 printf("%s\n", udev.name);
335 if (list_empty(&udev.symlink_list))
338 list_for_each_entry(name_loop, &udev.symlink_list, node)
339 printf("%s/%s ", udev_root, name_loop->name);
341 list_for_each_entry(name_loop, &udev.symlink_list, node)
342 printf("%s ", name_loop->name);
346 printf("%s\n", udev.devpath);
357 if (path[0] == '\0') {
358 printf("attribute walk on device chain needs path(-p) specified\n");
362 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
363 /* prepend sysfs mountpoint if not given */
364 strfieldcpy(temp, path);
365 strfieldcpy(path, sysfs_path);
366 strfieldcat(path, temp);
368 print_device_chain(path);
374 printf("%s\n", udev_root);
379 printf("Usage: udevinfo [-anpqrVh]\n"
380 " -q TYPE query database for the specified value:\n"
381 " 'name' name of device node\n"
382 " 'symlink' pointing to node\n"
383 " 'path' sysfs device path\n"
384 " 'all' all values\n"
386 " -p PATH sysfs device path used for query or chain\n"
387 " -n NAME node/symlink name used for query\n"
389 " -r print udev root\n"
390 " -a print all SYSFS_attributes along the device chain\n"
391 " -d print the relationship of devpath and the node name for all\n"
392 " devices available in the database\n"
393 " -V print udev version\n"
394 " -h print this help text\n"
398 udev_cleanup_device(&udev);