2 * udevinfo.c - fetches stored device information or sysfs attributes
4 * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 void log_message (int priority, const char *format, ...)
39 if (priority > udev_log_priority)
42 va_start(args, format);
43 vsyslog(priority, format, args);
48 static void print_all_attributes(const char *devpath)
54 strlcpy(path, sysfs_path, sizeof(path));
55 strlcat(path, devpath, sizeof(path));
59 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
61 char value[NAME_SIZE];
64 attr_value = sysfs_attr_get_value(devpath, dent->d_name);
65 if (attr_value == NULL)
67 len = strlcpy(value, attr_value, sizeof(value));
68 dbg("attr '%s'='%s'(%zi)", dent->d_name, value, len);
70 /* remove trailing newlines */
71 while (len && value[len-1] == '\n')
74 /* skip nonprintable attributes */
75 while (len && isprint(value[len-1]))
78 dbg("attribute value of '%s' non-printable, skip", dent->d_name);
82 replace_untrusted_chars(value);
83 printf(" SYSFS{%s}==\"%s\"\n", dent->d_name, value);
89 static int print_device_chain(const char *devpath)
91 struct sysfs_device *dev;
94 "udevinfo starts with the device the node belongs to and then walks up the\n"
95 "device chain, to print for every device found, all possibly useful attributes\n"
96 "in the udev key format.\n"
97 "Only attributes within one device section may be used together in one rule,\n"
98 "to match the device for which the node will be created.\n"
101 dev = sysfs_device_get(devpath);
105 printf(" looking at device '%s':\n", dev->devpath);
106 printf(" KERNEL==\"%s\"\n", dev->kernel_name);
107 printf(" SUBSYSTEM==\"%s\"\n", dev->subsystem);
108 print_all_attributes(dev->devpath);
110 /* walk up the chain of devices */
112 dev = sysfs_device_get_parent(dev);
115 printf(" looking at device '%s':\n", dev->devpath);
116 printf(" ID==\"%s\"\n", dev->kernel_name);
117 printf(" BUS==\"%s\"\n", dev->subsystem);
118 printf(" DRIVER==\"%s\"\n", dev->driver);
120 print_all_attributes(dev->devpath);
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 static void print_help(void)
167 fprintf(stderr, "Usage: udevinfo [-anpqrVh]\n"
168 " -q TYPE query database for the specified value:\n"
169 " 'name' name of device node\n"
170 " 'symlink' pointing to node\n"
171 " 'path' sysfs device path\n"
172 " 'env' the device related imported environment\n"
173 " 'all' all values\n"
175 " -p PATH sysfs device path used for query or chain\n"
176 " -n NAME node/symlink name used for query\n"
178 " -r prepend to query result or print udev_root\n"
179 " -a print all SYSFS_attributes along the device chain\n"
180 " -e export the content of the udev database\n"
181 " -V print udev version\n"
182 " -h print this help text\n"
186 int main(int argc, char *argv[], char *envp[])
188 static const char short_options[] = "aden:p:q:rVh";
190 struct udevice *udev;
196 ACTION_ATTRIBUTE_WALK,
198 } action = ACTION_NONE;
207 } query = QUERY_NONE;
209 char path[PATH_SIZE] = "";
210 char name[PATH_SIZE] = "";
211 char temp[PATH_SIZE];
212 struct name_entry *name_loop;
216 logging_init("udevinfo");
221 udev = udev_device_init();
227 /* get command line options */
229 option = getopt(argc, argv, short_options);
233 dbg("option '%c'", option);
236 dbg("udev name: %s\n", optarg);
237 strlcpy(name, optarg, sizeof(name));
240 dbg("udev path: %s\n", optarg);
241 /* remove sysfs mountpoint if not given */
242 if (strncmp(optarg, sysfs_path, strlen(sysfs_path)) == 0)
243 strlcpy(path, &optarg[strlen(sysfs_path)], sizeof(path));
245 strlcpy(path, optarg, sizeof(path));
248 dbg("udev query: %s\n", optarg);
249 action = ACTION_QUERY;
250 if (strcmp(optarg, "name") == 0) {
254 if (strcmp(optarg, "symlink") == 0) {
255 query = QUERY_SYMLINK;
258 if (strcmp(optarg, "path") == 0) {
262 if (strcmp(optarg, "env") == 0) {
266 if (strcmp(optarg, "all") == 0) {
270 fprintf(stderr, "unknown query type\n");
274 if (action == ACTION_NONE)
275 action = ACTION_ROOT;
279 action = ACTION_ATTRIBUTE_WALK;
282 export_db(export_name_devpath);
285 export_db(export_record);
288 printf("udevinfo, version %s\n", UDEV_VERSION);
301 /* need devpath or node/symlink name for query */
302 if (path[0] != '\0') {
303 /* remove sysfs_path if given */
304 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
305 pos = path + strlen(sysfs_path);
307 if (path[0] != '/') {
308 /* prepend '/' if missing */
310 strlcpy(temp, path, sizeof(temp));
316 if (udev_db_get_device(udev, pos) != 0) {
317 fprintf(stderr, "no record for '%s' in database\n", pos);
321 } else if (name[0] != '\0') {
322 char devpath[PATH_SIZE];
325 /* remove udev_root if given */
326 len = strlen(udev_root);
327 if (strncmp(name, udev_root, len) == 0) {
332 if (udev_db_lookup_name(pos, devpath, sizeof(devpath)) != 0) {
333 fprintf(stderr, "no record for '%s' in database\n", pos);
337 udev_db_get_device(udev, devpath);
339 fprintf(stderr, "query needs device path(-p) or node name(-n) specified\n");
347 printf("%s/%s\n", udev_root, udev->name);
349 printf("%s\n", udev->name);
352 if (list_empty(&udev->symlink_list))
355 list_for_each_entry(name_loop, &udev->symlink_list, node)
356 printf("%s/%s ", udev_root, name_loop->name);
358 list_for_each_entry(name_loop, &udev->symlink_list, node)
359 printf("%s ", name_loop->name);
363 printf("%s\n", udev->dev->devpath);
366 list_for_each_entry(name_loop, &udev->env_list, node)
367 printf("%s\n", name_loop->name);
377 case ACTION_ATTRIBUTE_WALK:
378 if (path[0] == '\0') {
379 fprintf(stderr, "attribute walk on device chain needs path(-p) specified\n");
383 print_device_chain(path);
386 printf("%s\n", udev_root);
395 udev_device_cleanup(udev);