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);
95 static int print_device_chain(const char *path)
97 struct sysfs_class_device *class_dev;
98 struct sysfs_class_device *class_dev_parent;
99 struct sysfs_attribute *attr;
100 struct sysfs_device *sysfs_dev;
101 struct dlist *attr_list;
104 /* get the class dev */
105 class_dev = sysfs_open_class_device_path(path);
106 if (class_dev == NULL) {
107 fprintf(stderr, "couldn't get the class device\n");
111 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
112 "device chain, to print for every device found, all possibly useful attributes\n"
113 "in the udev key format.\n"
114 "Only attributes within one device section may be used together in one rule,\n"
115 "to match the device for which the node will be created.\n"
118 /* look for the 'dev' file */
119 attr = sysfs_get_classdev_attr(class_dev, "dev");
121 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
123 /* open sysfs class device directory and print all attributes */
124 printf(" looking at class device '%s':\n", class_dev->path);
125 printf(" SUBSYSTEM==\"%s\"\n", class_dev->classname);
127 attr_list = sysfs_get_classdev_attributes(class_dev);
128 if (attr_list == NULL) {
129 fprintf(stderr, "couldn't open class device directory\n");
133 print_all_attributes(attr_list);
135 /* get the device link (if parent exists look here) */
136 class_dev_parent = sysfs_get_classdev_parent(class_dev);
137 if (class_dev_parent != NULL)
138 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
140 sysfs_dev = sysfs_get_classdev_device(class_dev);
142 if (sysfs_dev != NULL)
143 printf("follow the \"device\"-link to the physical device:\n");
145 /* look the device chain upwards */
146 while (sysfs_dev != NULL) {
147 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
148 printf(" BUS==\"%s\"\n", sysfs_dev->bus);
149 printf(" ID==\"%s\"\n", sysfs_dev->bus_id);
150 printf(" DRIVER==\"%s\"\n", sysfs_dev->driver_name);
152 attr_list = sysfs_get_device_attributes(sysfs_dev);
153 if (attr_list != NULL)
154 print_all_attributes(attr_list);
158 sysfs_dev = sysfs_get_device_parent(sysfs_dev);
159 if (sysfs_dev == NULL)
164 sysfs_close_class_device(class_dev);
168 static int print_dump(const char *devpath, const char *name) {
169 printf("%s=%s/%s\n", devpath, udev_root, name);
173 int main(int argc, char *argv[], char *envp[])
175 static const char short_options[] = "adn:p:q:rVh";
187 } query = QUERY_NONE;
188 char path[PATH_SIZE] = "";
189 char name[PATH_SIZE] = "";
190 char temp[PATH_SIZE];
191 struct name_entry *name_loop;
195 logging_init("udevinfo");
198 udev_init_device(&udev, NULL, NULL, NULL);
200 /* get command line options */
202 option = getopt(argc, argv, short_options);
206 dbg("option '%c'", option);
209 dbg("udev name: %s\n", optarg);
210 strlcpy(name, optarg, sizeof(name));
214 dbg("udev path: %s\n", optarg);
215 strlcpy(path, optarg, sizeof(path));
219 dbg("udev query: %s\n", optarg);
221 if (strcmp(optarg, "name") == 0) {
226 if (strcmp(optarg, "symlink") == 0) {
227 query = QUERY_SYMLINK;
231 if (strcmp(optarg, "path") == 0) {
236 if (strcmp(optarg, "env") == 0) {
241 if (strcmp(optarg, "all") == 0) {
246 fprintf(stderr, "unknown query type\n");
259 udev_db_dump_names(print_dump);
263 printf("udevinfo, version %s\n", UDEV_VERSION);
274 /* process options */
275 if (query != QUERY_NONE) {
276 if (path[0] != '\0') {
277 /* remove sysfs_path if given */
278 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
279 pos = path + strlen(sysfs_path);
281 if (path[0] != '/') {
282 /* prepend '/' if missing */
284 strlcpy(temp, path, sizeof(temp));
290 retval = udev_db_get_device(&udev, pos);
292 fprintf(stderr, "device not found in database\n");
298 if (name[0] != '\0') {
299 char devpath[PATH_SIZE];
302 /* remove udev_root if given */
303 len = strlen(udev_root);
304 if (strncmp(name, udev_root, len) == 0) {
309 retval = udev_db_search_name(devpath, sizeof(devpath), pos);
311 fprintf(stderr, "device not found in database\n");
314 udev_db_get_device(&udev, devpath);
318 fprintf(stderr, "query needs device path(-p) or node name(-n) specified\n");
326 printf("%s/%s\n", udev_root, udev.name);
328 printf("%s\n", udev.name);
331 if (list_empty(&udev.symlink_list))
334 list_for_each_entry(name_loop, &udev.symlink_list, node)
335 printf("%s/%s ", udev_root, name_loop->name);
337 list_for_each_entry(name_loop, &udev.symlink_list, node)
338 printf("%s ", name_loop->name);
342 printf("%s\n", udev.devpath);
345 list_for_each_entry(name_loop, &udev.env_list, node)
346 printf("%s\n", name_loop->name);
357 if (path[0] == '\0') {
358 fprintf(stderr, "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 snprintf(temp, sizeof(temp), "%s%s", sysfs_path, path);
365 temp[sizeof(temp)-1] = '\0';
366 strlcpy(path, temp, sizeof(temp));
368 print_device_chain(path);
374 printf("%s\n", udev_root);
379 fprintf(stderr, "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 " 'env' the device related imported environment\n"
385 " 'all' all values\n"
387 " -p PATH sysfs device path used for query or chain\n"
388 " -n NAME node/symlink name used for query\n"
390 " -r print udev root\n"
391 " -a print all SYSFS_attributes along the device chain\n"
392 " -d print the relationship of devpath and the node name for all\n"
393 " devices available in the database\n"
394 " -V print udev version\n"
395 " -h print this help text\n"
399 udev_cleanup_device(&udev);