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_version.h"
38 # define SYSFS_VALUE_MAX 200
44 unsigned char logname[LOGNAME_SIZE];
45 void log_message (int level, const char *format, ...)
49 va_start(args, format);
50 vsyslog(level, format, args);
55 static int print_all_attributes(const char *path)
57 struct dlist *attributes;
58 struct sysfs_attribute *attr;
59 struct sysfs_directory *sysfs_dir;
60 char value[SYSFS_VALUE_MAX];
64 sysfs_dir = sysfs_open_directory(path);
65 if (sysfs_dir == NULL)
68 attributes = sysfs_get_dir_attributes(sysfs_dir);
69 if (attributes == NULL) {
74 dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
75 if (attr->value != NULL) {
76 strfieldcpy(value, attr->value);
81 /* remove trailing newline */
82 if (value[len-1] == '\n') {
87 /* skip nonprintable values */
89 if (isprint(value[len-1]) == 0)
94 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
100 sysfs_close_directory(sysfs_dir);
105 /* callback for database dump */
106 static int print_record(char *path, struct udevice *dev)
108 printf("P: %s\n", path);
109 printf("N: %s\n", dev->name);
110 printf("M: %#o\n", dev->mode);
111 printf("S: %s\n", dev->symlink);
112 printf("O: %s\n", dev->owner);
113 printf("G: %s\n", dev->group);
129 static int print_device_chain(const char *path)
131 struct sysfs_class_device *class_dev;
132 struct sysfs_class_device *class_dev_parent;
133 struct sysfs_attribute *attr;
134 struct sysfs_device *sysfs_dev;
135 struct sysfs_device *sysfs_dev_parent;
138 /* get the class dev */
139 class_dev = sysfs_open_class_device_path(path);
140 if (class_dev == NULL) {
141 printf("couldn't get the class device\n");
145 /* read the 'dev' file for major/minor*/
146 attr = sysfs_get_classdev_attr(class_dev, "dev");
148 printf("couldn't get the \"dev\" file\n");
153 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
154 "device chain, to print for every device found, all possibly useful attributes\n"
155 "in the udev key format.\n"
156 "Only attributes within one device section may be used together in one rule,\n"
157 "to match the device for which the node will be created.\n"
159 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
160 sysfs_close_attribute(attr);
162 /* open sysfs class device directory and print all attributes */
163 printf(" looking at class device '%s':\n", class_dev->path);
164 if (print_all_attributes(class_dev->path) != 0) {
165 printf("couldn't open class device directory\n");
170 /* get the device link (if parent exists look here) */
171 class_dev_parent = sysfs_get_classdev_parent(class_dev);
172 if (class_dev_parent != NULL) {
173 //sysfs_close_class_device(class_dev);
174 class_dev = class_dev_parent;
176 sysfs_dev = sysfs_get_classdev_device(class_dev);
177 if (sysfs_dev != NULL)
178 printf("follow the class device's \"device\"\n");
180 /* look the device chain upwards */
181 while (sysfs_dev != NULL) {
182 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
183 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
184 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
186 /* open sysfs device directory and print all attributes */
187 print_all_attributes(sysfs_dev->path);
189 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
190 if (sysfs_dev_parent == NULL)
193 //sysfs_close_device(sysfs_dev);
194 sysfs_dev = sysfs_dev_parent;
196 sysfs_close_device(sysfs_dev);
199 //sysfs_close_class_device(class_dev);
203 static int process_options(void)
205 static const char short_options[] = "adn:p:q:rVh";
211 enum query_type query = NONE;
212 char result[NAME_SIZE] = "";
213 char path[NAME_SIZE] = "";
214 char name[NAME_SIZE] = "";
215 char temp[NAME_SIZE];
218 /* get command line options */
220 option = getopt(main_argc, main_argv, short_options);
224 dbg("option '%c'", option);
227 dbg("udev name: %s\n", optarg);
228 strfieldcpy(name, optarg);
232 dbg("udev path: %s\n", optarg);
233 strfieldcpy(path, optarg);
237 dbg("udev query: %s\n", optarg);
239 if (strcmp(optarg, "name") == 0) {
244 if (strcmp(optarg, "symlink") == 0) {
249 if (strcmp(optarg, "mode") == 0) {
254 if (strcmp(optarg, "owner") == 0) {
259 if (strcmp(optarg, "group") == 0) {
264 if (strcmp(optarg, "path") == 0) {
269 if (strcmp(optarg, "all") == 0) {
274 printf("unknown query type\n");
286 retval = udevdb_open_ro();
288 printf("unable to open udev database\n");
291 udevdb_call_foreach(print_record);
296 printf("udevinfo, version %s\n", UDEV_VERSION);
307 /* process options */
309 retval = udevdb_open_ro();
311 printf("unable to open udev database\n");
315 if (path[0] != '\0') {
316 /* remove sysfs_path if given */
317 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
318 pos = path + strlen(sysfs_path);
320 if (path[0] != '/') {
321 /* prepend '/' if missing */
322 strfieldcat(temp, "/");
323 strfieldcat(temp, path);
329 retval = udevdb_get_dev(pos, &dev);
331 printf("device not found in database\n");
337 if (name[0] != '\0') {
338 /* remove udev_root if given */
339 if (strncmp(name, udev_root, strlen(udev_root)) == 0) {
340 pos = name + strlen(udev_root);
343 retval = udevdb_get_dev_byname(pos, path, &dev);
345 printf("device not found in database\n");
351 printf("query needs device path(-p) or node name(-n) specified\n");
358 strfieldcpy(result, udev_root);
359 strfieldcat(result, dev.name);
363 strfieldcpy(result, dev.symlink);
367 sprintf(result, "%#o", dev.mode);
371 strfieldcpy(result, dev.group);
375 strfieldcpy(result, dev.owner);
379 strfieldcpy(result, path);
383 print_record(path, &dev);
389 printf("%s\n", result);
397 if (path[0] == '\0') {
398 printf("attribute walk on device chain needs path(-p) specified\n");
401 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
402 /* prepend sysfs mountpoint if not given */
403 strfieldcpy(temp, path);
404 strfieldcpy(path, sysfs_path);
405 strfieldcat(path, temp);
407 print_device_chain(path);
413 printf("%s\n", udev_root);
418 printf("Usage: [-anpqrdVh]\n"
419 " -q TYPE query database for the specified value:\n"
420 " 'name' name of device node\n"
421 " 'symlink' pointing to node\n"
422 " 'mode' permissions of node\n"
425 " 'path' sysfs device path\n"
426 " 'all' all values\n"
428 " -p PATH sysfs device path used for query or chain\n"
429 " -n NAME node/symlink name used for query\n"
431 " -r print udev root\n"
432 " -a print all SYSFS_attributes along the device chain\n"
433 " -d dump whole database\n"
434 " -V print udev version\n"
435 " -h print this help text\n"
440 int main(int argc, char *argv[], char *envp[])
447 init_logging("udevinfo");
449 /* initialize our configuration */
452 retval = process_options();