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);
115 printf("F: %s\n", dev->config_file);
116 printf("L: %i\n", dev->config_line);
117 printf("T: %li\n", dev->config_time);
133 static int print_device_chain(const char *path)
135 struct sysfs_class_device *class_dev;
136 struct sysfs_class_device *class_dev_parent;
137 struct sysfs_attribute *attr;
138 struct sysfs_device *sysfs_dev;
139 struct sysfs_device *sysfs_dev_parent;
142 /* get the class dev */
143 class_dev = sysfs_open_class_device_path(path);
144 if (class_dev == NULL) {
145 printf("couldn't get the class device\n");
149 /* read the 'dev' file for major/minor*/
150 attr = sysfs_get_classdev_attr(class_dev, "dev");
152 printf("couldn't get the \"dev\" file\n");
157 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
158 "device chain, to print for every device found, all possibly useful attributes\n"
159 "in the udev key format.\n"
160 "Only attributes within one device section may be used together in one rule,\n"
161 "to match the device for which the node will be created.\n"
163 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
165 /* open sysfs class device directory and print all attributes */
166 printf(" looking at class device '%s':\n", class_dev->path);
167 if (print_all_attributes(class_dev->path) != 0) {
168 printf("couldn't open class device directory\n");
173 /* get the device link (if parent exists look here) */
174 class_dev_parent = sysfs_get_classdev_parent(class_dev);
175 if (class_dev_parent != NULL)
176 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
178 sysfs_dev = sysfs_get_classdev_device(class_dev);
180 if (sysfs_dev != NULL)
181 printf("follow the class device's \"device\"\n");
183 /* look the device chain upwards */
184 while (sysfs_dev != NULL) {
185 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
186 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
187 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
189 /* open sysfs device directory and print all attributes */
190 print_all_attributes(sysfs_dev->path);
192 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
193 if (sysfs_dev_parent == NULL)
196 sysfs_dev = sysfs_dev_parent;
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();