2 * udevinfo - fetches attributes for a device
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include "libsysfs/sysfs/libsysfs.h"
31 #include "libsysfs/dlist.h"
34 #include "udev_version.h"
39 # define SYSFS_VALUE_MAX 200
45 unsigned char logname[LOGNAME_SIZE];
46 void log_message (int level, const char *format, ...)
50 va_start(args, format);
51 vsyslog(level, format, args);
56 static int print_all_attributes(const char *path)
58 struct dlist *attributes;
59 struct sysfs_attribute *attr;
60 struct sysfs_directory *sysfs_dir;
61 char value[SYSFS_VALUE_MAX];
65 sysfs_dir = sysfs_open_directory(path);
66 if (sysfs_dir == NULL)
69 attributes = sysfs_get_dir_attributes(sysfs_dir);
70 if (attributes == NULL) {
75 dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
76 if (attr->value != NULL) {
77 strfieldcpy(value, attr->value);
82 /* remove trailing newline */
83 if (value[len-1] == '\n') {
88 /* skip nonprintable values */
90 if (isprint(value[len-1]) == 0)
95 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
101 sysfs_close_directory(sysfs_dir);
106 static int print_record(struct udevice *udev)
108 printf("P: %s\n", udev->devpath);
109 printf("N: %s\n", udev->name);
110 printf("S: %s\n", udev->symlink);
123 static int print_device_chain(const char *path)
125 struct sysfs_class_device *class_dev;
126 struct sysfs_class_device *class_dev_parent;
127 struct sysfs_attribute *attr;
128 struct sysfs_device *sysfs_dev;
129 struct sysfs_device *sysfs_dev_parent;
133 type = get_device_type(path, "");
134 dbg("device type is %c", type);
136 /* get the class dev */
137 class_dev = sysfs_open_class_device_path(path);
138 if (class_dev == NULL) {
139 printf("couldn't get the class device\n");
143 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
144 "device chain, to print for every device found, all possibly useful attributes\n"
145 "in the udev key format.\n"
146 "Only attributes within one device section may be used together in one rule,\n"
147 "to match the device for which the node will be created.\n"
150 if (type == 'b' || type =='c') {
151 /* read the 'dev' file for major/minor*/
152 attr = sysfs_get_classdev_attr(class_dev, "dev");
154 printf("couldn't get the \"dev\" file\n");
158 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
161 /* open sysfs class device directory and print all attributes */
162 printf(" looking at class device '%s':\n", class_dev->path);
163 if (print_all_attributes(class_dev->path) != 0) {
164 printf("couldn't open class device directory\n");
169 /* get the device link (if parent exists look here) */
170 class_dev_parent = sysfs_get_classdev_parent(class_dev);
171 if (class_dev_parent != NULL)
172 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
174 sysfs_dev = sysfs_get_classdev_device(class_dev);
176 if (sysfs_dev != NULL)
177 printf("follow the class device's \"device\"\n");
179 /* look the device chain upwards */
180 while (sysfs_dev != NULL) {
181 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
182 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
183 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
185 /* open sysfs device directory and print all attributes */
186 print_all_attributes(sysfs_dev->path);
188 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
189 if (sysfs_dev_parent == NULL)
192 sysfs_dev = sysfs_dev_parent;
196 sysfs_close_class_device(class_dev);
200 static int process_options(void)
202 static const char short_options[] = "adn:p:q:rVh";
208 enum query_type query = NONE;
209 char result[NAME_SIZE] = "";
210 char path[NAME_SIZE] = "";
211 char name[NAME_SIZE] = "";
212 char temp[NAME_SIZE];
215 /* get command line options */
217 option = getopt(main_argc, main_argv, short_options);
221 dbg("option '%c'", option);
224 dbg("udev name: %s\n", optarg);
225 strfieldcpy(name, optarg);
229 dbg("udev path: %s\n", optarg);
230 strfieldcpy(path, optarg);
234 dbg("udev query: %s\n", optarg);
236 if (strcmp(optarg, "name") == 0) {
241 if (strcmp(optarg, "symlink") == 0) {
246 if (strcmp(optarg, "path") == 0) {
251 if (strcmp(optarg, "all") == 0) {
256 printf("unknown query type\n");
268 printf("udevinfo, version %s\n", UDEV_VERSION);
279 /* process options */
281 if (path[0] != '\0') {
282 /* remove sysfs_path if given */
283 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
284 pos = path + strlen(sysfs_path);
286 if (path[0] != '/') {
287 /* prepend '/' if missing */
288 strfieldcat(temp, "/");
289 strfieldcat(temp, path);
295 memset(&udev, 0x00, sizeof(struct udevice));
296 strfieldcpy(udev.devpath, pos);
297 retval = udevdb_get_dev(&udev);
299 printf("device not found in database\n");
305 if (name[0] != '\0') {
306 /* remove udev_root if given */
307 int len = strlen(udev_root);
309 if (strncmp(name, udev_root, len) == 0) {
314 memset(&udev, 0x00, sizeof(struct udevice));
315 strfieldcpy(udev.name, pos);
316 retval = udevdb_get_dev_byname(&udev, pos);
318 printf("device not found in database\n");
325 printf("query needs device path(-p) or node name(-n) specified\n");
332 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
333 result[NAME_SIZE-1] = '\0';
335 strfieldcpy(result, udev.name);
340 strfieldcpy(result, udev.symlink);
344 strfieldcpy(result, path);
354 printf("%s\n", result);
361 if (path[0] == '\0') {
362 printf("attribute walk on device chain needs path(-p) specified\n");
365 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
366 /* prepend sysfs mountpoint if not given */
367 strfieldcpy(temp, path);
368 strfieldcpy(path, sysfs_path);
369 strfieldcat(path, temp);
371 print_device_chain(path);
377 printf("%s\n", udev_root);
382 printf("Usage: [-anpqrdVh]\n"
383 " -q TYPE query database for the specified value:\n"
384 " 'name' name of device node\n"
385 " 'symlink' pointing to node\n"
386 " 'path' sysfs device path\n"
387 " 'all' all values\n"
389 " -p PATH sysfs device path used for query or chain\n"
390 " -n NAME node/symlink name used for query\n"
392 " -r print udev root\n"
393 " -a print all SYSFS_attributes along the device chain\n"
394 " -V print udev version\n"
395 " -h print this help text\n"
400 int main(int argc, char *argv[], char *envp[])
407 logging_init("udevinfo");
409 /* initialize our configuration */
412 rc = process_options();