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_MAX 200
45 unsigned char logname[LOGNAME_SIZE];
46 void log_message (int level, const char *format, ...)
50 va_start(args, format);
51 vsyslog(level, format, args);
56 static int print_all_attributes(const char *path)
58 struct dlist *attributes;
59 struct sysfs_attribute *attr;
60 struct sysfs_directory *sysfs_dir;
61 char value[SYSFS_VALUE_MAX];
65 sysfs_dir = sysfs_open_directory(path);
66 if (sysfs_dir == NULL)
69 attributes = sysfs_get_dir_attributes(sysfs_dir);
70 if (attributes == NULL) {
75 dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
76 if (attr->value != NULL) {
77 strfieldcpy(value, attr->value);
82 /* remove trailing newline */
83 if (value[len-1] == '\n') {
88 /* skip nonprintable values */
90 if (isprint(value[len-1]) == 0)
95 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
101 sysfs_close_directory(sysfs_dir);
106 static int print_record(struct udevice *udev)
108 printf("P: %s\n", udev->devpath);
109 printf("N: %s\n", udev->name);
110 printf("S: %s\n", udev->symlink);
123 static int print_device_chain(const char *path)
125 struct sysfs_class_device *class_dev;
126 struct sysfs_class_device *class_dev_parent;
127 struct sysfs_attribute *attr;
128 struct sysfs_device *sysfs_dev;
129 struct sysfs_device *sysfs_dev_parent;
133 type = get_device_type(path, "");
134 dbg("device type is %c", type);
136 /* get the class dev */
137 class_dev = sysfs_open_class_device_path(path);
138 if (class_dev == NULL) {
139 printf("couldn't get the class device\n");
143 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
144 "device chain, to print for every device found, all possibly useful attributes\n"
145 "in the udev key format.\n"
146 "Only attributes within one device section may be used together in one rule,\n"
147 "to match the device for which the node will be created.\n"
150 if (type == 'b' || type =='c') {
151 /* read the 'dev' file for major/minor*/
152 attr = sysfs_get_classdev_attr(class_dev, "dev");
154 printf("couldn't get the \"dev\" file\n");
158 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
161 /* open sysfs class device directory and print all attributes */
162 printf(" looking at class device '%s':\n", class_dev->path);
163 if (print_all_attributes(class_dev->path) != 0) {
164 printf("couldn't open class device directory\n");
169 /* get the device link (if parent exists look here) */
170 class_dev_parent = sysfs_get_classdev_parent(class_dev);
171 if (class_dev_parent != NULL)
172 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
174 sysfs_dev = sysfs_get_classdev_device(class_dev);
176 if (sysfs_dev != NULL)
177 printf("follow the class device's \"device\"\n");
179 /* look the device chain upwards */
180 while (sysfs_dev != NULL) {
181 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
182 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
183 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
185 /* open sysfs device directory and print all attributes */
186 print_all_attributes(sysfs_dev->path);
188 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
189 if (sysfs_dev_parent == NULL)
192 sysfs_dev = sysfs_dev_parent;
196 sysfs_close_class_device(class_dev);
200 /* print all class/block devices with major/minor, physical device and bus*/
201 static void print_sysfs_devices(void)
203 struct dlist *subsyslist;
206 subsyslist = sysfs_open_subsystem_list("class");
210 dlist_for_each_data(subsyslist, class, char) {
211 struct sysfs_class *cls;
212 struct dlist *class_devices;
213 struct sysfs_class_device *class_dev;
214 struct sysfs_device *phys_dev;
216 cls = sysfs_open_class(class);
220 class_devices = sysfs_get_class_devices(cls);
224 dlist_for_each_data(class_devices, class_dev, struct sysfs_class_device) {
225 struct sysfs_attribute *attr;
228 printf("DEVPATH '%s'\n", class_dev->path);
229 printf("SUBSYSTEM '%s'\n", class_dev->classname);
230 printf("NAME '%s'\n", class_dev->name);
232 attr = sysfs_get_classdev_attr(class_dev, "dev");
234 char *pos = &(attr->value[strlen(attr->value)-1]);
239 printf("MAJORMINOR '%s'\n", attr->value);
242 phys_dev = sysfs_get_classdev_device(class_dev);
244 printf("PHYSDEVPATH '%s'\n", phys_dev->path);
245 if (phys_dev->bus[0] != '\0')
246 printf("PHYSDEVPATHBUS '%s'\n", phys_dev->bus);
247 if (phys_dev->driver_name[0] != '\0')
248 printf("DRIVER '%s'\n", phys_dev->driver_name);
252 sysfs_close_class(cls);
255 sysfs_close_list(subsyslist);
258 static int process_options(void)
260 static const char short_options[] = "adn:p:q:rsVh";
266 enum query_type query = NONE;
267 char result[NAME_SIZE] = "";
268 char path[NAME_SIZE] = "";
269 char name[NAME_SIZE] = "";
270 char temp[NAME_SIZE];
273 /* get command line options */
275 option = getopt(main_argc, main_argv, short_options);
279 dbg("option '%c'", option);
282 dbg("udev name: %s\n", optarg);
283 strfieldcpy(name, optarg);
287 dbg("udev path: %s\n", optarg);
288 strfieldcpy(path, optarg);
292 dbg("udev query: %s\n", optarg);
294 if (strcmp(optarg, "name") == 0) {
299 if (strcmp(optarg, "symlink") == 0) {
304 if (strcmp(optarg, "path") == 0) {
309 if (strcmp(optarg, "all") == 0) {
314 printf("unknown query type\n");
322 print_sysfs_devices();
330 printf("udevinfo, version %s\n", UDEV_VERSION);
341 /* process options */
343 if (path[0] != '\0') {
344 /* remove sysfs_path if given */
345 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
346 pos = path + strlen(sysfs_path);
348 if (path[0] != '/') {
349 /* prepend '/' if missing */
350 strfieldcat(temp, "/");
351 strfieldcat(temp, path);
357 memset(&udev, 0x00, sizeof(struct udevice));
358 strfieldcpy(udev.devpath, pos);
359 retval = udevdb_get_dev(&udev);
361 printf("device not found in database\n");
367 if (name[0] != '\0') {
368 /* remove udev_root if given */
369 int len = strlen(udev_root);
371 if (strncmp(name, udev_root, len) == 0) {
376 memset(&udev, 0x00, sizeof(struct udevice));
377 strfieldcpy(udev.name, pos);
378 retval = udevdb_get_dev_byname(&udev, pos);
380 printf("device not found in database\n");
387 printf("query needs device path(-p) or node name(-n) specified\n");
394 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
395 result[NAME_SIZE-1] = '\0';
397 strfieldcpy(result, udev.name);
402 strfieldcpy(result, udev.symlink);
406 strfieldcpy(result, path);
416 printf("%s\n", result);
423 if (path[0] == '\0') {
424 printf("attribute walk on device chain needs path(-p) specified\n");
427 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
428 /* prepend sysfs mountpoint if not given */
429 strfieldcpy(temp, path);
430 strfieldcpy(path, sysfs_path);
431 strfieldcat(path, temp);
433 print_device_chain(path);
439 printf("%s\n", udev_root);
444 printf("Usage: [-anpqrdVh]\n"
445 " -q TYPE query database for the specified value:\n"
446 " 'name' name of device node\n"
447 " 'symlink' pointing to node\n"
448 " 'path' sysfs device path\n"
449 " 'all' all values\n"
451 " -p PATH sysfs device path used for query or chain\n"
452 " -n NAME node/symlink name used for query\n"
454 " -r print udev root\n"
455 " -a print all SYSFS_attributes along the device chain\n"
456 " -s print all sysfs devices with major/minor, physical device and bus\n"
457 " -V print udev version\n"
458 " -h print this help text\n"
463 int main(int argc, char *argv[], char *envp[])
470 logging_init("udevinfo");
472 /* initialize our configuration */
475 rc = process_options();