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 printf("P: %s\n", udev->devpath);
87 printf("N: %s\n", udev->name);
88 printf("S: %s\n", udev->symlink);
101 static int print_device_chain(const char *path)
103 struct sysfs_class_device *class_dev;
104 struct sysfs_class_device *class_dev_parent;
105 struct sysfs_attribute *attr;
106 struct sysfs_device *sysfs_dev;
107 struct sysfs_device *sysfs_dev_parent;
108 struct dlist *attr_list;
111 /* get the class dev */
112 class_dev = sysfs_open_class_device_path(path);
113 if (class_dev == NULL) {
114 printf("couldn't get the class device\n");
118 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
119 "device chain, to print for every device found, all possibly useful attributes\n"
120 "in the udev key format.\n"
121 "Only attributes within one device section may be used together in one rule,\n"
122 "to match the device for which the node will be created.\n"
125 /* look for the 'dev' file */
126 attr = sysfs_get_classdev_attr(class_dev, "dev");
128 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
130 /* open sysfs class device directory and print all attributes */
131 printf(" looking at class device '%s':\n", class_dev->path);
132 printf(" SUBSYSTEM=\"%s\"\n", class_dev->classname);
134 attr_list = sysfs_get_classdev_attributes(class_dev);
135 if (attr_list == NULL) {
136 printf("couldn't open class device directory\n");
140 print_all_attributes(attr_list);
142 /* get the device link (if parent exists look here) */
143 class_dev_parent = sysfs_get_classdev_parent(class_dev);
144 if (class_dev_parent != NULL)
145 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
147 sysfs_dev = sysfs_get_classdev_device(class_dev);
149 if (sysfs_dev != NULL)
150 printf("follow the class device's \"device\"\n");
152 /* look the device chain upwards */
153 while (sysfs_dev != NULL) {
154 attr_list = sysfs_get_device_attributes(sysfs_dev);
155 if (attr_list == NULL) {
156 printf("couldn't open device directory\n");
161 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
162 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
163 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
164 printf(" DRIVER=\"%s\"\n", sysfs_dev->driver_name);
166 /* open sysfs device directory and print all attributes */
167 print_all_attributes(attr_list);
169 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
170 if (sysfs_dev_parent == NULL)
173 sysfs_dev = sysfs_dev_parent;
177 sysfs_close_class_device(class_dev);
181 static int print_dump(struct udevice *udev) {
182 printf("%s:%s/%s\n", udev->devpath, udev_root, udev->name);
186 static int process_options(int argc, char *argv[])
188 static const char short_options[] = "adn:p:q:rVh";
194 enum query_type query = NONE;
195 char result[1024] = "";
196 char path[NAME_SIZE] = "";
197 char name[NAME_SIZE] = "";
198 char temp[NAME_SIZE];
201 /* get command line options */
203 option = getopt(argc, argv, short_options);
207 dbg("option '%c'", option);
210 dbg("udev name: %s\n", optarg);
211 strfieldcpy(name, optarg);
215 dbg("udev path: %s\n", optarg);
216 strfieldcpy(path, optarg);
220 dbg("udev query: %s\n", optarg);
222 if (strcmp(optarg, "name") == 0) {
227 if (strcmp(optarg, "symlink") == 0) {
232 if (strcmp(optarg, "path") == 0) {
237 if (strcmp(optarg, "all") == 0) {
242 printf("unknown query type\n");
254 udev_db_call_foreach(print_dump);
258 printf("udevinfo, version %s\n", UDEV_VERSION);
269 /* process options */
271 if (path[0] != '\0') {
272 /* remove sysfs_path if given */
273 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
274 pos = path + strlen(sysfs_path);
276 if (path[0] != '/') {
277 /* prepend '/' if missing */
278 strfieldcat(temp, "/");
279 strfieldcat(temp, path);
285 memset(&udev, 0x00, sizeof(struct udevice));
286 retval = udev_db_get_device_by_devpath(&udev, pos);
288 printf("device not found in database\n");
294 if (name[0] != '\0') {
295 /* remove udev_root if given */
296 int len = strlen(udev_root);
298 if (strncmp(name, udev_root, len) == 0) {
303 memset(&udev, 0x00, sizeof(struct udevice));
304 strfieldcpy(udev.name, pos);
305 retval = udev_db_get_device_by_name(&udev, pos);
307 printf("device not found in database\n");
314 printf("query needs device path(-p) or node name(-n) specified\n");
321 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
322 result[NAME_SIZE-1] = '\0';
324 strfieldcpy(result, udev.name);
332 char slink[NAME_SIZE];
335 foreach_strpart(udev.symlink, " \n\r", spos, slen) {
336 strncpy(slink, spos, slen);
338 pos += sprintf(pos, "%s/%s ", udev_root, slink);
341 strfieldcpy(result, udev.symlink);
346 strfieldcpy(result, udev.devpath);
356 printf("%s\n", result);
363 if (path[0] == '\0') {
364 printf("attribute walk on device chain needs path(-p) specified\n");
367 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
368 /* prepend sysfs mountpoint if not given */
369 strfieldcpy(temp, path);
370 strfieldcpy(path, sysfs_path);
371 strfieldcat(path, temp);
373 print_device_chain(path);
379 printf("%s\n", udev_root);
384 printf("Usage: udevinfo [-anpqrVh]\n"
385 " -q TYPE query database for the specified value:\n"
386 " 'name' name of device node\n"
387 " 'symlink' pointing to node\n"
388 " 'path' sysfs device path\n"
389 " 'all' all values\n"
391 " -p PATH sysfs device path used for query or chain\n"
392 " -n NAME node/symlink name used for query\n"
394 " -r print udev root\n"
395 " -a print all SYSFS_attributes along the device chain\n"
396 " -d print the relationship of devpath and the node name for all\n"
397 " devices available in the database\n"
398 " -V print udev version\n"
399 " -h print this help text\n"
404 int main(int argc, char *argv[], char *envp[])
408 logging_init("udevinfo");
410 /* initialize our configuration */
413 rc = process_options(argc, argv);