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 /* callback for database dump */
107 static int print_record(char *path, struct udevice *dev)
109 printf("P: %s\n", path);
110 printf("N: %s\n", dev->name);
111 printf("M: %#o\n", dev->mode);
112 printf("S: %s\n", dev->symlink);
113 printf("O: %s\n", dev->owner);
114 printf("G: %s\n", dev->group);
130 static int print_device_chain(const char *path)
132 struct sysfs_class_device *class_dev;
133 struct sysfs_class_device *class_dev_parent;
134 struct sysfs_attribute *attr;
135 struct sysfs_device *sysfs_dev;
136 struct sysfs_device *sysfs_dev_parent;
139 /* get the class dev */
140 class_dev = sysfs_open_class_device_path(path);
141 if (class_dev == NULL) {
142 printf("couldn't get the class device\n");
146 /* read the 'dev' file for major/minor*/
147 attr = sysfs_get_classdev_attr(class_dev, "dev");
149 printf("couldn't get the \"dev\" file\n");
154 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
155 "device chain, to print for every device found, all possibly useful attributes\n"
156 "in the udev key format.\n"
157 "Only attributes within one device section may be used together in one rule,\n"
158 "to match the device for which the node will be created.\n"
160 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
161 sysfs_close_attribute(attr);
163 /* open sysfs class device directory and print all attributes */
164 printf(" looking at class device '%s':\n", class_dev->path);
165 if (print_all_attributes(class_dev->path) != 0) {
166 printf("couldn't open class device directory\n");
171 /* get the device link (if parent exists look here) */
172 class_dev_parent = sysfs_get_classdev_parent(class_dev);
173 if (class_dev_parent != NULL) {
174 //sysfs_close_class_device(class_dev);
175 class_dev = class_dev_parent;
177 sysfs_dev = sysfs_get_classdev_device(class_dev);
178 if (sysfs_dev != NULL)
179 printf("follow the class device's \"device\"\n");
181 /* look the device chain upwards */
182 while (sysfs_dev != NULL) {
183 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
184 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
185 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
187 /* open sysfs device directory and print all attributes */
188 print_all_attributes(sysfs_dev->path);
190 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
191 if (sysfs_dev_parent == NULL)
194 //sysfs_close_device(sysfs_dev);
195 sysfs_dev = sysfs_dev_parent;
197 sysfs_close_device(sysfs_dev);
200 //sysfs_close_class_device(class_dev);
204 static int process_options(void)
206 static const char short_options[] = "adn:p:q:rVh";
212 enum query_type query = NONE;
213 char result[NAME_SIZE] = "";
214 char path[NAME_SIZE] = "";
215 char name[NAME_SIZE] = "";
216 char temp[NAME_SIZE];
219 /* get command line options */
221 option = getopt(main_argc, main_argv, short_options);
225 dbg("option '%c'", option);
228 dbg("udev name: %s\n", optarg);
229 strfieldcpy(name, optarg);
233 dbg("udev path: %s\n", optarg);
234 strfieldcpy(path, optarg);
238 dbg("udev query: %s\n", optarg);
240 if (strcmp(optarg, "name") == 0) {
245 if (strcmp(optarg, "symlink") == 0) {
250 if (strcmp(optarg, "mode") == 0) {
255 if (strcmp(optarg, "owner") == 0) {
260 if (strcmp(optarg, "group") == 0) {
265 if (strcmp(optarg, "path") == 0) {
270 if (strcmp(optarg, "all") == 0) {
275 printf("unknown query type\n");
287 retval = udevdb_open_ro();
289 printf("unable to open udev database\n");
292 udevdb_call_foreach(print_record);
297 printf("udevinfo, version %s\n", UDEV_VERSION);
308 /* process options */
310 retval = udevdb_open_ro();
312 printf("unable to open udev database\n");
316 if (path[0] != '\0') {
317 /* remove sysfs_path if given */
318 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
319 pos = path + strlen(sysfs_path);
321 if (path[0] != '/') {
322 /* prepend '/' if missing */
323 strfieldcat(temp, "/");
324 strfieldcat(temp, path);
330 retval = udevdb_get_dev(pos, &dev);
332 printf("device not found in database\n");
338 if (name[0] != '\0') {
339 /* remove udev_root if given */
340 if (strncmp(name, udev_root, strlen(udev_root)) == 0) {
341 pos = name + strlen(udev_root);
344 retval = udevdb_get_dev_byname(pos, path, &dev);
346 printf("device not found in database\n");
352 printf("query needs device path(-p) or node name(-n) specified\n");
359 strfieldcpy(result, udev_root);
360 strfieldcat(result, dev.name);
364 strfieldcpy(result, dev.symlink);
368 sprintf(result, "%#o", dev.mode);
372 strfieldcpy(result, dev.group);
376 strfieldcpy(result, dev.owner);
380 strfieldcpy(result, path);
384 print_record(path, &dev);
390 printf("%s\n", result);
398 if (path[0] == '\0') {
399 printf("attribute walk on device chain needs path(-p) specified\n");
402 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
403 /* prepend sysfs mountpoint if not given */
404 strfieldcpy(temp, path);
405 strfieldcpy(path, sysfs_path);
406 strfieldcat(path, temp);
408 print_device_chain(path);
414 printf("%s\n", udev_root);
419 printf("Usage: [-anpqrdVh]\n"
420 " -q TYPE query database for the specified value:\n"
421 " 'name' name of device node\n"
422 " 'symlink' pointing to node\n"
423 " 'mode' permissions of node\n"
426 " 'path' sysfs device path\n"
427 " 'all' all values\n"
429 " -p PATH sysfs device path used for query or chain\n"
430 " -n NAME node/symlink name used for query\n"
432 " -r print udev root\n"
433 " -a print all SYSFS_attributes along the device chain\n"
434 " -d dump whole database\n"
435 " -V print udev version\n"
436 " -h print this help text\n"
441 int main(int argc, char *argv[], char *envp[])
448 init_logging("udevinfo");
450 /* initialize our configuration */
453 retval = process_options();