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)
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(" SYSFS{%s}==\"%s\"\n", 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_name);
107 printf(" SUBSYSTEM==\"%s\"\n", dev->subsystem);
108 printf(" DRIVER==\"%s\"\n", dev->driver);
109 print_all_attributes(dev->devpath);
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(" ID==\"%s\"\n", dev->kernel_name);
118 printf(" BUS==\"%s\"\n", dev->subsystem);
119 printf(" DRIVER==\"%s\"\n", dev->driver);
121 print_all_attributes(dev->devpath);
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 char temp[PATH_SIZE];
213 struct name_entry *name_loop;
217 logging_init("udevinfo");
222 udev = udev_device_init();
228 /* get command line options */
230 option = getopt(argc, argv, short_options);
234 dbg("option '%c'", option);
237 dbg("udev name: %s\n", optarg);
238 strlcpy(name, optarg, sizeof(name));
241 dbg("udev path: %s\n", optarg);
242 /* remove sysfs mountpoint if not given */
243 if (strncmp(optarg, sysfs_path, strlen(sysfs_path)) == 0)
244 strlcpy(path, &optarg[strlen(sysfs_path)], sizeof(path));
246 strlcpy(path, optarg, sizeof(path));
249 dbg("udev query: %s\n", optarg);
250 action = ACTION_QUERY;
251 if (strcmp(optarg, "name") == 0) {
255 if (strcmp(optarg, "symlink") == 0) {
256 query = QUERY_SYMLINK;
259 if (strcmp(optarg, "path") == 0) {
263 if (strcmp(optarg, "env") == 0) {
267 if (strcmp(optarg, "all") == 0) {
271 fprintf(stderr, "unknown query type\n");
275 if (action == ACTION_NONE)
276 action = ACTION_ROOT;
280 action = ACTION_ATTRIBUTE_WALK;
283 export_db(export_name_devpath);
286 export_db(export_record);
289 printf("udevinfo, version %s\n", UDEV_VERSION);
302 /* need devpath or node/symlink name for query */
303 if (path[0] != '\0') {
304 /* remove sysfs_path if given */
305 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
306 pos = path + strlen(sysfs_path);
308 if (path[0] != '/') {
309 /* prepend '/' if missing */
311 strlcpy(temp, path, sizeof(temp));
317 if (udev_db_get_device(udev, pos) != 0) {
318 fprintf(stderr, "no record for '%s' in database\n", pos);
322 } else if (name[0] != '\0') {
323 char devpath[PATH_SIZE];
326 /* remove udev_root if given */
327 len = strlen(udev_root);
328 if (strncmp(name, udev_root, len) == 0) {
333 if (udev_db_lookup_name(pos, devpath, sizeof(devpath)) != 0) {
334 fprintf(stderr, "no record for '%s' in database\n", pos);
338 udev_db_get_device(udev, devpath);
340 fprintf(stderr, "query needs device path(-p) or node name(-n) specified\n");
348 printf("%s/%s\n", udev_root, udev->name);
350 printf("%s\n", udev->name);
353 if (list_empty(&udev->symlink_list))
356 list_for_each_entry(name_loop, &udev->symlink_list, node)
357 printf("%s/%s ", udev_root, name_loop->name);
359 list_for_each_entry(name_loop, &udev->symlink_list, node)
360 printf("%s ", name_loop->name);
364 printf("%s\n", udev->dev->devpath);
367 list_for_each_entry(name_loop, &udev->env_list, node)
368 printf("%s\n", name_loop->name);
378 case ACTION_ATTRIBUTE_WALK:
379 if (path[0] == '\0') {
380 fprintf(stderr, "attribute walk on device chain needs path(-p) specified\n");
384 print_device_chain(path);
387 printf("%s\n", udev_root);
396 udev_device_cleanup(udev);