2 * Copyright (C) 2004-2008 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/>.
29 #include <sys/types.h>
33 static void print_all_attributes(struct udev_device *device, const char *key)
38 dir = opendir(udev_device_get_syspath(device));
40 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
42 char filename[UTIL_PATH_SIZE];
46 if (dent->d_name[0] == '.')
49 if (strcmp(dent->d_name, "uevent") == 0)
51 if (strcmp(dent->d_name, "dev") == 0)
54 util_strlcpy(filename, udev_device_get_syspath(device), sizeof(filename));
55 util_strlcat(filename, "/", sizeof(filename));
56 util_strlcat(filename, dent->d_name, sizeof(filename));
57 if (lstat(filename, &statbuf) != 0)
59 if (S_ISLNK(statbuf.st_mode))
62 value = udev_device_get_attr_value(device, dent->d_name);
65 dbg(udev, "attr '%s'='%s'(%zi)\n", dent->d_name, value, len);
67 /* skip nonprintable attributes */
69 while (len > 0 && isprint(value[len-1]))
72 dbg(info, "attribute value of '%s' non-printable, skip\n", dent->d_name);
76 printf(" %s{%s}==\"%s\"\n", key, dent->d_name, value);
83 static int print_device_chain(struct udev_device *device)
85 struct udev_device *device_parent;
89 "Udevinfo starts with the device specified by the devpath and then\n"
90 "walks up the chain of parent devices. It prints for every device\n"
91 "found, all possible attributes in the udev rules key format.\n"
92 "A rule to match, can be composed by the attributes of the device\n"
93 "and the attributes from one single parent device.\n"
96 printf(" looking at device '%s':\n", udev_device_get_devpath(device));
97 printf(" KERNEL==\"%s\"\n", udev_device_get_sysname(device));
98 str = udev_device_get_subsystem(device);
101 printf(" SUBSYSTEM==\"%s\"\n", str);
102 str = udev_device_get_driver(device);
105 printf(" DRIVER==\"%s\"\n", str);
106 print_all_attributes(device, "ATTR");
108 device_parent = device;
110 device_parent = udev_device_get_parent(device_parent);
111 if (device_parent == NULL)
113 printf(" looking at parent device '%s':\n", udev_device_get_devpath(device_parent));
114 printf(" KERNELS==\"%s\"\n", udev_device_get_sysname(device_parent));
115 str = udev_device_get_subsystem(device_parent);
118 printf(" SUBSYSTEMS==\"%s\"\n", str);
119 str = udev_device_get_driver(device_parent);
122 printf(" DRIVERS==\"%s\"\n", str);
123 print_all_attributes(device_parent, "ATTRS");
124 } while (device_parent != NULL);
129 static int print_record_devlinks_cb(struct udev_device *device, const char *value, void *data)
133 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
134 printf("S: %s\n", &value[len+1]);
138 static int print_record_properties_cb(struct udev_device *device, const char *key, const char *value, void *data)
140 printf("E: %s=%s\n", key, value);
144 static void print_record(struct udev_device *device)
149 printf("P: %s\n", udev_device_get_devpath(device));
150 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
151 printf("N: %s\n", &udev_device_get_devname(device)[len+1]);
152 i = device_get_devlink_priority(device);
154 printf("L: %i\n", i);
155 i = device_get_num_fake_partitions(device);
158 i = device_get_ignore_remove(device);
161 udev_device_get_devlinks(device, print_record_devlinks_cb, NULL);
162 udev_device_get_properties(device, print_record_properties_cb, NULL);
166 static int export_all_cb(struct udev_device *device, void *data)
168 if (udev_device_get_devname(device) != NULL)
169 print_record(device);
173 static struct udev_device *lookup_device_by_name(struct udev *udev, const char *name)
175 struct udev_device *udev_device = NULL;
176 LIST_HEAD(name_list);
178 struct name_entry *device;
180 count = udev_db_get_devices_by_name(udev, name, &name_list);
184 info(udev, "found %i devices for '%s'\n", count, name);
186 /* select the device that matches */
187 list_for_each_entry(device, &name_list, node) {
188 struct udevice *udevice_loop;
189 char filename[UTIL_PATH_SIZE];
192 udevice_loop = udev_device_init(udev);
193 if (udevice_loop == NULL)
195 if (udev_db_get_device(udevice_loop, device->name) != 0)
197 info(udev, "found db entry '%s'\n", device->name);
198 /* make sure, we don't get a link of a different device */
199 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
200 util_strlcat(filename, "/", sizeof(filename));
201 util_strlcat(filename, name, sizeof(filename));
202 if (stat(filename, &statbuf) != 0)
204 if (major(udevice_loop->devt) > 0 && udevice_loop->devt != statbuf.st_rdev) {
205 info(udev, "skip '%s', dev_t doesn't match\n", udevice_loop->name);
208 util_strlcpy(filename, udev_get_sys_path(udev), sizeof(filename));
209 util_strlcat(filename, udevice_loop->dev->devpath, sizeof(filename));
210 udev_device = udev_device_new_from_syspath(udev, filename);
211 udev_device_cleanup(udevice_loop);
214 udev_device_cleanup(udevice_loop);
217 name_list_cleanup(udev, &name_list);
221 static int add_devlink_cb(struct udev_device *device, const char *value, void *data)
225 if (*links == NULL) {
226 *links = strdup(value);
230 asprintf(&str, "%s %s", *links, value);
237 static int add_devlink_noroot_cb(struct udev_device *device, const char *value, void *data)
241 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
242 value = &value[len+1];
243 return add_devlink_cb(device, value, data);
246 static int print_property_cb(struct udev_device *device, const char *key, const char *value, void *data)
248 printf("%s=%s\n", key, value);
252 static int stat_device(const char *name, int export, const char *prefix)
256 if (stat(name, &statbuf) != 0)
262 printf("%sMAJOR=%d\n"
264 prefix, major(statbuf.st_dev),
265 prefix, minor(statbuf.st_dev));
267 printf("%d:%d\n", major(statbuf.st_dev), minor(statbuf.st_dev));
271 int udevadm_info(struct udev *udev, int argc, char *argv[])
273 struct udev_device *device = NULL;
276 const char *export_prefix = NULL;
277 char path[UTIL_PATH_SIZE];
278 char name[UTIL_PATH_SIZE];
282 static const struct option options[] = {
283 { "name", 1, NULL, 'n' },
284 { "path", 1, NULL, 'p' },
285 { "query", 1, NULL, 'q' },
286 { "attribute-walk", 0, NULL, 'a' },
287 { "export-db", 0, NULL, 'e' },
288 { "root", 0, NULL, 'r' },
289 { "device-id-of-file", 1, NULL, 'd' },
290 { "export", 0, NULL, 'x' },
291 { "export-prefix", 1, NULL, 'P' },
292 { "version", 0, NULL, 1 }, /* -V outputs braindead format */
293 { "help", 0, NULL, 'h' },
300 ACTION_ATTRIBUTE_WALK,
302 ACTION_DEVICE_ID_FILE,
303 } action = ACTION_NONE;
312 } query = QUERY_NONE;
317 option = getopt_long(argc, argv, "aed:n:p:q:rxPVh", options, NULL);
321 dbg(udev, "option '%c'\n", option);
324 if (device != NULL) {
325 fprintf(stderr, "device already specified\n");
329 /* remove /dev if given */
330 if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) == 0)
331 util_strlcpy(name, &optarg[strlen(udev_get_dev_path(udev))+1], sizeof(name));
333 util_strlcpy(name, optarg, sizeof(name));
334 util_remove_trailing_chars(name, '/');
335 device = lookup_device_by_name(udev, name);
338 if (device != NULL) {
339 fprintf(stderr, "device already specified\n");
343 /* add /sys if needed */
344 if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) {
345 util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
346 util_strlcat(path, optarg, sizeof(path));
348 util_strlcpy(path, optarg, sizeof(path));
350 util_remove_trailing_chars(path, '/');
351 device = udev_device_new_from_syspath(udev, path);
354 action = ACTION_QUERY;
355 if (strcmp(optarg, "name") == 0) {
359 if (strcmp(optarg, "symlink") == 0) {
360 query = QUERY_SYMLINK;
363 if (strcmp(optarg, "path") == 0) {
367 if (strcmp(optarg, "env") == 0) {
371 if (strcmp(optarg, "all") == 0) {
375 fprintf(stderr, "unknown query type\n");
379 if (action == ACTION_NONE)
380 action = ACTION_ROOT;
384 action = ACTION_DEVICE_ID_FILE;
385 util_strlcpy(name, optarg, sizeof(name));
388 action = ACTION_ATTRIBUTE_WALK;
391 udev_enumerate_devices(udev, NULL, export_all_cb, NULL);
397 export_prefix = optarg;
400 printf("%s\n", VERSION);
403 printf("udevinfo, version %s\n", VERSION);
406 printf("Usage: udevadm info OPTIONS\n"
407 " --query=<type> query database for the specified value:\n"
408 " name name of device node\n"
409 " symlink pointing to node\n"
410 " path sysfs device path\n"
411 " env the device related imported environment\n"
413 " --path=<devpath> sysfs device path used for query or chain\n"
414 " --name=<name> node or symlink name used for query\n"
415 " --root prepend to query result or print udev_root\n"
416 " --attribute-walk print all key matches while walking along chain\n"
417 " of parent devices\n"
418 " --device-id-of-file=<file> print major/minor of underlying device\n"
419 " --export-db export the content of the udev database\n"
420 " --help print this text\n"
430 if (device == NULL) {
431 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
439 printf("%s\n", udev_device_get_devname(device));
443 len = strlen(udev_get_dev_path(udev));
444 printf("%s\n", &udev_device_get_devname(device)[len+1]);
450 udev_device_get_devlinks(device, add_devlink_cb, &links);
452 udev_device_get_devlinks(device, add_devlink_noroot_cb, &links);
453 printf("%s\n", links);
457 printf("%s\n", udev_device_get_devpath(device));
460 udev_device_get_properties(device, print_property_cb, NULL);
463 print_record(device);
466 fprintf(stderr, "unknown query type\n");
470 case ACTION_ATTRIBUTE_WALK:
471 if (device == NULL) {
472 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
476 print_device_chain(device);
478 case ACTION_DEVICE_ID_FILE:
479 if (stat_device(name, export, export_prefix) != 0)
483 printf("%s\n", udev_get_dev_path(udev));
486 fprintf(stderr, "missing option\n");
492 udev_device_unref(device);