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 static void print_help(void)
168 fprintf(stderr, "Usage: udevinfo [-anpqrVh]\n"
169 " -q TYPE query database for the specified value:\n"
170 " 'name' name of device node\n"
171 " 'symlink' pointing to node\n"
172 " 'path' sysfs device path\n"
173 " 'env' the device related imported environment\n"
174 " 'all' all values\n"
176 " -p PATH sysfs device path used for query or chain\n"
177 " -n NAME node/symlink name used for query\n"
179 " -r prepend to query result or print udev_root\n"
180 " -a print all SYSFS_attributes along the device chain\n"
181 " -e export the content of the udev database\n"
182 " -V print udev version\n"
183 " -h print this help text\n"
187 int main(int argc, char *argv[], char *envp[])
189 static const char short_options[] = "aden:p:q:rVh";
191 struct udevice *udev;
197 ACTION_ATTRIBUTE_WALK,
199 } action = ACTION_NONE;
208 } query = QUERY_NONE;
210 char path[PATH_SIZE] = "";
211 char name[PATH_SIZE] = "";
212 struct name_entry *name_loop;
215 logging_init("udevinfo");
220 udev = udev_device_init();
226 /* get command line options */
228 option = getopt(argc, argv, short_options);
232 dbg("option '%c'", option);
235 /* remove /dev if given */
236 if (strncmp(optarg, udev_root, strlen(udev_root)) == 0)
237 strlcpy(name, &optarg[strlen(udev_root)+1], sizeof(name));
239 strlcpy(name, optarg, sizeof(name));
240 dbg("name: %s\n", name);
243 /* remove /sys if given */
244 if (strncmp(optarg, sysfs_path, strlen(sysfs_path)) == 0)
245 strlcpy(path, &optarg[strlen(sysfs_path)], sizeof(path));
247 strlcpy(path, optarg, sizeof(path));
248 dbg("path: %s\n", path);
251 dbg("udev query: %s\n", optarg);
252 action = ACTION_QUERY;
253 if (strcmp(optarg, "name") == 0) {
257 if (strcmp(optarg, "symlink") == 0) {
258 query = QUERY_SYMLINK;
261 if (strcmp(optarg, "path") == 0) {
265 if (strcmp(optarg, "env") == 0) {
269 if (strcmp(optarg, "all") == 0) {
273 fprintf(stderr, "unknown query type\n");
277 if (action == ACTION_NONE)
278 action = ACTION_ROOT;
282 action = ACTION_ATTRIBUTE_WALK;
285 export_db(export_name_devpath);
288 export_db(export_record);
291 printf("udevinfo, version %s\n", UDEV_VERSION);
304 /* needs devpath or node/symlink name for query */
305 if (path[0] != '\0') {
306 if (udev_db_get_device(udev, path) != 0) {
307 fprintf(stderr, "no record for '%s' in database\n", path);
311 } else if (name[0] != '\0') {
312 char devpath[PATH_SIZE];
314 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
315 fprintf(stderr, "node name not found\n");
319 udev_db_get_device(udev, devpath);
321 fprintf(stderr, "query needs device path(-p) or node name(-n) specified\n");
329 printf("%s/%s\n", udev_root, udev->name);
331 printf("%s\n", udev->name);
334 if (list_empty(&udev->symlink_list))
337 list_for_each_entry(name_loop, &udev->symlink_list, node)
338 printf("%s/%s ", udev_root, name_loop->name);
340 list_for_each_entry(name_loop, &udev->symlink_list, node)
341 printf("%s ", name_loop->name);
345 printf("%s\n", udev->dev->devpath);
348 list_for_each_entry(name_loop, &udev->env_list, node)
349 printf("%s\n", name_loop->name);
359 case ACTION_ATTRIBUTE_WALK:
360 if (path[0] != '\0') {
361 print_device_chain(path);
362 } else if (name[0] != '\0') {
363 char devpath[PATH_SIZE];
365 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
366 fprintf(stderr, "node name not found\n");
370 print_device_chain(devpath);
372 fprintf(stderr, "attribute walk needs device path(-p) or node name(-n) specified\n");
378 printf("%s\n", udev_root);
387 udev_device_cleanup(udev);