2 * Copyright (C) 2004-2009 Kay Sievers <kay.sievers@vrfy.org>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include <sys/types.h>
34 static bool skip_attribute(const char *name)
36 static const char const *skip[] = {
47 for (i = 0; i < ARRAY_SIZE(skip); i++)
48 if (strcmp(name, skip[i]) == 0)
53 static void print_all_attributes(struct udev_device *device, const char *key)
55 struct udev_list_entry *sysattr;
57 udev_list_entry_foreach(sysattr, udev_device_get_sysattr_list_entry(device)) {
58 struct udev *udev = udev_device_get_udev(device);
63 name = udev_list_entry_get_name(sysattr);
64 if (skip_attribute(name))
67 value = udev_device_get_sysattr_value(device, name);
70 dbg(udev, "attr '%s'='%s'\n", name, value);
72 /* skip nonprintable attributes */
74 while (len > 0 && isprint(value[len-1]))
77 dbg(udev, "attribute value of '%s' non-printable, skip\n", name);
81 printf(" %s{%s}==\"%s\"\n", key, name, value);
86 static int print_device_chain(struct udev_device *device)
88 struct udev_device *device_parent;
92 "Udevadm info 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 printf(" looking at device '%s':\n", udev_device_get_devpath(device));
100 printf(" KERNEL==\"%s\"\n", udev_device_get_sysname(device));
101 str = udev_device_get_subsystem(device);
104 printf(" SUBSYSTEM==\"%s\"\n", str);
105 str = udev_device_get_driver(device);
108 printf(" DRIVER==\"%s\"\n", str);
109 print_all_attributes(device, "ATTR");
111 device_parent = device;
113 device_parent = udev_device_get_parent(device_parent);
114 if (device_parent == NULL)
116 printf(" looking at parent device '%s':\n", udev_device_get_devpath(device_parent));
117 printf(" KERNELS==\"%s\"\n", udev_device_get_sysname(device_parent));
118 str = udev_device_get_subsystem(device_parent);
121 printf(" SUBSYSTEMS==\"%s\"\n", str);
122 str = udev_device_get_driver(device_parent);
125 printf(" DRIVERS==\"%s\"\n", str);
126 print_all_attributes(device_parent, "ATTRS");
127 } while (device_parent != NULL);
132 static void print_record(struct udev_device *device)
137 struct udev_list_entry *list_entry;
139 printf("P: %s\n", udev_device_get_devpath(device));
141 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
142 str = udev_device_get_devnode(device);
144 printf("N: %s\n", &str[len+1]);
146 i = udev_device_get_devlink_priority(device);
148 printf("L: %i\n", i);
150 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
151 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
152 printf("S: %s\n", &udev_list_entry_get_name(list_entry)[len+1]);
155 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device))
157 udev_list_entry_get_name(list_entry),
158 udev_list_entry_get_value(list_entry));
162 static int stat_device(const char *name, bool export, const char *prefix)
166 if (stat(name, &statbuf) != 0)
172 printf("%sMAJOR=%d\n"
174 prefix, major(statbuf.st_dev),
175 prefix, minor(statbuf.st_dev));
177 printf("%d:%d\n", major(statbuf.st_dev), minor(statbuf.st_dev));
181 static int export_devices(struct udev *udev)
183 struct udev_enumerate *udev_enumerate;
184 struct udev_list_entry *list_entry;
186 udev_enumerate = udev_enumerate_new(udev);
187 if (udev_enumerate == NULL)
189 udev_enumerate_scan_devices(udev_enumerate);
190 udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
191 struct udev_device *device;
193 device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
194 if (device != NULL) {
195 print_record(device);
196 udev_device_unref(device);
199 udev_enumerate_unref(udev_enumerate);
203 int udevadm_info(struct udev *udev, int argc, char *argv[])
205 struct udev_device *device = NULL;
208 const char *export_prefix = NULL;
209 char path[UTIL_PATH_SIZE];
210 char name[UTIL_PATH_SIZE];
211 struct udev_list_entry *list_entry;
214 static const struct option options[] = {
215 { "name", required_argument, NULL, 'n' },
216 { "path", required_argument, NULL, 'p' },
217 { "query", required_argument, NULL, 'q' },
218 { "attribute-walk", no_argument, NULL, 'a' },
219 { "export-db", no_argument, NULL, 'e' },
220 { "root", no_argument, NULL, 'r' },
221 { "run", no_argument, NULL, 'R' },
222 { "device-id-of-file", required_argument, NULL, 'd' },
223 { "export", no_argument, NULL, 'x' },
224 { "export-prefix", required_argument, NULL, 'P' },
225 { "version", no_argument, NULL, 'V' },
226 { "help", no_argument, NULL, 'h' },
233 ACTION_ATTRIBUTE_WALK,
235 ACTION_DEVICE_ID_FILE,
236 } action = ACTION_NONE;
245 } query = QUERY_NONE;
251 option = getopt_long(argc, argv, "aed:n:p:q:rxP:RVh", options, NULL);
255 dbg(udev, "option '%c'\n", option);
258 if (device != NULL) {
259 fprintf(stderr, "device already specified\n");
263 /* remove /dev if given */
264 if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) != 0)
265 util_strscpyl(name, sizeof(name), udev_get_dev_path(udev), "/", optarg, NULL);
267 util_strscpy(name, sizeof(name), optarg);
268 util_remove_trailing_chars(name, '/');
269 if (stat(name, &statbuf) < 0) {
270 fprintf(stderr, "device node not found\n");
276 if (S_ISBLK(statbuf.st_mode)) {
278 } else if (S_ISCHR(statbuf.st_mode)) {
281 fprintf(stderr, "device node has wrong file type\n");
285 device = udev_device_new_from_devnum(udev, type, statbuf.st_rdev);
286 if (device == NULL) {
287 fprintf(stderr, "device node not found\n");
294 if (device != NULL) {
295 fprintf(stderr, "device already specified\n");
299 /* add sys dir if needed */
300 if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0)
301 util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), optarg, NULL);
303 util_strscpy(path, sizeof(path), optarg);
304 util_remove_trailing_chars(path, '/');
305 device = udev_device_new_from_syspath(udev, path);
306 if (device == NULL) {
307 fprintf(stderr, "device path not found\n");
313 action = ACTION_QUERY;
314 if (strcmp(optarg, "property") == 0 || strcmp(optarg, "env") == 0) {
315 query = QUERY_PROPERTY;
316 } else if (strcmp(optarg, "name") == 0) {
318 } else if (strcmp(optarg, "symlink") == 0) {
319 query = QUERY_SYMLINK;
320 } else if (strcmp(optarg, "path") == 0) {
322 } else if (strcmp(optarg, "all") == 0) {
325 fprintf(stderr, "unknown query type\n");
331 if (action == ACTION_NONE)
332 action = ACTION_ROOT;
336 printf("%s\n", udev_get_run_path(udev));
339 action = ACTION_DEVICE_ID_FILE;
340 util_strscpy(name, sizeof(name), optarg);
343 action = ACTION_ATTRIBUTE_WALK;
346 export_devices(udev);
352 export_prefix = optarg;
355 printf("%s\n", VERSION);
358 printf("Usage: udevadm info OPTIONS\n"
359 " --query=<type> query device information:\n"
360 " name name of device node\n"
361 " symlink pointing to node\n"
362 " path sys device path\n"
363 " property the device properties\n"
365 " --path=<syspath> sys device path used for query or attribute walk\n"
366 " --name=<name> node or symlink name used for query or attribute walk\n"
367 " --root prepend dev directory to path names\n"
368 " --attribute-walk print all key matches while walking along the chain\n"
369 " of parent devices\n"
370 " --device-id-of-file=<file> print major:minor of device containing this file\n"
371 " --export export key/value pairs\n"
372 " --export-prefix export the key name with a prefix\n"
373 " --export-db export the content of the udev database\n"
383 if (device == NULL) {
384 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
391 const char *node = udev_device_get_devnode(device);
394 fprintf(stderr, "no device node found\n");
400 printf("%s\n", udev_device_get_devnode(device));
402 size_t len = strlen(udev_get_dev_path(udev));
404 printf("%s\n", &udev_device_get_devnode(device)[len+1]);
409 list_entry = udev_device_get_devlinks_list_entry(device);
410 while (list_entry != NULL) {
412 printf("%s", udev_list_entry_get_name(list_entry));
416 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
417 printf("%s", &udev_list_entry_get_name(list_entry)[len+1]);
419 list_entry = udev_list_entry_get_next(list_entry);
420 if (list_entry != NULL)
426 printf("%s\n", udev_device_get_devpath(device));
429 list_entry = udev_device_get_properties_list_entry(device);
430 while (list_entry != NULL) {
432 const char *prefix = export_prefix;
436 printf("%s%s='%s'\n", prefix,
437 udev_list_entry_get_name(list_entry),
438 udev_list_entry_get_value(list_entry));
440 printf("%s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry));
442 list_entry = udev_list_entry_get_next(list_entry);
446 print_record(device);
449 fprintf(stderr, "unknown query type\n");
453 case ACTION_ATTRIBUTE_WALK:
454 if (device == NULL) {
455 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
459 print_device_chain(device);
461 case ACTION_DEVICE_ID_FILE:
462 if (stat_device(name, export, export_prefix) != 0)
466 printf("%s\n", udev_get_dev_path(udev));
469 fprintf(stderr, "missing option\n");
475 udev_device_unref(device);