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/main block devices with major/minor, physical device, driver and bus */
201 static int 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;
215 struct sysfs_driver *driver;
217 cls = sysfs_open_class(class);
221 class_devices = sysfs_get_class_devices(cls);
225 dlist_for_each_data(class_devices, class_dev, struct sysfs_class_device) {
226 struct sysfs_attribute *attr;
229 printf("DEVPATH '%s'\n", class_dev->path);
230 printf("SUBSYSTEM '%s'\n", class_dev->classname);
232 attr = sysfs_get_classdev_attr(class_dev, "dev");
234 char *pos = &(attr->value[strlen(attr->value)-1]);
239 printf("DEVMAJORMINOR '%s'\n", attr->value);
242 driver = sysfs_get_classdev_driver(class_dev);
244 printf("DEVDRIVER '%s'\n", driver->name);
246 phys_dev = sysfs_get_classdev_device(class_dev);
248 printf("PHYSDEVPATH '%s'\n", phys_dev->path);
249 if (phys_dev->bus[0] != '\0')
250 printf("PHYSDEVBUS '%s'\n", phys_dev->bus);
253 sysfs_close_class(cls);
255 sysfs_close_list(subsyslist);
260 static int process_options(void)
262 static const char short_options[] = "adn:p:q:rsVh";
268 enum query_type query = NONE;
269 char result[1024] = "";
270 char path[NAME_SIZE] = "";
271 char name[NAME_SIZE] = "";
272 char temp[NAME_SIZE];
275 /* get command line options */
277 option = getopt(main_argc, main_argv, short_options);
281 dbg("option '%c'", option);
284 dbg("udev name: %s\n", optarg);
285 strfieldcpy(name, optarg);
289 dbg("udev path: %s\n", optarg);
290 strfieldcpy(path, optarg);
294 dbg("udev query: %s\n", optarg);
296 if (strcmp(optarg, "name") == 0) {
301 if (strcmp(optarg, "symlink") == 0) {
306 if (strcmp(optarg, "path") == 0) {
311 if (strcmp(optarg, "all") == 0) {
316 printf("unknown query type\n");
324 print_sysfs_devices();
332 printf("udevinfo, version %s\n", UDEV_VERSION);
343 /* process options */
345 if (path[0] != '\0') {
346 /* remove sysfs_path if given */
347 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
348 pos = path + strlen(sysfs_path);
350 if (path[0] != '/') {
351 /* prepend '/' if missing */
352 strfieldcat(temp, "/");
353 strfieldcat(temp, path);
359 memset(&udev, 0x00, sizeof(struct udevice));
360 strfieldcpy(udev.devpath, pos);
361 retval = udevdb_get_dev(&udev);
363 printf("device not found in database\n");
369 if (name[0] != '\0') {
370 /* remove udev_root if given */
371 int len = strlen(udev_root);
373 if (strncmp(name, udev_root, len) == 0) {
378 memset(&udev, 0x00, sizeof(struct udevice));
379 strfieldcpy(udev.name, pos);
380 retval = udevdb_get_dev_byname(&udev, pos);
382 printf("device not found in database\n");
389 printf("query needs device path(-p) or node name(-n) specified\n");
396 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
397 result[NAME_SIZE-1] = '\0';
399 strfieldcpy(result, udev.name);
407 char slink[NAME_SIZE];
410 foreach_strpart(udev.symlink, " \n\r", spos, slen) {
411 strncpy(slink, spos, slen);
413 pos += sprintf(pos, "%s/%s ", udev_root, slink);
416 strfieldcpy(result, udev.symlink);
421 strfieldcpy(result, path);
431 printf("%s\n", result);
438 if (path[0] == '\0') {
439 printf("attribute walk on device chain needs path(-p) specified\n");
442 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
443 /* prepend sysfs mountpoint if not given */
444 strfieldcpy(temp, path);
445 strfieldcpy(path, sysfs_path);
446 strfieldcat(path, temp);
448 print_device_chain(path);
454 printf("%s\n", udev_root);
459 printf("Usage: [-anpqrdVh]\n"
460 " -q TYPE query database for the specified value:\n"
461 " 'name' name of device node\n"
462 " 'symlink' pointing to node\n"
463 " 'path' sysfs device path\n"
464 " 'all' all values\n"
466 " -p PATH sysfs device path used for query or chain\n"
467 " -n NAME node/symlink name used for query\n"
469 " -r print udev root\n"
470 " -a print all SYSFS_attributes along the device chain\n"
471 " -s print all sysfs devices with major/minor, physical device and bus\n"
472 " -V print udev version\n"
473 " -h print this help text\n"
478 int main(int argc, char *argv[], char *envp[])
485 logging_init("udevinfo");
487 /* initialize our configuration */
490 rc = process_options();