2 * udevinfo.c - fetches stored device information or sysfs attributes
4 * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 void log_message (int priority, const char *format, ...)
39 if (priority > udev_log_priority)
42 va_start(args, format);
43 vsyslog(priority, format, args);
48 static void print_all_attributes(const char *devpath, const char *key)
54 strlcpy(path, sysfs_path, sizeof(path));
55 strlcat(path, devpath, sizeof(path));
59 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
61 char value[NAME_SIZE];
64 attr_value = sysfs_attr_get_value(devpath, dent->d_name);
65 if (attr_value == NULL)
67 len = strlcpy(value, attr_value, sizeof(value));
68 dbg("attr '%s'='%s'(%zi)", dent->d_name, value, len);
70 /* remove trailing newlines */
71 while (len && value[len-1] == '\n')
74 /* skip nonprintable attributes */
75 while (len && isprint(value[len-1]))
78 dbg("attribute value of '%s' non-printable, skip", dent->d_name);
82 replace_untrusted_chars(value);
83 printf(" %s{%s}==\"%s\"\n", key, dent->d_name, value);
89 static int print_device_chain(const char *devpath)
91 struct sysfs_device *dev;
94 "Udevinfo starts with the device specified by the devpath and then\n"
95 "walks up the chain of parent devices. It prints for every device\n"
96 "found, all possible attributes in the udev rules key format.\n"
97 "A rule to match, can be composed by the attributes of the device\n"
98 "and the attributes from one single parent device.\n"
101 dev = sysfs_device_get(devpath);
105 printf(" looking at device '%s':\n", dev->devpath);
106 printf(" KERNEL==\"%s\"\n", dev->kernel);
107 printf(" SUBSYSTEM==\"%s\"\n", dev->subsystem);
108 printf(" DRIVER==\"%s\"\n", dev->driver);
109 print_all_attributes(dev->devpath, "ATTR");
111 /* walk up the chain of devices */
113 dev = sysfs_device_get_parent(dev);
116 printf(" looking at parent device '%s':\n", dev->devpath);
117 printf(" KERNELS==\"%s\"\n", dev->kernel);
118 printf(" SUBSYTEMS==\"%s\"\n", dev->subsystem);
119 printf(" DRIVERS==\"%s\"\n", dev->driver);
121 print_all_attributes(dev->devpath, "ATTRS");
127 static void print_record(struct udevice *udev)
129 struct name_entry *name_loop;
131 printf("P: %s\n", udev->dev->devpath);
132 printf("N: %s\n", udev->name);
133 list_for_each_entry(name_loop, &udev->symlink_list, node)
134 printf("S: %s\n", name_loop->name);
135 list_for_each_entry(name_loop, &udev->env_list, node)
136 printf("E: %s\n", name_loop->name);
139 static void export_name_devpath(struct udevice *udev) {
140 printf("%s=%s/%s\n", udev->dev->devpath, udev_root, udev->name);
143 static void export_record(struct udevice *udev) {
148 static void export_db(void fnct(struct udevice *udev)) {
149 LIST_HEAD(name_list);
150 struct name_entry *name_loop;
152 udev_db_get_all_entries(&name_list);
153 list_for_each_entry(name_loop, &name_list, node) {
154 struct udevice *udev_db;
156 udev_db = udev_device_init();
159 if (udev_db_get_device(udev_db, name_loop->name) == 0)
161 udev_device_cleanup(udev_db);
163 name_list_cleanup(&name_list);
166 int main(int argc, char *argv[], char *envp[])
169 struct udevice *udev;
175 ACTION_ATTRIBUTE_WALK,
177 } action = ACTION_NONE;
186 } query = QUERY_NONE;
188 char path[PATH_SIZE] = "";
189 char name[PATH_SIZE] = "";
190 struct name_entry *name_loop;
193 logging_init("udevinfo");
197 udev = udev_device_init();
203 /* get command line options */
206 option = getopt(argc, argv, ":aden:p:q:rVh");
210 dbg("option '%c'", option);
213 /* remove /dev if given */
214 if (strncmp(optarg, udev_root, strlen(udev_root)) == 0)
215 strlcpy(name, &optarg[strlen(udev_root)+1], sizeof(name));
217 strlcpy(name, optarg, sizeof(name));
218 dbg("name: %s\n", name);
221 /* remove /sys if given */
222 if (strncmp(optarg, sysfs_path, strlen(sysfs_path)) == 0)
223 strlcpy(path, &optarg[strlen(sysfs_path)], sizeof(path));
225 strlcpy(path, optarg, sizeof(path));
226 dbg("path: %s\n", path);
229 dbg("udev query: %s\n", optarg);
230 action = ACTION_QUERY;
231 if (strcmp(optarg, "name") == 0) {
235 if (strcmp(optarg, "symlink") == 0) {
236 query = QUERY_SYMLINK;
239 if (strcmp(optarg, "path") == 0) {
243 if (strcmp(optarg, "env") == 0) {
247 if (strcmp(optarg, "all") == 0) {
251 fprintf(stderr, "unknown query type\n");
255 if (action == ACTION_NONE)
256 action = ACTION_ROOT;
260 action = ACTION_ATTRIBUTE_WALK;
263 export_db(export_name_devpath);
266 export_db(export_record);
269 printf("udevinfo, version %s\n", UDEV_VERSION);
272 printf("Usage: udevinfo [-anpqrVh]\n"
273 " -q TYPE query database for the specified value:\n"
274 " 'name' name of device node\n"
275 " 'symlink' pointing to node\n"
276 " 'path' sysfs device path\n"
277 " 'env' the device related imported environment\n"
278 " 'all' all values\n"
280 " -p PATH sysfs device path used for query or chain\n"
281 " -n NAME node/symlink name used for query\n"
283 " -r prepend to query result or print udev_root\n"
284 " -a print all SYSFS_attributes along the device chain\n"
285 " -e export the content of the udev database\n"
286 " -V print udev version\n"
287 " -h print this help text\n"
291 fprintf(stderr, "missing argument for '%c'\n", optopt);
295 fprintf(stderr, "unrecognized option '%c'\n", optopt);
303 /* needs devpath or node/symlink name for query */
304 if (path[0] != '\0') {
305 if (udev_db_get_device(udev, path) != 0) {
306 fprintf(stderr, "no record for '%s' in database\n", path);
310 } else if (name[0] != '\0') {
311 char devpath[PATH_SIZE];
313 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
314 fprintf(stderr, "node name not found\n");
318 udev_db_get_device(udev, devpath);
320 fprintf(stderr, "query needs device path(-p) or node name(-n) specified\n");
328 printf("%s/%s\n", udev_root, udev->name);
330 printf("%s\n", udev->name);
333 if (list_empty(&udev->symlink_list))
336 list_for_each_entry(name_loop, &udev->symlink_list, node)
337 printf("%s/%s ", udev_root, name_loop->name);
339 list_for_each_entry(name_loop, &udev->symlink_list, node)
340 printf("%s ", name_loop->name);
344 printf("%s\n", udev->dev->devpath);
347 list_for_each_entry(name_loop, &udev->env_list, node)
348 printf("%s\n", name_loop->name);
354 fprintf(stderr, "unknown query type\n");
358 case ACTION_ATTRIBUTE_WALK:
359 if (path[0] != '\0') {
360 print_device_chain(path);
361 } else if (name[0] != '\0') {
362 char devpath[PATH_SIZE];
364 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
365 fprintf(stderr, "node name not found\n");
369 print_device_chain(devpath);
371 fprintf(stderr, "attribute walk needs device path(-p) or node name(-n) specified\n");
377 printf("%s\n", udev_root);
380 fprintf(stderr, "missing option\n");
386 udev_device_cleanup(udev);