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/>.
31 #include <sys/types.h>
35 static void print_all_attributes(struct udev_device *device, const char *key)
40 dir = opendir(udev_device_get_syspath(device));
42 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
44 char filename[UTIL_PATH_SIZE];
48 if (dent->d_name[0] == '.')
51 if (strcmp(dent->d_name, "uevent") == 0)
53 if (strcmp(dent->d_name, "dev") == 0)
56 util_strlcpy(filename, udev_device_get_syspath(device), sizeof(filename));
57 util_strlcat(filename, "/", sizeof(filename));
58 util_strlcat(filename, dent->d_name, sizeof(filename));
59 if (lstat(filename, &statbuf) != 0)
61 if (S_ISLNK(statbuf.st_mode))
64 value = udev_device_get_attr_value(device, dent->d_name);
67 dbg(udev, "attr '%s'='%s'(%zi)\n", dent->d_name, value, len);
69 /* skip nonprintable attributes */
71 while (len > 0 && isprint(value[len-1]))
74 dbg(info, "attribute value of '%s' non-printable, skip\n", dent->d_name);
78 printf(" %s{%s}==\"%s\"\n", key, dent->d_name, value);
85 static int print_device_chain(struct udev_device *device)
87 struct udev_device *device_parent;
91 "Udevinfo starts with the device specified by the devpath and then\n"
92 "walks up the chain of parent devices. It prints for every device\n"
93 "found, all possible attributes in the udev rules key format.\n"
94 "A rule to match, can be composed by the attributes of the device\n"
95 "and the attributes from one single parent device.\n"
98 printf(" looking at device '%s':\n", udev_device_get_devpath(device));
99 printf(" KERNEL==\"%s\"\n", udev_device_get_sysname(device));
100 str = udev_device_get_subsystem(device);
103 printf(" SUBSYSTEM==\"%s\"\n", str);
104 str = udev_device_get_driver(device);
107 printf(" DRIVER==\"%s\"\n", str);
108 print_all_attributes(device, "ATTR");
110 device_parent = device;
112 device_parent = udev_device_get_parent(device_parent);
113 if (device_parent == NULL)
115 printf(" looking at parent device '%s':\n", udev_device_get_devpath(device_parent));
116 printf(" KERNELS==\"%s\"\n", udev_device_get_sysname(device_parent));
117 str = udev_device_get_subsystem(device_parent);
120 printf(" SUBSYSTEMS==\"%s\"\n", str);
121 str = udev_device_get_driver(device_parent);
124 printf(" DRIVERS==\"%s\"\n", str);
125 print_all_attributes(device_parent, "ATTRS");
126 } while (device_parent != NULL);
131 static int print_record_devlinks_cb(struct udev_device *device, const char *value, void *data)
135 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
136 printf("S: %s\n", &value[len+1]);
140 static int print_record_properties_cb(struct udev_device *device, const char *key, const char *value, void *data)
142 printf("E: %s=%s\n", key, value);
146 static void print_record(struct udev_device *device)
151 printf("P: %s\n", udev_device_get_devpath(device));
152 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
153 printf("N: %s\n", &udev_device_get_devname(device)[len+1]);
154 i = device_get_devlink_priority(device);
156 printf("L: %i\n", i);
157 i = device_get_num_fake_partitions(device);
160 i = device_get_ignore_remove(device);
163 udev_device_get_devlinks(device, print_record_devlinks_cb, NULL);
164 udev_device_get_properties(device, print_record_properties_cb, NULL);
168 static int export_all_cb(struct udev_device *device, void *data)
170 if (udev_device_get_devname(device) != NULL)
171 print_record(device);
175 static struct udev_device *lookup_device_by_name(struct udev *udev, const char *name)
177 struct udev_device *udev_device = NULL;
178 LIST_HEAD(name_list);
180 struct name_entry *device;
182 count = udev_db_get_devices_by_name(udev, name, &name_list);
186 info(udev, "found %i devices for '%s'\n", count, name);
188 /* select the device that matches */
189 list_for_each_entry(device, &name_list, node) {
190 struct udevice *udevice_loop;
191 char filename[UTIL_PATH_SIZE];
194 udevice_loop = udev_device_init(udev);
195 if (udevice_loop == NULL)
197 if (udev_db_get_device(udevice_loop, device->name) != 0)
199 info(udev, "found db entry '%s'\n", device->name);
200 /* make sure, we don't get a link of a different device */
201 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
202 util_strlcat(filename, "/", sizeof(filename));
203 util_strlcat(filename, name, sizeof(filename));
204 if (stat(filename, &statbuf) != 0)
206 if (major(udevice_loop->devt) > 0 && udevice_loop->devt != statbuf.st_rdev) {
207 info(udev, "skip '%s', dev_t doesn't match\n", udevice_loop->name);
210 util_strlcpy(filename, udev_get_sys_path(udev), sizeof(filename));
211 util_strlcat(filename, udevice_loop->dev->devpath, sizeof(filename));
212 udev_device = udev_device_new_from_syspath(udev, filename);
213 udev_device_cleanup(udevice_loop);
216 udev_device_cleanup(udevice_loop);
219 name_list_cleanup(udev, &name_list);
223 static int add_devlink_cb(struct udev_device *device, const char *value, void *data)
227 if (*links == NULL) {
228 *links = strdup(value);
232 asprintf(&str, "%s %s", *links, value);
239 static int add_devlink_noroot_cb(struct udev_device *device, const char *value, void *data)
243 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
244 value = &value[len+1];
245 return add_devlink_cb(device, value, data);
248 static int print_property_cb(struct udev_device *device, const char *key, const char *value, void *data)
250 printf("%s=%s\n", key, value);
254 static int stat_device(const char *name, int export, const char *prefix)
258 if (stat(name, &statbuf) != 0)
264 printf("%sMAJOR=%d\n"
266 prefix, major(statbuf.st_dev),
267 prefix, minor(statbuf.st_dev));
269 printf("%d:%d\n", major(statbuf.st_dev), minor(statbuf.st_dev));
273 int udevadm_info(struct udev *udev, int argc, char *argv[])
275 struct udev_device *device = NULL;
278 const char *export_prefix = NULL;
279 char path[UTIL_PATH_SIZE];
280 char name[UTIL_PATH_SIZE];
284 static const struct option options[] = {
285 { "name", 1, NULL, 'n' },
286 { "path", 1, NULL, 'p' },
287 { "query", 1, NULL, 'q' },
288 { "attribute-walk", 0, NULL, 'a' },
289 { "export-db", 0, NULL, 'e' },
290 { "root", 0, NULL, 'r' },
291 { "device-id-of-file", 1, NULL, 'd' },
292 { "export", 0, NULL, 'x' },
293 { "export-prefix", 1, NULL, 'P' },
294 { "version", 0, NULL, 1 }, /* -V outputs braindead format */
295 { "help", 0, NULL, 'h' },
302 ACTION_ATTRIBUTE_WALK,
304 ACTION_DEVICE_ID_FILE,
305 } action = ACTION_NONE;
314 } query = QUERY_NONE;
319 option = getopt_long(argc, argv, "aed:n:p:q:rxPVh", options, NULL);
323 dbg(udev, "option '%c'\n", option);
326 if (device != NULL) {
327 fprintf(stderr, "device already specified\n");
331 /* remove /dev if given */
332 if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) == 0)
333 util_strlcpy(name, &optarg[strlen(udev_get_dev_path(udev))+1], sizeof(name));
335 util_strlcpy(name, optarg, sizeof(name));
336 util_remove_trailing_chars(name, '/');
337 device = lookup_device_by_name(udev, name);
340 if (device != NULL) {
341 fprintf(stderr, "device already specified\n");
345 /* add /sys if needed */
346 if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) {
347 util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
348 util_strlcat(path, optarg, sizeof(path));
350 util_strlcpy(path, optarg, sizeof(path));
352 util_remove_trailing_chars(path, '/');
353 device = udev_device_new_from_syspath(udev, path);
356 action = ACTION_QUERY;
357 if (strcmp(optarg, "name") == 0) {
361 if (strcmp(optarg, "symlink") == 0) {
362 query = QUERY_SYMLINK;
365 if (strcmp(optarg, "path") == 0) {
369 if (strcmp(optarg, "env") == 0) {
373 if (strcmp(optarg, "all") == 0) {
377 fprintf(stderr, "unknown query type\n");
381 if (action == ACTION_NONE)
382 action = ACTION_ROOT;
386 action = ACTION_DEVICE_ID_FILE;
387 util_strlcpy(name, optarg, sizeof(name));
390 action = ACTION_ATTRIBUTE_WALK;
393 udev_enumerate_devices(udev, NULL, export_all_cb, NULL);
399 export_prefix = optarg;
402 printf("%s\n", VERSION);
405 printf("udevinfo, version %s\n", VERSION);
408 printf("Usage: udevadm info OPTIONS\n"
409 " --query=<type> query database for the specified value:\n"
410 " name name of device node\n"
411 " symlink pointing to node\n"
412 " path sysfs device path\n"
413 " env the device related imported environment\n"
415 " --path=<devpath> sysfs device path used for query or chain\n"
416 " --name=<name> node or symlink name used for query\n"
417 " --root prepend to query result or print udev_root\n"
418 " --attribute-walk print all key matches while walking along chain\n"
419 " of parent devices\n"
420 " --device-id-of-file=<file> print major/minor of underlying device\n"
421 " --export-db export the content of the udev database\n"
422 " --help print this text\n"
432 if (device == NULL) {
433 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
441 printf("%s\n", udev_device_get_devname(device));
445 len = strlen(udev_get_dev_path(udev));
446 printf("%s\n", &udev_device_get_devname(device)[len+1]);
452 udev_device_get_devlinks(device, add_devlink_cb, &links);
454 udev_device_get_devlinks(device, add_devlink_noroot_cb, &links);
455 printf("%s\n", links);
459 printf("%s\n", udev_device_get_devpath(device));
462 udev_device_get_properties(device, print_property_cb, NULL);
465 print_record(device);
468 fprintf(stderr, "unknown query type\n");
472 case ACTION_ATTRIBUTE_WALK:
473 if (device == NULL) {
474 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
478 print_device_chain(device);
480 case ACTION_DEVICE_ID_FILE:
481 if (stat_device(name, export, export_prefix) != 0)
485 printf("%s\n", udev_get_dev_path(udev));
488 fprintf(stderr, "missing option\n");
494 udev_device_unref(device);