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"
34 #include "udev_version.h"
39 #define SYSFS_VALUE_SIZE 256
42 unsigned char logname[LOGNAME_SIZE];
43 void log_message (int level, const char *format, ...)
47 va_start(args, format);
48 vsyslog(level, format, args);
53 static int print_all_attributes(const char *path)
55 struct dlist *attributes;
56 struct sysfs_attribute *attr;
57 struct sysfs_directory *sysfs_dir;
58 char value[SYSFS_VALUE_SIZE];
62 sysfs_dir = sysfs_open_directory(path);
63 if (sysfs_dir == NULL)
66 attributes = sysfs_get_dir_attributes(sysfs_dir);
67 if (attributes == NULL) {
72 dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
73 if (attr->value != NULL) {
74 strfieldcpy(value, attr->value);
79 /* remove trailing newline */
80 if (value[len-1] == '\n') {
85 /* skip nonprintable values */
87 if (isprint(value[len-1]) == 0)
92 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
98 sysfs_close_directory(sysfs_dir);
103 static int print_record(struct udevice *udev)
105 printf("P: %s\n", udev->devpath);
106 printf("N: %s\n", udev->name);
107 printf("S: %s\n", udev->symlink);
120 static int print_device_chain(const char *path)
122 struct sysfs_class_device *class_dev;
123 struct sysfs_class_device *class_dev_parent;
124 struct sysfs_attribute *attr;
125 struct sysfs_device *sysfs_dev;
126 struct sysfs_device *sysfs_dev_parent;
130 type = get_device_type(path, "");
131 dbg("device type is %c", type);
133 /* get the class dev */
134 class_dev = sysfs_open_class_device_path(path);
135 if (class_dev == NULL) {
136 printf("couldn't get the class device\n");
140 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
141 "device chain, to print for every device found, all possibly useful attributes\n"
142 "in the udev key format.\n"
143 "Only attributes within one device section may be used together in one rule,\n"
144 "to match the device for which the node will be created.\n"
147 if (type == 'b' || type =='c') {
148 /* read the 'dev' file for major/minor*/
149 attr = sysfs_get_classdev_attr(class_dev, "dev");
151 printf("couldn't get the \"dev\" file\n");
155 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
158 /* open sysfs class device directory and print all attributes */
159 printf(" looking at class device '%s':\n", class_dev->path);
160 if (print_all_attributes(class_dev->path) != 0) {
161 printf("couldn't open class device directory\n");
166 /* get the device link (if parent exists look here) */
167 class_dev_parent = sysfs_get_classdev_parent(class_dev);
168 if (class_dev_parent != NULL)
169 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
171 sysfs_dev = sysfs_get_classdev_device(class_dev);
173 if (sysfs_dev != NULL)
174 printf("follow the class device's \"device\"\n");
176 /* look the device chain upwards */
177 while (sysfs_dev != NULL) {
178 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
179 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
180 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
182 /* open sysfs device directory and print all attributes */
183 print_all_attributes(sysfs_dev->path);
185 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
186 if (sysfs_dev_parent == NULL)
189 sysfs_dev = sysfs_dev_parent;
193 sysfs_close_class_device(class_dev);
197 /* print all class/main block devices with major/minor, physical device, driver and bus */
198 static int print_sysfs_devices(void)
200 struct dlist *subsyslist;
203 subsyslist = sysfs_open_subsystem_list("class");
207 dlist_for_each_data(subsyslist, class, char) {
208 struct sysfs_class *cls;
209 struct dlist *class_devices;
210 struct sysfs_class_device *class_dev;
211 struct sysfs_device *phys_dev;
212 struct sysfs_driver *driver;
214 cls = sysfs_open_class(class);
218 class_devices = sysfs_get_class_devices(cls);
222 dlist_for_each_data(class_devices, class_dev, struct sysfs_class_device) {
223 struct sysfs_attribute *attr;
226 printf("DEVPATH '%s'\n", class_dev->path);
227 printf("SUBSYSTEM '%s'\n", class_dev->classname);
229 attr = sysfs_get_classdev_attr(class_dev, "dev");
231 char *pos = &(attr->value[strlen(attr->value)-1]);
236 printf("DEVMAJORMINOR '%s'\n", attr->value);
239 driver = sysfs_get_classdev_driver(class_dev);
241 printf("DEVDRIVER '%s'\n", driver->name);
243 phys_dev = sysfs_get_classdev_device(class_dev);
245 printf("PHYSDEVPATH '%s'\n", phys_dev->path);
246 if (phys_dev->bus[0] != '\0')
247 printf("PHYSDEVBUS '%s'\n", phys_dev->bus);
250 sysfs_close_class(cls);
252 sysfs_close_list(subsyslist);
257 static int process_options(int argc, char *argv[])
259 static const char short_options[] = "adn:p:q:rsVh";
265 enum query_type query = NONE;
266 char result[1024] = "";
267 char path[NAME_SIZE] = "";
268 char name[NAME_SIZE] = "";
269 char temp[NAME_SIZE];
272 /* get command line options */
274 option = getopt(argc, argv, short_options);
278 dbg("option '%c'", option);
281 dbg("udev name: %s\n", optarg);
282 strfieldcpy(name, optarg);
286 dbg("udev path: %s\n", optarg);
287 strfieldcpy(path, optarg);
291 dbg("udev query: %s\n", optarg);
293 if (strcmp(optarg, "name") == 0) {
298 if (strcmp(optarg, "symlink") == 0) {
303 if (strcmp(optarg, "path") == 0) {
308 if (strcmp(optarg, "all") == 0) {
313 printf("unknown query type\n");
321 print_sysfs_devices();
329 printf("udevinfo, version %s\n", UDEV_VERSION);
340 /* process options */
342 if (path[0] != '\0') {
343 /* remove sysfs_path if given */
344 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
345 pos = path + strlen(sysfs_path);
347 if (path[0] != '/') {
348 /* prepend '/' if missing */
349 strfieldcat(temp, "/");
350 strfieldcat(temp, path);
356 memset(&udev, 0x00, sizeof(struct udevice));
357 strfieldcpy(udev.devpath, pos);
358 retval = udev_db_get_device(&udev);
360 printf("device not found in database\n");
366 if (name[0] != '\0') {
367 /* remove udev_root if given */
368 int len = strlen(udev_root);
370 if (strncmp(name, udev_root, len) == 0) {
375 memset(&udev, 0x00, sizeof(struct udevice));
376 strfieldcpy(udev.name, pos);
377 retval = udev_db_get_device_byname(&udev, pos);
379 printf("device not found in database\n");
386 printf("query needs device path(-p) or node name(-n) specified\n");
393 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
394 result[NAME_SIZE-1] = '\0';
396 strfieldcpy(result, udev.name);
404 char slink[NAME_SIZE];
407 foreach_strpart(udev.symlink, " \n\r", spos, slen) {
408 strncpy(slink, spos, slen);
410 pos += sprintf(pos, "%s/%s ", udev_root, slink);
413 strfieldcpy(result, udev.symlink);
418 strfieldcpy(result, path);
428 printf("%s\n", result);
435 if (path[0] == '\0') {
436 printf("attribute walk on device chain needs path(-p) specified\n");
439 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
440 /* prepend sysfs mountpoint if not given */
441 strfieldcpy(temp, path);
442 strfieldcpy(path, sysfs_path);
443 strfieldcat(path, temp);
445 print_device_chain(path);
451 printf("%s\n", udev_root);
456 printf("Usage: [-anpqrdVh]\n"
457 " -q TYPE query database for the specified value:\n"
458 " 'name' name of device node\n"
459 " 'symlink' pointing to node\n"
460 " 'path' sysfs device path\n"
461 " 'all' all values\n"
463 " -p PATH sysfs device path used for query or chain\n"
464 " -n NAME node/symlink name used for query\n"
466 " -r print udev root\n"
467 " -a print all SYSFS_attributes along the device chain\n"
468 " -s print all sysfs devices with major/minor, physical device and bus\n"
469 " -V print udev version\n"
470 " -h print this help text\n"
475 int main(int argc, char *argv[], char *envp[])
479 logging_init("udevinfo");
481 /* initialize our configuration */
484 rc = process_options(argc, argv);