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 int print_all_attributes(const char *path)
54 struct dlist *attributes;
55 struct sysfs_attribute *attr;
56 struct sysfs_directory *sysfs_dir;
57 char value[SYSFS_VALUE_SIZE];
61 sysfs_dir = sysfs_open_directory(path);
62 if (sysfs_dir == NULL)
65 attributes = sysfs_get_dir_attributes(sysfs_dir);
66 if (attributes == NULL) {
71 dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
72 if (attr->value != NULL) {
73 strfieldcpy(value, attr->value);
78 /* remove trailing newline */
79 if (value[len-1] == '\n') {
84 /* skip nonprintable values */
86 if (isprint(value[len-1]) == 0)
91 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
97 sysfs_close_directory(sysfs_dir);
102 static int print_record(struct udevice *udev)
104 printf("P: %s\n", udev->devpath);
105 printf("N: %s\n", udev->name);
106 printf("S: %s\n", udev->symlink);
119 static int print_device_chain(const char *path)
121 struct sysfs_class_device *class_dev;
122 struct sysfs_class_device *class_dev_parent;
123 struct sysfs_attribute *attr;
124 struct sysfs_device *sysfs_dev;
125 struct sysfs_device *sysfs_dev_parent;
128 /* get the class dev */
129 class_dev = sysfs_open_class_device_path(path);
130 if (class_dev == NULL) {
131 printf("couldn't get the class device\n");
135 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
136 "device chain, to print for every device found, all possibly useful attributes\n"
137 "in the udev key format.\n"
138 "Only attributes within one device section may be used together in one rule,\n"
139 "to match the device for which the node will be created.\n"
142 /* look for the 'dev' file */
143 attr = sysfs_get_classdev_attr(class_dev, "dev");
145 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
147 /* open sysfs class device directory and print all attributes */
148 printf(" looking at class device '%s':\n", class_dev->path);
149 printf(" SUBSYSTEM=\"%s\"\n", class_dev->classname);
150 if (print_all_attributes(class_dev->path) != 0) {
151 printf("couldn't open class device directory\n");
156 /* get the device link (if parent exists look here) */
157 class_dev_parent = sysfs_get_classdev_parent(class_dev);
158 if (class_dev_parent != NULL)
159 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
161 sysfs_dev = sysfs_get_classdev_device(class_dev);
163 if (sysfs_dev != NULL)
164 printf("follow the class device's \"device\"\n");
166 /* look the device chain upwards */
167 while (sysfs_dev != NULL) {
168 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
169 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
170 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
171 printf(" DRIVER=\"%s\"\n", sysfs_dev->driver_name);
173 /* open sysfs device directory and print all attributes */
174 print_all_attributes(sysfs_dev->path);
176 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
177 if (sysfs_dev_parent == NULL)
180 sysfs_dev = sysfs_dev_parent;
184 sysfs_close_class_device(class_dev);
188 /* print all class/main block devices with major/minor, physical device, driver and bus */
189 static int print_sysfs_devices(void)
191 struct dlist *subsyslist;
194 subsyslist = sysfs_open_subsystem_list("class");
198 dlist_for_each_data(subsyslist, class, char) {
199 struct sysfs_class *cls;
200 struct dlist *class_devices;
201 struct sysfs_class_device *class_dev;
202 struct sysfs_device *phys_dev;
203 unsigned int major, minor;
205 cls = sysfs_open_class(class);
209 class_devices = sysfs_get_class_devices(cls);
213 dlist_for_each_data(class_devices, class_dev, struct sysfs_class_device) {
214 struct sysfs_attribute *attr;
217 printf("DEVPATH '%s'\n", class_dev->path);
218 printf("SUBSYSTEM '%s'\n", class_dev->classname);
220 attr = sysfs_get_classdev_attr(class_dev, "dev");
222 sscanf(attr->value, "%u:%u", &major, &minor);
223 printf("MAJOR %u\n", major);
224 printf("MINOR %u\n", minor);
227 phys_dev = sysfs_get_classdev_device(class_dev);
229 printf("PHYSDEVPATH '%s'\n", phys_dev->path);
230 if (phys_dev->bus[0] != '\0')
231 printf("PHYSDEVBUS '%s'\n", phys_dev->bus);
233 if (phys_dev->driver_name[0] != '\0')
234 printf("PHYSDEVDRIVER '%s'\n", phys_dev->driver_name);
237 sysfs_close_class(cls);
239 sysfs_close_list(subsyslist);
244 static int process_options(int argc, char *argv[])
246 static const char short_options[] = "an:p:q:rsVh";
252 enum query_type query = NONE;
253 char result[1024] = "";
254 char path[NAME_SIZE] = "";
255 char name[NAME_SIZE] = "";
256 char temp[NAME_SIZE];
259 /* get command line options */
261 option = getopt(argc, argv, short_options);
265 dbg("option '%c'", option);
268 dbg("udev name: %s\n", optarg);
269 strfieldcpy(name, optarg);
273 dbg("udev path: %s\n", optarg);
274 strfieldcpy(path, optarg);
278 dbg("udev query: %s\n", optarg);
280 if (strcmp(optarg, "name") == 0) {
285 if (strcmp(optarg, "symlink") == 0) {
290 if (strcmp(optarg, "path") == 0) {
295 if (strcmp(optarg, "all") == 0) {
300 printf("unknown query type\n");
308 print_sysfs_devices();
316 printf("udevinfo, version %s\n", UDEV_VERSION);
327 /* process options */
329 if (path[0] != '\0') {
330 /* remove sysfs_path if given */
331 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
332 pos = path + strlen(sysfs_path);
334 if (path[0] != '/') {
335 /* prepend '/' if missing */
336 strfieldcat(temp, "/");
337 strfieldcat(temp, path);
343 memset(&udev, 0x00, sizeof(struct udevice));
344 strfieldcpy(udev.devpath, pos);
345 retval = udev_db_get_device(&udev);
347 printf("device not found in database\n");
353 if (name[0] != '\0') {
354 /* remove udev_root if given */
355 int len = strlen(udev_root);
357 if (strncmp(name, udev_root, len) == 0) {
362 memset(&udev, 0x00, sizeof(struct udevice));
363 strfieldcpy(udev.name, pos);
364 retval = udev_db_get_device_byname(&udev, pos);
366 printf("device not found in database\n");
373 printf("query needs device path(-p) or node name(-n) specified\n");
380 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
381 result[NAME_SIZE-1] = '\0';
383 strfieldcpy(result, udev.name);
391 char slink[NAME_SIZE];
394 foreach_strpart(udev.symlink, " \n\r", spos, slen) {
395 strncpy(slink, spos, slen);
397 pos += sprintf(pos, "%s/%s ", udev_root, slink);
400 strfieldcpy(result, udev.symlink);
405 strfieldcpy(result, udev.devpath);
415 printf("%s\n", result);
422 if (path[0] == '\0') {
423 printf("attribute walk on device chain needs path(-p) specified\n");
426 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
427 /* prepend sysfs mountpoint if not given */
428 strfieldcpy(temp, path);
429 strfieldcpy(path, sysfs_path);
430 strfieldcat(path, temp);
432 print_device_chain(path);
438 printf("%s\n", udev_root);
443 printf("Usage: udevinfo [-anpqrVh]\n"
444 " -q TYPE query database for the specified value:\n"
445 " 'name' name of device node\n"
446 " 'symlink' pointing to node\n"
447 " 'path' sysfs device path\n"
448 " 'all' all values\n"
450 " -p PATH sysfs device path used for query or chain\n"
451 " -n NAME node/symlink name used for query\n"
453 " -r print udev root\n"
454 " -a print all SYSFS_attributes along the device chain\n"
455 " -s print all sysfs devices with major/minor, physical device and bus\n"
456 " -V print udev version\n"
457 " -h print this help text\n"
462 int main(int argc, char *argv[], char *envp[])
466 logging_init("udevinfo");
468 /* initialize our configuration */
471 rc = process_options(argc, argv);