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 unsigned int major, minor;
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 sscanf(attr->value, "%u:%u", &major, &minor);
232 printf("MAJOR %u\n", minor);
233 printf("MINOR %u\n", major);
236 phys_dev = sysfs_get_classdev_device(class_dev);
238 printf("PHYSDEVPATH '%s'\n", phys_dev->path);
239 if (phys_dev->bus[0] != '\0')
240 printf("PHYSDEVBUS '%s'\n", phys_dev->bus);
242 if (phys_dev->driver_name[0] != '\0')
243 printf("PHYSDEVDRIVER '%s'\n", phys_dev->driver_name);
246 sysfs_close_class(cls);
248 sysfs_close_list(subsyslist);
253 static int process_options(int argc, char *argv[])
255 static const char short_options[] = "adn:p:q:rsVh";
261 enum query_type query = NONE;
262 char result[1024] = "";
263 char path[NAME_SIZE] = "";
264 char name[NAME_SIZE] = "";
265 char temp[NAME_SIZE];
268 /* get command line options */
270 option = getopt(argc, argv, short_options);
274 dbg("option '%c'", option);
277 dbg("udev name: %s\n", optarg);
278 strfieldcpy(name, optarg);
282 dbg("udev path: %s\n", optarg);
283 strfieldcpy(path, optarg);
287 dbg("udev query: %s\n", optarg);
289 if (strcmp(optarg, "name") == 0) {
294 if (strcmp(optarg, "symlink") == 0) {
299 if (strcmp(optarg, "path") == 0) {
304 if (strcmp(optarg, "all") == 0) {
309 printf("unknown query type\n");
317 print_sysfs_devices();
325 printf("udevinfo, version %s\n", UDEV_VERSION);
336 /* process options */
338 if (path[0] != '\0') {
339 /* remove sysfs_path if given */
340 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
341 pos = path + strlen(sysfs_path);
343 if (path[0] != '/') {
344 /* prepend '/' if missing */
345 strfieldcat(temp, "/");
346 strfieldcat(temp, path);
352 memset(&udev, 0x00, sizeof(struct udevice));
353 strfieldcpy(udev.devpath, pos);
354 retval = udev_db_get_device(&udev);
356 printf("device not found in database\n");
362 if (name[0] != '\0') {
363 /* remove udev_root if given */
364 int len = strlen(udev_root);
366 if (strncmp(name, udev_root, len) == 0) {
371 memset(&udev, 0x00, sizeof(struct udevice));
372 strfieldcpy(udev.name, pos);
373 retval = udev_db_get_device_byname(&udev, pos);
375 printf("device not found in database\n");
382 printf("query needs device path(-p) or node name(-n) specified\n");
389 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
390 result[NAME_SIZE-1] = '\0';
392 strfieldcpy(result, udev.name);
400 char slink[NAME_SIZE];
403 foreach_strpart(udev.symlink, " \n\r", spos, slen) {
404 strncpy(slink, spos, slen);
406 pos += sprintf(pos, "%s/%s ", udev_root, slink);
409 strfieldcpy(result, udev.symlink);
414 strfieldcpy(result, path);
424 printf("%s\n", result);
431 if (path[0] == '\0') {
432 printf("attribute walk on device chain needs path(-p) specified\n");
435 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
436 /* prepend sysfs mountpoint if not given */
437 strfieldcpy(temp, path);
438 strfieldcpy(path, sysfs_path);
439 strfieldcat(path, temp);
441 print_device_chain(path);
447 printf("%s\n", udev_root);
452 printf("Usage: [-anpqrdVh]\n"
453 " -q TYPE query database for the specified value:\n"
454 " 'name' name of device node\n"
455 " 'symlink' pointing to node\n"
456 " 'path' sysfs device path\n"
457 " 'all' all values\n"
459 " -p PATH sysfs device path used for query or chain\n"
460 " -n NAME node/symlink name used for query\n"
462 " -r print udev root\n"
463 " -a print all SYSFS_attributes along the device chain\n"
464 " -s print all sysfs devices with major/minor, physical device and bus\n"
465 " -V print udev version\n"
466 " -h print this help text\n"
471 int main(int argc, char *argv[], char *envp[])
475 logging_init("udevinfo");
477 /* initialize our configuration */
480 rc = process_options(argc, argv);