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;
143 type = get_device_type(path, "");
144 dbg("device type is %c", type);
146 /* get the class dev */
147 class_dev = sysfs_open_class_device_path(path);
148 if (class_dev == NULL) {
149 printf("couldn't get the class device\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"
160 if (type == 'b' || type =='c') {
161 /* read the 'dev' file for major/minor*/
162 attr = sysfs_get_classdev_attr(class_dev, "dev");
164 printf("couldn't get the \"dev\" file\n");
168 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
171 /* open sysfs class device directory and print all attributes */
172 printf(" looking at class device '%s':\n", class_dev->path);
173 if (print_all_attributes(class_dev->path) != 0) {
174 printf("couldn't open class device directory\n");
179 /* get the device link (if parent exists look here) */
180 class_dev_parent = sysfs_get_classdev_parent(class_dev);
181 if (class_dev_parent != NULL)
182 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
184 sysfs_dev = sysfs_get_classdev_device(class_dev);
186 if (sysfs_dev != NULL)
187 printf("follow the class device's \"device\"\n");
189 /* look the device chain upwards */
190 while (sysfs_dev != NULL) {
191 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
192 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
193 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
195 /* open sysfs device directory and print all attributes */
196 print_all_attributes(sysfs_dev->path);
198 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
199 if (sysfs_dev_parent == NULL)
202 sysfs_dev = sysfs_dev_parent;
206 sysfs_close_class_device(class_dev);
210 static int process_options(void)
212 static const char short_options[] = "adn:p:q:rVh";
218 enum query_type query = NONE;
219 char result[NAME_SIZE] = "";
220 char path[NAME_SIZE] = "";
221 char name[NAME_SIZE] = "";
222 char temp[NAME_SIZE];
225 /* get command line options */
227 option = getopt(main_argc, main_argv, short_options);
231 dbg("option '%c'", option);
234 dbg("udev name: %s\n", optarg);
235 strfieldcpy(name, optarg);
239 dbg("udev path: %s\n", optarg);
240 strfieldcpy(path, optarg);
244 dbg("udev query: %s\n", optarg);
246 if (strcmp(optarg, "name") == 0) {
251 if (strcmp(optarg, "symlink") == 0) {
256 if (strcmp(optarg, "mode") == 0) {
261 if (strcmp(optarg, "owner") == 0) {
266 if (strcmp(optarg, "group") == 0) {
271 if (strcmp(optarg, "path") == 0) {
276 if (strcmp(optarg, "all") == 0) {
281 printf("unknown query type\n");
293 retval = udevdb_open_ro();
295 printf("unable to open udev database\n");
298 udevdb_call_foreach(print_record);
303 printf("udevinfo, version %s\n", UDEV_VERSION);
314 /* process options */
316 retval = udevdb_open_ro();
318 printf("unable to open udev database\n");
322 if (path[0] != '\0') {
323 /* remove sysfs_path if given */
324 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
325 pos = path + strlen(sysfs_path);
327 if (path[0] != '/') {
328 /* prepend '/' if missing */
329 strfieldcat(temp, "/");
330 strfieldcat(temp, path);
336 retval = udevdb_get_dev(pos, &dev);
338 printf("device not found in database\n");
344 if (name[0] != '\0') {
345 /* remove udev_root if given */
346 if (strncmp(name, udev_root, strlen(udev_root)) == 0) {
347 pos = name + strlen(udev_root);
350 retval = udevdb_get_dev_byname(pos, path, &dev);
352 printf("device not found in database\n");
358 printf("query needs device path(-p) or node name(-n) specified\n");
365 strfieldcpy(result, udev_root);
366 strfieldcat(result, dev.name);
370 strfieldcpy(result, dev.symlink);
374 sprintf(result, "%#o", dev.mode);
378 strfieldcpy(result, dev.group);
382 strfieldcpy(result, dev.owner);
386 strfieldcpy(result, path);
390 print_record(path, &dev);
396 printf("%s\n", result);
404 if (path[0] == '\0') {
405 printf("attribute walk on device chain needs path(-p) specified\n");
408 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
409 /* prepend sysfs mountpoint if not given */
410 strfieldcpy(temp, path);
411 strfieldcpy(path, sysfs_path);
412 strfieldcat(path, temp);
414 print_device_chain(path);
420 printf("%s\n", udev_root);
425 printf("Usage: [-anpqrdVh]\n"
426 " -q TYPE query database for the specified value:\n"
427 " 'name' name of device node\n"
428 " 'symlink' pointing to node\n"
429 " 'mode' permissions of node\n"
432 " 'path' sysfs device path\n"
433 " 'all' all values\n"
435 " -p PATH sysfs device path used for query or chain\n"
436 " -n NAME node/symlink name used for query\n"
438 " -r print udev root\n"
439 " -a print all SYSFS_attributes along the device chain\n"
440 " -d dump whole database\n"
441 " -V print udev version\n"
442 " -h print this help text\n"
447 int main(int argc, char *argv[], char *envp[])
454 init_logging("udevinfo");
456 /* initialize our configuration */
459 retval = process_options();