]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/udevadm-info.c
2 * Copyright (C) 2004-2009 Kay Sievers <kay@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
< ELEMENTSOF(skip
); i
++)
48 if (streq(name
, skip
[i
]))
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
)) {
62 name
= udev_list_entry_get_name(sysattr
);
63 if (skip_attribute(name
))
66 value
= udev_device_get_sysattr_value(device
, name
);
70 /* skip any values that look like a path */
74 /* skip nonprintable attributes */
76 while (len
> 0 && isprint(value
[len
-1]))
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
)
136 struct udev_list_entry
*list_entry
;
138 printf("P: %s\n", udev_device_get_devpath(device
));
140 str
= udev_device_get_devnode(device
);
142 printf("N: %s\n", str
+ strlen("/dev/"));
144 i
= udev_device_get_devlink_priority(device
);
146 printf("L: %i\n", i
);
148 udev_list_entry_foreach(list_entry
, udev_device_get_devlinks_list_entry(device
))
149 printf("S: %s\n", udev_list_entry_get_name(list_entry
) + strlen("/dev/"));
151 udev_list_entry_foreach(list_entry
, udev_device_get_properties_list_entry(device
))
153 udev_list_entry_get_name(list_entry
),
154 udev_list_entry_get_value(list_entry
));
158 static int stat_device(const char *name
, bool export
, const char *prefix
)
162 if (stat(name
, &statbuf
) != 0)
168 printf("%sMAJOR=%d\n"
170 prefix
, major(statbuf
.st_dev
),
171 prefix
, minor(statbuf
.st_dev
));
173 printf("%d:%d\n", major(statbuf
.st_dev
), minor(statbuf
.st_dev
));
177 static int export_devices(struct udev
*udev
)
179 struct udev_enumerate
*udev_enumerate
;
180 struct udev_list_entry
*list_entry
;
182 udev_enumerate
= udev_enumerate_new(udev
);
183 if (udev_enumerate
== NULL
)
185 udev_enumerate_scan_devices(udev_enumerate
);
186 udev_list_entry_foreach(list_entry
, udev_enumerate_get_list_entry(udev_enumerate
)) {
187 struct udev_device
*device
;
189 device
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(list_entry
));
190 if (device
!= NULL
) {
191 print_record(device
);
192 udev_device_unref(device
);
195 udev_enumerate_unref(udev_enumerate
);
199 static void cleanup_dir(DIR *dir
, mode_t mask
, int depth
)
206 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
209 if (dent
->d_name
[0] == '.')
211 if (fstatat(dirfd(dir
), dent
->d_name
, &stats
, AT_SYMLINK_NOFOLLOW
) != 0)
213 if ((stats
.st_mode
& mask
) != 0)
215 if (S_ISDIR(stats
.st_mode
)) {
218 dir2
= fdopendir(openat(dirfd(dir
), dent
->d_name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
));
220 cleanup_dir(dir2
, mask
, depth
-1);
223 unlinkat(dirfd(dir
), dent
->d_name
, AT_REMOVEDIR
);
225 unlinkat(dirfd(dir
), dent
->d_name
, 0);
230 static void cleanup_db(struct udev
*udev
)
234 unlink("/run/udev/queue.bin");
236 dir
= opendir("/run/udev/data");
238 cleanup_dir(dir
, S_ISVTX
, 1);
242 dir
= opendir("/run/udev/links");
244 cleanup_dir(dir
, 0, 2);
248 dir
= opendir("/run/udev/tags");
250 cleanup_dir(dir
, 0, 2);
254 dir
= opendir("/run/udev/static_node-tags");
256 cleanup_dir(dir
, 0, 2);
260 dir
= opendir("/run/udev/watch");
262 cleanup_dir(dir
, 0, 1);
267 static struct udev_device
*find_device(struct udev
*udev
, const char *id
, const char *prefix
)
269 char name
[UTIL_PATH_SIZE
];
271 if (prefix
&& !startswith(id
, prefix
)) {
272 strscpyl(name
, sizeof(name
), prefix
, id
, NULL
);
276 if (startswith(id
, "/dev/")) {
280 if (stat(id
, &statbuf
) < 0)
283 if (S_ISBLK(statbuf
.st_mode
))
285 else if (S_ISCHR(statbuf
.st_mode
))
290 return udev_device_new_from_devnum(udev
, type
, statbuf
.st_rdev
);
291 } else if (startswith(id
, "/sys/"))
292 return udev_device_new_from_syspath(udev
, id
);
297 static int uinfo(struct udev
*udev
, int argc
, char *argv
[])
299 struct udev_device
*device
= NULL
;
302 const char *export_prefix
= NULL
;
303 char name
[UTIL_PATH_SIZE
];
304 struct udev_list_entry
*list_entry
;
307 static const struct option options
[] = {
308 { "name", required_argument
, NULL
, 'n' },
309 { "path", required_argument
, NULL
, 'p' },
310 { "query", required_argument
, NULL
, 'q' },
311 { "attribute-walk", no_argument
, NULL
, 'a' },
312 { "cleanup-db", no_argument
, NULL
, 'c' },
313 { "export-db", no_argument
, NULL
, 'e' },
314 { "root", no_argument
, NULL
, 'r' },
315 { "device-id-of-file", required_argument
, NULL
, 'd' },
316 { "export", no_argument
, NULL
, 'x' },
317 { "export-prefix", required_argument
, NULL
, 'P' },
318 { "version", no_argument
, NULL
, 'V' },
319 { "help", no_argument
, NULL
, 'h' },
323 static const char *usage
=
324 "Usage: udevadm info [OPTIONS] [DEVPATH|FILE]\n"
325 " -q,--query=TYPE query device information:\n"
326 " name name of device node\n"
327 " symlink pointing to node\n"
328 " path sys device path\n"
329 " property the device properties\n"
331 " -p,--path=SYSPATH sys device path used for query or attribute walk\n"
332 " -n,--name=NAME node or symlink name used for query or attribute walk\n"
333 " -r,--root prepend dev directory to path names\n"
334 " -a,--attribute-walk print all key matches walking along the chain\n"
335 " of parent devices\n"
336 " -d,--device-id-of-file=FILE print major:minor of device containing this file\n"
337 " -x,--export export key/value pairs\n"
338 " -P,--export-prefix export the key name with a prefix\n"
339 " -e,--export-db export the content of the udev database\n"
340 " -c,--cleanup-db cleanup the udev database\n"
341 " --version print version of the program\n"
342 " -h,--help print this message\n";
346 ACTION_ATTRIBUTE_WALK
,
347 ACTION_DEVICE_ID_FILE
,
348 } action
= ACTION_QUERY
;
358 while ((c
= getopt_long(argc
, argv
, "aced:n:p:q:rxP:RVh", options
, NULL
)) >= 0)
361 if (device
!= NULL
) {
362 fprintf(stderr
, "device already specified\n");
367 device
= find_device(udev
, optarg
, "/dev/");
368 if (device
== NULL
) {
369 fprintf(stderr
, "device node not found\n");
376 if (device
!= NULL
) {
377 fprintf(stderr
, "device already specified\n");
382 device
= find_device(udev
, optarg
, "/sys");
383 if (device
== NULL
) {
384 fprintf(stderr
, "syspath not found\n");
390 action
= ACTION_QUERY
;
391 if (streq(optarg
, "property") || streq(optarg
, "env")) {
392 query
= QUERY_PROPERTY
;
393 } else if (streq(optarg
, "name")) {
395 } else if (streq(optarg
, "symlink")) {
396 query
= QUERY_SYMLINK
;
397 } else if (streq(optarg
, "path")) {
399 } else if (streq(optarg
, "all")) {
402 fprintf(stderr
, "unknown query type\n");
411 action
= ACTION_DEVICE_ID_FILE
;
412 strscpy(name
, sizeof(name
), optarg
);
415 action
= ACTION_ATTRIBUTE_WALK
;
418 export_devices(udev
);
427 export_prefix
= optarg
;
430 printf("%s\n", VERSION
);
433 printf("%s\n", usage
);
444 fprintf(stderr
, "%s\n", usage
);
448 device
= find_device(udev
, argv
[optind
], NULL
);
450 fprintf(stderr
, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n");
458 const char *node
= udev_device_get_devnode(device
);
461 fprintf(stderr
, "no device node found\n");
467 printf("%s\n", udev_device_get_devnode(device
));
469 printf("%s\n", udev_device_get_devnode(device
) + strlen("/dev/"));
473 list_entry
= udev_device_get_devlinks_list_entry(device
);
474 while (list_entry
!= NULL
) {
476 printf("%s", udev_list_entry_get_name(list_entry
));
478 printf("%s", udev_list_entry_get_name(list_entry
) + strlen("/dev/"));
479 list_entry
= udev_list_entry_get_next(list_entry
);
480 if (list_entry
!= NULL
)
486 printf("%s\n", udev_device_get_devpath(device
));
489 list_entry
= udev_device_get_properties_list_entry(device
);
490 while (list_entry
!= NULL
) {
492 const char *prefix
= export_prefix
;
496 printf("%s%s='%s'\n", prefix
,
497 udev_list_entry_get_name(list_entry
),
498 udev_list_entry_get_value(list_entry
));
500 printf("%s=%s\n", udev_list_entry_get_name(list_entry
), udev_list_entry_get_value(list_entry
));
502 list_entry
= udev_list_entry_get_next(list_entry
);
506 print_record(device
);
509 fprintf(stderr
, "unknown query type\n");
513 case ACTION_ATTRIBUTE_WALK
:
514 if (!device
&& argv
[optind
]) {
515 device
= find_device(udev
, argv
[optind
], NULL
);
517 fprintf(stderr
, "Unknown device, absolute path in /dev/ or /sys expected.\n");
523 fprintf(stderr
, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n");
527 print_device_chain(device
);
529 case ACTION_DEVICE_ID_FILE
:
530 if (stat_device(name
, export
, export_prefix
) != 0)
536 udev_device_unref(device
);
540 const struct udevadm_cmd udevadm_info
= {
543 .help
= "query sysfs or the udev database",