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("T: %c\n", dev->type);
112 printf("M: %#o\n", dev->mode);
113 printf("S: %s\n", dev->symlink);
114 printf("O: %s\n", dev->owner);
115 printf("G: %s\n", dev->group);
116 printf("F: %s\n", dev->config_file);
117 printf("L: %i\n", dev->config_line);
118 printf("U: %li\n", dev->config_uptime);
134 static int print_device_chain(const char *path)
136 struct sysfs_class_device *class_dev;
137 struct sysfs_class_device *class_dev_parent;
138 struct sysfs_attribute *attr;
139 struct sysfs_device *sysfs_dev;
140 struct sysfs_device *sysfs_dev_parent;
144 type = get_device_type(path, "");
145 dbg("device type is %c", type);
147 /* get the class dev */
148 class_dev = sysfs_open_class_device_path(path);
149 if (class_dev == NULL) {
150 printf("couldn't get the class device\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"
161 if (type == 'b' || type =='c') {
162 /* read the 'dev' file for major/minor*/
163 attr = sysfs_get_classdev_attr(class_dev, "dev");
165 printf("couldn't get the \"dev\" file\n");
169 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
172 /* open sysfs class device directory and print all attributes */
173 printf(" looking at class device '%s':\n", class_dev->path);
174 if (print_all_attributes(class_dev->path) != 0) {
175 printf("couldn't open class device directory\n");
180 /* get the device link (if parent exists look here) */
181 class_dev_parent = sysfs_get_classdev_parent(class_dev);
182 if (class_dev_parent != NULL)
183 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
185 sysfs_dev = sysfs_get_classdev_device(class_dev);
187 if (sysfs_dev != NULL)
188 printf("follow the class device's \"device\"\n");
190 /* look the device chain upwards */
191 while (sysfs_dev != NULL) {
192 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
193 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
194 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
196 /* open sysfs device directory and print all attributes */
197 print_all_attributes(sysfs_dev->path);
199 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
200 if (sysfs_dev_parent == NULL)
203 sysfs_dev = sysfs_dev_parent;
207 sysfs_close_class_device(class_dev);
211 static int process_options(void)
213 static const char short_options[] = "adn:p:q:rVh";
219 enum query_type query = NONE;
220 char result[NAME_SIZE] = "";
221 char path[NAME_SIZE] = "";
222 char name[NAME_SIZE] = "";
223 char temp[NAME_SIZE];
226 /* get command line options */
228 option = getopt(main_argc, main_argv, short_options);
232 dbg("option '%c'", option);
235 dbg("udev name: %s\n", optarg);
236 strfieldcpy(name, optarg);
240 dbg("udev path: %s\n", optarg);
241 strfieldcpy(path, optarg);
245 dbg("udev query: %s\n", optarg);
247 if (strcmp(optarg, "name") == 0) {
252 if (strcmp(optarg, "symlink") == 0) {
257 if (strcmp(optarg, "mode") == 0) {
262 if (strcmp(optarg, "owner") == 0) {
267 if (strcmp(optarg, "group") == 0) {
272 if (strcmp(optarg, "path") == 0) {
277 if (strcmp(optarg, "all") == 0) {
282 printf("unknown query type\n");
294 retval = udevdb_open_ro();
296 printf("unable to open udev database\n");
299 udevdb_call_foreach(print_record);
304 printf("udevinfo, version %s\n", UDEV_VERSION);
315 /* process options */
317 retval = udevdb_open_ro();
319 printf("unable to open udev database\n");
323 if (path[0] != '\0') {
324 /* remove sysfs_path if given */
325 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
326 pos = path + strlen(sysfs_path);
328 if (path[0] != '/') {
329 /* prepend '/' if missing */
330 strfieldcat(temp, "/");
331 strfieldcat(temp, path);
337 retval = udevdb_get_dev(pos, &dev);
339 printf("device not found in database\n");
345 if (name[0] != '\0') {
346 /* remove udev_root if given */
347 if (strncmp(name, udev_root, strlen(udev_root)) == 0) {
348 pos = name + strlen(udev_root);
351 retval = udevdb_get_dev_byname(pos, path, &dev);
353 printf("device not found in database\n");
359 printf("query needs device path(-p) or node name(-n) specified\n");
366 strfieldcpy(result, udev_root);
367 strfieldcat(result, dev.name);
371 strfieldcpy(result, dev.symlink);
375 sprintf(result, "%#o", dev.mode);
379 strfieldcpy(result, dev.group);
383 strfieldcpy(result, dev.owner);
387 strfieldcpy(result, path);
391 print_record(path, &dev);
397 printf("%s\n", result);
405 if (path[0] == '\0') {
406 printf("attribute walk on device chain needs path(-p) specified\n");
409 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
410 /* prepend sysfs mountpoint if not given */
411 strfieldcpy(temp, path);
412 strfieldcpy(path, sysfs_path);
413 strfieldcat(path, temp);
415 print_device_chain(path);
421 printf("%s\n", udev_root);
426 printf("Usage: [-anpqrdVh]\n"
427 " -q TYPE query database for the specified value:\n"
428 " 'name' name of device node\n"
429 " 'symlink' pointing to node\n"
430 " 'mode' permissions of node\n"
433 " 'path' sysfs device path\n"
434 " 'all' all values\n"
436 " -p PATH sysfs device path used for query or chain\n"
437 " -n NAME node/symlink name used for query\n"
439 " -r print udev root\n"
440 " -a print all SYSFS_attributes along the device chain\n"
441 " -d dump whole database\n"
442 " -V print udev version\n"
443 " -h print this help text\n"
448 int main(int argc, char *argv[], char *envp[])
455 init_logging("udevinfo");
457 /* initialize our configuration */
460 retval = process_options();