2 * Copyright (C) 2004-2006 Kay Sievers <kay.sievers@vrfy.org>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
33 void log_message (int priority, const char *format, ...)
37 if (priority > udev_log_priority)
40 va_start(args, format);
41 vsyslog(priority, format, args);
46 static void print_all_attributes(const char *devpath, const char *key)
52 strlcpy(path, sysfs_path, sizeof(path));
53 strlcat(path, devpath, sizeof(path));
57 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
59 char value[NAME_SIZE];
62 attr_value = sysfs_attr_get_value(devpath, dent->d_name);
63 if (attr_value == NULL)
65 len = strlcpy(value, attr_value, sizeof(value));
66 dbg("attr '%s'='%s'(%zi)", dent->d_name, value, len);
68 /* remove trailing newlines */
69 while (len && value[len-1] == '\n')
72 /* skip nonprintable attributes */
73 while (len && isprint(value[len-1]))
76 dbg("attribute value of '%s' non-printable, skip", dent->d_name);
80 replace_untrusted_chars(value);
81 printf(" %s{%s}==\"%s\"\n", key, dent->d_name, value);
87 static int print_device_chain(const char *devpath)
89 struct sysfs_device *dev;
92 "Udevinfo starts with the device specified by the devpath and then\n"
93 "walks up the chain of parent devices. It prints for every device\n"
94 "found, all possible attributes in the udev rules key format.\n"
95 "A rule to match, can be composed by the attributes of the device\n"
96 "and the attributes from one single parent device.\n"
99 dev = sysfs_device_get(devpath);
103 printf(" looking at device '%s':\n", dev->devpath);
104 printf(" KERNEL==\"%s\"\n", dev->kernel);
105 printf(" SUBSYSTEM==\"%s\"\n", dev->subsystem);
106 printf(" DRIVER==\"%s\"\n", dev->driver);
107 print_all_attributes(dev->devpath, "ATTR");
109 /* walk up the chain of devices */
111 dev = sysfs_device_get_parent(dev);
114 printf(" looking at parent device '%s':\n", dev->devpath);
115 printf(" KERNELS==\"%s\"\n", dev->kernel);
116 printf(" SUBSYTEMS==\"%s\"\n", dev->subsystem);
117 printf(" DRIVERS==\"%s\"\n", dev->driver);
119 print_all_attributes(dev->devpath, "ATTRS");
125 static void print_record(struct udevice *udev)
127 struct name_entry *name_loop;
129 printf("P: %s\n", udev->dev->devpath);
130 printf("N: %s\n", udev->name);
131 list_for_each_entry(name_loop, &udev->symlink_list, node)
132 printf("S: %s\n", name_loop->name);
133 list_for_each_entry(name_loop, &udev->env_list, node)
134 printf("E: %s\n", name_loop->name);
137 static void export_name_devpath(struct udevice *udev) {
138 printf("%s=%s/%s\n", udev->dev->devpath, udev_root, udev->name);
141 static void export_record(struct udevice *udev) {
146 static void export_db(void fnct(struct udevice *udev)) {
147 LIST_HEAD(name_list);
148 struct name_entry *name_loop;
150 udev_db_get_all_entries(&name_list);
151 list_for_each_entry(name_loop, &name_list, node) {
152 struct udevice *udev_db;
154 udev_db = udev_device_init();
157 if (udev_db_get_device(udev_db, name_loop->name) == 0)
159 udev_device_cleanup(udev_db);
161 name_list_cleanup(&name_list);
164 int main(int argc, char *argv[], char *envp[])
167 struct udevice *udev;
173 ACTION_ATTRIBUTE_WALK,
175 } action = ACTION_NONE;
184 } query = QUERY_NONE;
186 char path[PATH_SIZE] = "";
187 char name[PATH_SIZE] = "";
188 struct name_entry *name_loop;
191 logging_init("udevinfo");
195 udev = udev_device_init();
201 /* get command line options */
204 option = getopt(argc, argv, ":aden:p:q:rVh");
208 dbg("option '%c'", option);
211 /* remove /dev if given */
212 if (strncmp(optarg, udev_root, strlen(udev_root)) == 0)
213 strlcpy(name, &optarg[strlen(udev_root)+1], sizeof(name));
215 strlcpy(name, optarg, sizeof(name));
216 dbg("name: %s\n", name);
219 /* remove /sys if given */
220 if (strncmp(optarg, sysfs_path, strlen(sysfs_path)) == 0)
221 strlcpy(path, &optarg[strlen(sysfs_path)], sizeof(path));
223 strlcpy(path, optarg, sizeof(path));
224 dbg("path: %s\n", path);
227 dbg("udev query: %s\n", optarg);
228 action = ACTION_QUERY;
229 if (strcmp(optarg, "name") == 0) {
233 if (strcmp(optarg, "symlink") == 0) {
234 query = QUERY_SYMLINK;
237 if (strcmp(optarg, "path") == 0) {
241 if (strcmp(optarg, "env") == 0) {
245 if (strcmp(optarg, "all") == 0) {
249 fprintf(stderr, "unknown query type\n");
253 if (action == ACTION_NONE)
254 action = ACTION_ROOT;
258 action = ACTION_ATTRIBUTE_WALK;
261 export_db(export_name_devpath);
264 export_db(export_record);
267 printf("udevinfo, version %s\n", UDEV_VERSION);
270 printf("Usage: udevinfo [-anpqrVh]\n"
271 " -q TYPE query database for the specified value:\n"
272 " 'name' name of device node\n"
273 " 'symlink' pointing to node\n"
274 " 'path' sysfs device path\n"
275 " 'env' the device related imported environment\n"
276 " 'all' all values\n"
278 " -p PATH sysfs device path used for query or chain\n"
279 " -n NAME node/symlink name used for query\n"
281 " -r prepend to query result or print udev_root\n"
282 " -a print all SYSFS_attributes along the device chain\n"
283 " -e export the content of the udev database\n"
284 " -V print udev version\n"
285 " -h print this help text\n"
289 fprintf(stderr, "missing argument for '%c'\n", optopt);
293 fprintf(stderr, "unrecognized option '%c'\n", optopt);
301 /* needs devpath or node/symlink name for query */
302 if (path[0] != '\0') {
303 if (udev_db_get_device(udev, path) != 0) {
304 fprintf(stderr, "no record for '%s' in database\n", path);
308 } else if (name[0] != '\0') {
309 char devpath[PATH_SIZE];
311 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
312 fprintf(stderr, "node name not found\n");
316 udev_db_get_device(udev, devpath);
318 fprintf(stderr, "query needs device path(-p) or node name(-n) specified\n");
326 printf("%s/%s\n", udev_root, udev->name);
328 printf("%s\n", udev->name);
331 if (list_empty(&udev->symlink_list))
334 list_for_each_entry(name_loop, &udev->symlink_list, node)
335 printf("%s/%s ", udev_root, name_loop->name);
337 list_for_each_entry(name_loop, &udev->symlink_list, node)
338 printf("%s ", name_loop->name);
342 printf("%s\n", udev->dev->devpath);
345 list_for_each_entry(name_loop, &udev->env_list, node)
346 printf("%s\n", name_loop->name);
352 fprintf(stderr, "unknown query type\n");
356 case ACTION_ATTRIBUTE_WALK:
357 if (path[0] != '\0') {
358 print_device_chain(path);
359 } else if (name[0] != '\0') {
360 char devpath[PATH_SIZE];
362 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
363 fprintf(stderr, "node name not found\n");
367 print_device_chain(devpath);
369 fprintf(stderr, "attribute walk needs device path(-p) or node name(-n) specified\n");
375 printf("%s\n", udev_root);
378 fprintf(stderr, "missing option\n");
384 udev_device_cleanup(udev);