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);
164 sysfs_close_attribute(attr);
166 /* open sysfs class device directory and print all attributes */
167 printf(" looking at class device '%s':\n", class_dev->path);
168 if (print_all_attributes(class_dev->path) != 0) {
169 printf("couldn't open class device directory\n");
174 /* get the device link (if parent exists look here) */
175 class_dev_parent = sysfs_get_classdev_parent(class_dev);
176 if (class_dev_parent != NULL) {
177 //sysfs_close_class_device(class_dev);
178 class_dev = class_dev_parent;
180 sysfs_dev = sysfs_get_classdev_device(class_dev);
181 if (sysfs_dev != NULL)
182 printf("follow the class device's \"device\"\n");
184 /* look the device chain upwards */
185 while (sysfs_dev != NULL) {
186 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
187 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
188 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
190 /* open sysfs device directory and print all attributes */
191 print_all_attributes(sysfs_dev->path);
193 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
194 if (sysfs_dev_parent == NULL)
197 //sysfs_close_device(sysfs_dev);
198 sysfs_dev = sysfs_dev_parent;
200 sysfs_close_device(sysfs_dev);
203 //sysfs_close_class_device(class_dev);
207 static int process_options(void)
209 static const char short_options[] = "adn:p:q:rVh";
215 enum query_type query = NONE;
216 char result[NAME_SIZE] = "";
217 char path[NAME_SIZE] = "";
218 char name[NAME_SIZE] = "";
219 char temp[NAME_SIZE];
222 /* get command line options */
224 option = getopt(main_argc, main_argv, short_options);
228 dbg("option '%c'", option);
231 dbg("udev name: %s\n", optarg);
232 strfieldcpy(name, optarg);
236 dbg("udev path: %s\n", optarg);
237 strfieldcpy(path, optarg);
241 dbg("udev query: %s\n", optarg);
243 if (strcmp(optarg, "name") == 0) {
248 if (strcmp(optarg, "symlink") == 0) {
253 if (strcmp(optarg, "mode") == 0) {
258 if (strcmp(optarg, "owner") == 0) {
263 if (strcmp(optarg, "group") == 0) {
268 if (strcmp(optarg, "path") == 0) {
273 if (strcmp(optarg, "all") == 0) {
278 printf("unknown query type\n");
290 retval = udevdb_open_ro();
292 printf("unable to open udev database\n");
295 udevdb_call_foreach(print_record);
300 printf("udevinfo, version %s\n", UDEV_VERSION);
311 /* process options */
313 retval = udevdb_open_ro();
315 printf("unable to open udev database\n");
319 if (path[0] != '\0') {
320 /* remove sysfs_path if given */
321 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
322 pos = path + strlen(sysfs_path);
324 if (path[0] != '/') {
325 /* prepend '/' if missing */
326 strfieldcat(temp, "/");
327 strfieldcat(temp, path);
333 retval = udevdb_get_dev(pos, &dev);
335 printf("device not found in database\n");
341 if (name[0] != '\0') {
342 /* remove udev_root if given */
343 if (strncmp(name, udev_root, strlen(udev_root)) == 0) {
344 pos = name + strlen(udev_root);
347 retval = udevdb_get_dev_byname(pos, path, &dev);
349 printf("device not found in database\n");
355 printf("query needs device path(-p) or node name(-n) specified\n");
362 strfieldcpy(result, udev_root);
363 strfieldcat(result, dev.name);
367 strfieldcpy(result, dev.symlink);
371 sprintf(result, "%#o", dev.mode);
375 strfieldcpy(result, dev.group);
379 strfieldcpy(result, dev.owner);
383 strfieldcpy(result, path);
387 print_record(path, &dev);
393 printf("%s\n", result);
401 if (path[0] == '\0') {
402 printf("attribute walk on device chain needs path(-p) specified\n");
405 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
406 /* prepend sysfs mountpoint if not given */
407 strfieldcpy(temp, path);
408 strfieldcpy(path, sysfs_path);
409 strfieldcat(path, temp);
411 print_device_chain(path);
417 printf("%s\n", udev_root);
422 printf("Usage: [-anpqrdVh]\n"
423 " -q TYPE query database for the specified value:\n"
424 " 'name' name of device node\n"
425 " 'symlink' pointing to node\n"
426 " 'mode' permissions of node\n"
429 " 'path' sysfs device path\n"
430 " 'all' all values\n"
432 " -p PATH sysfs device path used for query or chain\n"
433 " -n NAME node/symlink name used for query\n"
435 " -r print udev root\n"
436 " -a print all SYSFS_attributes along the device chain\n"
437 " -d dump whole database\n"
438 " -V print udev version\n"
439 " -h print this help text\n"
444 int main(int argc, char *argv[], char *envp[])
451 init_logging("udevinfo");
453 /* initialize our configuration */
456 retval = process_options();