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 *udev,
169 const char *devpath, const char *subsystem, const char *name,
172 struct udev_device *device;
174 device = udev_device_new_from_devpath(udev, devpath);
177 if (udev_device_get_devname(device) != NULL)
178 print_record(device);
179 udev_device_unref(device);
183 static struct udev_device *lookup_device_by_name(struct udev *udev, const char *name)
185 struct udev_device *udev_device = NULL;
186 LIST_HEAD(name_list);
188 struct name_entry *device;
190 count = udev_db_get_devices_by_name(udev, name, &name_list);
194 info(udev, "found %i devices for '%s'\n", count, name);
196 /* select the device that matches */
197 list_for_each_entry(device, &name_list, node) {
198 struct udevice *udevice_loop;
199 char filename[UTIL_PATH_SIZE];
202 udevice_loop = udev_device_init(udev);
203 if (udevice_loop == NULL)
205 if (udev_db_get_device(udevice_loop, device->name) != 0)
207 info(udev, "found db entry '%s'\n", device->name);
208 /* make sure, we don't get a link of a different device */
209 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
210 util_strlcat(filename, "/", sizeof(filename));
211 util_strlcat(filename, name, sizeof(filename));
212 if (stat(filename, &statbuf) != 0)
214 if (major(udevice_loop->devt) > 0 && udevice_loop->devt != statbuf.st_rdev) {
215 info(udev, "skip '%s', dev_t doesn't match\n", udevice_loop->name);
218 udev_device = udev_device_new_from_devpath(udev, udevice_loop->dev->devpath);
219 udev_device_cleanup(udevice_loop);
222 udev_device_cleanup(udevice_loop);
225 name_list_cleanup(udev, &name_list);
229 static int add_devlink_cb(struct udev_device *device, const char *value, void *data)
233 if (*links == NULL) {
234 *links = strdup(value);
238 asprintf(&str, "%s %s", *links, value);
245 static int add_devlink_noroot_cb(struct udev_device *device, const char *value, void *data)
249 len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
250 value = &value[len+1];
251 return add_devlink_cb(device, value, data);
254 static int print_property_cb(struct udev_device *device, const char *key, const char *value, void *data)
256 printf("%s=%s\n", key, value);
260 static int stat_device(const char *name, int export, const char *prefix)
264 if (stat(name, &statbuf) != 0)
270 printf("%sMAJOR=%d\n"
272 prefix, major(statbuf.st_dev),
273 prefix, minor(statbuf.st_dev));
275 printf("%d:%d\n", major(statbuf.st_dev), minor(statbuf.st_dev));
279 int udevadm_info(struct udev *udev, int argc, char *argv[])
281 struct udev_device *device = NULL;
284 const char *export_prefix = NULL;
285 char path[UTIL_PATH_SIZE];
286 char name[UTIL_PATH_SIZE];
290 static const struct option options[] = {
291 { "name", 1, NULL, 'n' },
292 { "path", 1, NULL, 'p' },
293 { "query", 1, NULL, 'q' },
294 { "attribute-walk", 0, NULL, 'a' },
295 { "export-db", 0, NULL, 'e' },
296 { "root", 0, NULL, 'r' },
297 { "device-id-of-file", 1, NULL, 'd' },
298 { "export", 0, NULL, 'x' },
299 { "export-prefix", 1, NULL, 'P' },
300 { "version", 0, NULL, 1 }, /* -V outputs braindead format */
301 { "help", 0, NULL, 'h' },
308 ACTION_ATTRIBUTE_WALK,
310 ACTION_DEVICE_ID_FILE,
311 } action = ACTION_NONE;
320 } query = QUERY_NONE;
325 option = getopt_long(argc, argv, "aed:n:p:q:rxPVh", options, NULL);
329 dbg(udev, "option '%c'\n", option);
332 if (device != NULL) {
333 fprintf(stderr, "device already specified\n");
337 /* remove /dev if given */
338 if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) == 0)
339 util_strlcpy(name, &optarg[strlen(udev_get_dev_path(udev))+1], sizeof(name));
341 util_strlcpy(name, optarg, sizeof(name));
342 util_remove_trailing_chars(name, '/');
343 device = lookup_device_by_name(udev, name);
346 if (device != NULL) {
347 fprintf(stderr, "device already specified\n");
351 /* remove /sys if given */
352 if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) == 0)
353 util_strlcpy(path, &optarg[strlen(udev_get_sys_path(udev))], sizeof(path));
355 util_strlcpy(path, optarg, sizeof(path));
356 util_remove_trailing_chars(path, '/');
357 device = udev_device_new_from_devpath(udev, path);
360 action = ACTION_QUERY;
361 if (strcmp(optarg, "name") == 0) {
365 if (strcmp(optarg, "symlink") == 0) {
366 query = QUERY_SYMLINK;
369 if (strcmp(optarg, "path") == 0) {
373 if (strcmp(optarg, "env") == 0) {
377 if (strcmp(optarg, "all") == 0) {
381 fprintf(stderr, "unknown query type\n");
385 if (action == ACTION_NONE)
386 action = ACTION_ROOT;
390 action = ACTION_DEVICE_ID_FILE;
391 util_strlcpy(name, optarg, sizeof(name));
394 action = ACTION_ATTRIBUTE_WALK;
397 udev_enumerate_devices(udev, NULL, export_all_cb, NULL);
403 export_prefix = optarg;
406 printf("%s\n", VERSION);
409 printf("udevinfo, version %s\n", VERSION);
412 printf("Usage: udevadm info OPTIONS\n"
413 " --query=<type> query database for the specified value:\n"
414 " name name of device node\n"
415 " symlink pointing to node\n"
416 " path sysfs device path\n"
417 " env the device related imported environment\n"
419 " --path=<devpath> sysfs device path used for query or chain\n"
420 " --name=<name> node or symlink name used for query\n"
421 " --root prepend to query result or print udev_root\n"
422 " --attribute-walk print all key matches while walking along chain\n"
423 " of parent devices\n"
424 " --device-id-of-file=<file> print major/minor of underlying device\n"
425 " --export-db export the content of the udev database\n"
426 " --help print this text\n"
436 if (device == NULL) {
437 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
445 printf("%s\n", udev_device_get_devname(device));
449 len = strlen(udev_get_dev_path(udev));
450 printf("%s\n", &udev_device_get_devname(device)[len+1]);
456 udev_device_get_devlinks(device, add_devlink_cb, &links);
458 udev_device_get_devlinks(device, add_devlink_noroot_cb, &links);
459 printf("%s\n", links);
463 printf("%s\n", udev_device_get_devpath(device));
466 udev_device_get_properties(device, print_property_cb, NULL);
469 print_record(device);
472 fprintf(stderr, "unknown query type\n");
476 case ACTION_ATTRIBUTE_WALK:
477 if (device == NULL) {
478 fprintf(stderr, "query needs a valid device specified by --path= or --name=\n");
482 print_device_chain(device);
484 case ACTION_DEVICE_ID_FILE:
485 if (stat_device(name, export, export_prefix) != 0)
489 printf("%s\n", udev_get_dev_path(udev));
492 fprintf(stderr, "missing option\n");
498 udev_device_unref(device);