2 * Copyright (C) 2004-2006 Kay Sievers <kay.sievers@vrfy.org>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
34 void log_message (int priority, const char *format, ...)
38 if (priority > udev_log_priority)
41 va_start(args, format);
42 vsyslog(priority, format, args);
47 static void print_all_attributes(const char *devpath, const char *key)
53 strlcpy(path, sysfs_path, sizeof(path));
54 strlcat(path, devpath, sizeof(path));
58 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
60 char value[NAME_SIZE];
63 attr_value = sysfs_attr_get_value(devpath, dent->d_name);
64 if (attr_value == NULL)
66 len = strlcpy(value, attr_value, sizeof(value));
67 dbg("attr '%s'='%s'(%zi)", dent->d_name, value, len);
69 /* remove trailing newlines */
70 while (len && value[len-1] == '\n')
73 /* skip nonprintable attributes */
74 while (len && isprint(value[len-1]))
77 dbg("attribute value of '%s' non-printable, skip", dent->d_name);
81 replace_untrusted_chars(value);
82 printf(" %s{%s}==\"%s\"\n", key, dent->d_name, value);
88 static int print_device_chain(const char *devpath)
90 struct sysfs_device *dev;
93 "Udevinfo starts with the device specified by the devpath and then\n"
94 "walks up the chain of parent devices. It prints for every device\n"
95 "found, all possible attributes in the udev rules key format.\n"
96 "A rule to match, can be composed by the attributes of the device\n"
97 "and the attributes from one single parent device.\n"
100 dev = sysfs_device_get(devpath);
104 printf(" looking at device '%s':\n", dev->devpath);
105 printf(" KERNEL==\"%s\"\n", dev->kernel);
106 printf(" SUBSYSTEM==\"%s\"\n", dev->subsystem);
107 printf(" DRIVER==\"%s\"\n", dev->driver);
108 print_all_attributes(dev->devpath, "ATTR");
110 /* walk up the chain of devices */
112 dev = sysfs_device_get_parent(dev);
115 printf(" looking at parent device '%s':\n", dev->devpath);
116 printf(" KERNELS==\"%s\"\n", dev->kernel);
117 printf(" SUBSYTEMS==\"%s\"\n", dev->subsystem);
118 printf(" DRIVERS==\"%s\"\n", dev->driver);
120 print_all_attributes(dev->devpath, "ATTRS");
126 static void print_record(struct udevice *udev)
128 struct name_entry *name_loop;
130 printf("P: %s\n", udev->dev->devpath);
131 printf("N: %s\n", udev->name);
132 list_for_each_entry(name_loop, &udev->symlink_list, node)
133 printf("S: %s\n", name_loop->name);
134 list_for_each_entry(name_loop, &udev->env_list, node)
135 printf("E: %s\n", name_loop->name);
138 static void export_name_devpath(struct udevice *udev) {
139 printf("%s=%s/%s\n", udev->dev->devpath, udev_root, udev->name);
142 static void export_record(struct udevice *udev) {
147 static void export_db(void fnct(struct udevice *udev)) {
148 LIST_HEAD(name_list);
149 struct name_entry *name_loop;
151 udev_db_get_all_entries(&name_list);
152 list_for_each_entry(name_loop, &name_list, node) {
153 struct udevice *udev_db;
155 udev_db = udev_device_init();
158 if (udev_db_get_device(udev_db, name_loop->name) == 0)
160 udev_device_cleanup(udev_db);
162 name_list_cleanup(&name_list);
165 int main(int argc, char *argv[], char *envp[])
168 struct udevice *udev;
171 struct option options[] = {
172 { "name", 1, NULL, 'n' },
173 { "path", 1, NULL, 'p' },
174 { "query", 1, NULL, 'q' },
175 { "attribute-walk", 0, NULL, 'a' },
176 { "export-db", 0, NULL, 'e' },
177 { "root", 0, NULL, 'r' },
178 { "version", 0, NULL, 'V' },
179 { "help", 0, NULL, 'h' },
186 ACTION_ATTRIBUTE_WALK,
188 } action = ACTION_NONE;
197 } query = QUERY_NONE;
199 char path[PATH_SIZE] = "";
200 char name[PATH_SIZE] = "";
201 struct name_entry *name_loop;
204 logging_init("udevinfo");
208 udev = udev_device_init();
214 /* get command line options */
216 option = getopt_long(argc, argv, "aden:p:q:rVh", options, NULL);
220 dbg("option '%c'", option);
223 /* remove /dev if given */
224 if (strncmp(optarg, udev_root, strlen(udev_root)) == 0)
225 strlcpy(name, &optarg[strlen(udev_root)+1], sizeof(name));
227 strlcpy(name, optarg, sizeof(name));
228 dbg("name: %s\n", name);
231 /* remove /sys if given */
232 if (strncmp(optarg, sysfs_path, strlen(sysfs_path)) == 0)
233 strlcpy(path, &optarg[strlen(sysfs_path)], sizeof(path));
235 strlcpy(path, optarg, sizeof(path));
236 dbg("path: %s\n", path);
239 dbg("udev query: %s\n", optarg);
240 action = ACTION_QUERY;
241 if (strcmp(optarg, "name") == 0) {
245 if (strcmp(optarg, "symlink") == 0) {
246 query = QUERY_SYMLINK;
249 if (strcmp(optarg, "path") == 0) {
253 if (strcmp(optarg, "env") == 0) {
257 if (strcmp(optarg, "all") == 0) {
261 fprintf(stderr, "unknown query type\n");
265 if (action == ACTION_NONE)
266 action = ACTION_ROOT;
270 action = ACTION_ATTRIBUTE_WALK;
273 export_db(export_name_devpath);
276 export_db(export_record);
279 printf("udevinfo, version %s\n", UDEV_VERSION);
282 printf("Usage: udevinfo OPTIONS\n"
283 " --query=<type> query database for the specified value:\n"
284 " name name of device node\n"
285 " symlink pointing to node\n"
286 " path sysfs device path\n"
287 " env the device related imported environment\n"
290 " --path=<devpath> sysfs device path used for query or chain\n"
291 " --name=<name> node or symlink name used for query\n"
293 " --root prepend to query result or print udev_root\n"
294 " --attribute-walk print all SYSFS_attributes along the device chain\n"
295 " --export-db export the content of the udev database\n"
296 " --verision print udev version\n"
297 " --help print this text\n"
308 /* needs devpath or node/symlink name for query */
309 if (path[0] != '\0') {
310 if (udev_db_get_device(udev, path) != 0) {
311 fprintf(stderr, "no record for '%s' in database\n", path);
315 } else if (name[0] != '\0') {
316 char devpath[PATH_SIZE];
318 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
319 fprintf(stderr, "node name not found\n");
323 udev_db_get_device(udev, devpath);
325 fprintf(stderr, "query needs --path or node --name specified\n");
333 printf("%s/%s\n", udev_root, udev->name);
335 printf("%s\n", udev->name);
338 if (list_empty(&udev->symlink_list))
341 list_for_each_entry(name_loop, &udev->symlink_list, node)
342 printf("%s/%s ", udev_root, name_loop->name);
344 list_for_each_entry(name_loop, &udev->symlink_list, node)
345 printf("%s ", name_loop->name);
349 printf("%s\n", udev->dev->devpath);
352 list_for_each_entry(name_loop, &udev->env_list, node)
353 printf("%s\n", name_loop->name);
359 fprintf(stderr, "unknown query type\n");
363 case ACTION_ATTRIBUTE_WALK:
364 if (path[0] != '\0') {
365 print_device_chain(path);
366 } else if (name[0] != '\0') {
367 char devpath[PATH_SIZE];
369 if (udev_db_lookup_name(name, devpath, sizeof(devpath)) != 0) {
370 fprintf(stderr, "node name not found\n");
374 print_device_chain(devpath);
376 fprintf(stderr, "attribute walk needs --path or node --name specified\n");
382 printf("%s\n", udev_root);
385 fprintf(stderr, "missing option\n");
391 udev_device_cleanup(udev);