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 "libsysfs/dlist.h"
31 #include "udev_libc_wrapper.h"
33 #include "udev_utils.h"
34 #include "udev_version.h"
40 void log_message (int level, const char *format, ...)
44 va_start(args, format);
45 vsyslog(level, format, args);
50 static void print_all_attributes(struct dlist *attr_list)
52 struct sysfs_attribute *attr;
53 char value[VALUE_SIZE];
56 dlist_for_each_data(attr_list, attr, struct sysfs_attribute) {
57 if (attr->value != NULL) {
58 strlcpy(value, attr->value, sizeof(value));
63 /* remove trailing newline */
64 if (value[len-1] == '\n') {
69 /* skip nonprintable values */
71 if (isprint(value[len-1]) == 0)
76 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
82 static int print_record(struct udevice *udev)
84 struct name_entry *name_loop;
86 printf("P: %s\n", udev->devpath);
87 printf("N: %s\n", udev->name);
88 list_for_each_entry(name_loop, &udev->symlink_list, node)
89 printf("S: %s\n", name_loop->name);
102 static int print_device_chain(const char *path)
104 struct sysfs_class_device *class_dev;
105 struct sysfs_class_device *class_dev_parent;
106 struct sysfs_attribute *attr;
107 struct sysfs_device *sysfs_dev;
108 struct sysfs_device *sysfs_dev_parent;
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 printf("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 printf("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 class device's \"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 printf("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 /* open sysfs device directory and print all attributes */
168 print_all_attributes(attr_list);
170 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
171 if (sysfs_dev_parent == NULL)
174 sysfs_dev = sysfs_dev_parent;
178 sysfs_close_class_device(class_dev);
182 static int print_dump(const char *devpath, const char *name) {
183 printf("%s:%s/%s\n", devpath, udev_root, name);
187 int main(int argc, char *argv[], char *envp[])
189 static const char short_options[] = "adn:p:q:rVh";
194 enum query_type query = NONE;
195 char path[PATH_SIZE] = "";
196 char name[PATH_SIZE] = "";
197 char temp[PATH_SIZE];
198 struct name_entry *name_loop;
202 logging_init("udevinfo");
205 udev_init_device(&udev, NULL, NULL);
207 /* get command line options */
209 option = getopt(argc, argv, short_options);
213 dbg("option '%c'", option);
216 dbg("udev name: %s\n", optarg);
217 strlcpy(name, optarg, sizeof(name));
221 dbg("udev path: %s\n", optarg);
222 strlcpy(path, optarg, sizeof(path));
226 dbg("udev query: %s\n", optarg);
228 if (strcmp(optarg, "name") == 0) {
233 if (strcmp(optarg, "symlink") == 0) {
238 if (strcmp(optarg, "path") == 0) {
243 if (strcmp(optarg, "all") == 0) {
248 printf("unknown query type\n");
261 udev_db_dump_names(print_dump);
265 printf("udevinfo, version %s\n", UDEV_VERSION);
276 /* process options */
278 if (path[0] != '\0') {
279 /* remove sysfs_path if given */
280 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
281 pos = path + strlen(sysfs_path);
283 if (path[0] != '/') {
284 /* prepend '/' if missing */
286 strlcpy(temp, path, sizeof(temp));
292 retval = udev_db_get_device(&udev, pos);
294 printf("device not found in database\n");
300 if (name[0] != '\0') {
301 char devpath[PATH_SIZE];
304 /* remove udev_root if given */
305 len = strlen(udev_root);
306 if (strncmp(name, udev_root, len) == 0) {
311 retval = udev_db_search_name(devpath, sizeof(devpath), pos);
313 printf("device not found in database\n");
316 udev_db_get_device(&udev, devpath);
320 printf("query needs device path(-p) or node name(-n) specified\n");
328 printf("%s/%s\n", udev_root, udev.name);
330 printf("%s\n", udev.name);
333 if (list_empty(&udev.symlink_list))
336 list_for_each_entry(name_loop, &udev.symlink_list, node)
337 printf("%s/%s ", udev_root, name_loop->name);
339 list_for_each_entry(name_loop, &udev.symlink_list, node)
340 printf("%s ", name_loop->name);
344 printf("%s\n", udev.devpath);
355 if (path[0] == '\0') {
356 printf("attribute walk on device chain needs path(-p) specified\n");
360 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
361 /* prepend sysfs mountpoint if not given */
362 snprintf(temp, sizeof(temp), "%s%s", sysfs_path, path);
363 temp[sizeof(temp)-1] = '\0';
364 strlcpy(path, temp, sizeof(temp));
366 print_device_chain(path);
372 printf("%s\n", udev_root);
377 printf("Usage: udevinfo [-anpqrVh]\n"
378 " -q TYPE query database for the specified value:\n"
379 " 'name' name of device node\n"
380 " 'symlink' pointing to node\n"
381 " 'path' sysfs device path\n"
382 " 'all' all values\n"
384 " -p PATH sysfs device path used for query or chain\n"
385 " -n NAME node/symlink name used for query\n"
387 " -r print udev root\n"
388 " -a print all SYSFS_attributes along the device chain\n"
389 " -d print the relationship of devpath and the node name for all\n"
390 " devices available in the database\n"
391 " -V print udev version\n"
392 " -h print this help text\n"
396 udev_cleanup_device(&udev);