]> git.ipfire.org Git - thirdparty/systemd.git/blame - udevinfo.c
[PATCH] klibc: remove SCCS directories from the temporary klibc install
[thirdparty/systemd.git] / udevinfo.c
CommitLineData
be9b51f6
KS
1/*
2 * udevinfo - fetches attributes for a device
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
be9b51f6
KS
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.
9 *
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.
14 *
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.
18 *
19 */
20
21#include <stdlib.h>
22#include <string.h>
23#include <stdio.h>
034f35d7 24#include <ctype.h>
87171e46
KS
25#include <stdarg.h>
26#include <unistd.h>
27#include <errno.h>
be9b51f6 28
c80da508 29#include "libsysfs/sysfs/libsysfs.h"
63f61c5c 30#include "udev_libc_wrapper.h"
869fc2f1 31#include "udev.h"
9af5bb2f 32#include "udev_utils.h"
869fc2f1 33#include "udev_version.h"
02fa9ae5 34#include "udev_db.h"
869fc2f1 35#include "logging.h"
be9b51f6
KS
36
37
6c18b1fb 38#ifdef USE_LOG
d026a35d 39void log_message (int level, const char *format, ...)
51a8bb2f 40{
d026a35d
GKH
41 va_list args;
42
43 va_start(args, format);
44 vsyslog(level, format, args);
45 va_end(args);
51a8bb2f 46}
d026a35d 47#endif
51a8bb2f 48
f385ff65 49static void print_all_attributes(struct dlist *attr_list)
be9b51f6 50{
be9b51f6 51 struct sysfs_attribute *attr;
63f61c5c 52 char value[VALUE_SIZE];
be9b51f6 53 int len;
be9b51f6 54
f385ff65 55 dlist_for_each_data(attr_list, attr, struct sysfs_attribute) {
be9b51f6 56 if (attr->value != NULL) {
63f61c5c 57 strlcpy(value, attr->value, sizeof(value));
be9b51f6 58 len = strlen(value);
034f35d7
KS
59 if (len == 0)
60 continue;
61
62 /* remove trailing newline */
63 if (value[len-1] == '\n') {
be9b51f6 64 value[len-1] = '\0';
034f35d7
KS
65 len--;
66 }
67
68 /* skip nonprintable values */
69 while (len) {
70 if (isprint(value[len-1]) == 0)
71 break;
72 len--;
73 }
74 if (len == 0)
16378373 75 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
be9b51f6
KS
76 }
77 }
78 printf("\n");
be9b51f6
KS
79}
80
2b41e68a 81static int print_record(struct udevice *udev)
87171e46 82{
e48fc108
KS
83 struct name_entry *name_loop;
84
2b41e68a
KS
85 printf("P: %s\n", udev->devpath);
86 printf("N: %s\n", udev->name);
e48fc108
KS
87 list_for_each_entry(name_loop, &udev->symlink_list, node)
88 printf("S: %s\n", name_loop->name);
89
87171e46
KS
90 return 0;
91}
92
93enum query_type {
94 NONE,
95 NAME,
96 PATH,
97 SYMLINK,
e48fc108 98 ALL,
87171e46
KS
99};
100
101static int print_device_chain(const char *path)
be9b51f6 102{
be9b51f6
KS
103 struct sysfs_class_device *class_dev;
104 struct sysfs_class_device *class_dev_parent;
105 struct sysfs_attribute *attr;
034f35d7
KS
106 struct sysfs_device *sysfs_dev;
107 struct sysfs_device *sysfs_dev_parent;
f385ff65 108 struct dlist *attr_list;
be9b51f6
KS
109 int retval = 0;
110
be9b51f6
KS
111 /* get the class dev */
112 class_dev = sysfs_open_class_device_path(path);
113 if (class_dev == NULL) {
114 printf("couldn't get the class device\n");
115 return -1;
116 }
117
dba8c18b 118 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
ebc39fef 119 "device chain, to print for every device found, all possibly useful attributes\n"
dba8c18b 120 "in the udev key format.\n"
ebc39fef
KS
121 "Only attributes within one device section may be used together in one rule,\n"
122 "to match the device for which the node will be created.\n"
dba8c18b 123 "\n");
f61d732a 124
fc2aa296
KS
125 /* look for the 'dev' file */
126 attr = sysfs_get_classdev_attr(class_dev, "dev");
c02ae2fe 127 if (attr != NULL)
f61d732a 128 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
be9b51f6
KS
129
130 /* open sysfs class device directory and print all attributes */
034f35d7 131 printf(" looking at class device '%s':\n", class_dev->path);
f51d8ec6 132 printf(" SUBSYSTEM=\"%s\"\n", class_dev->classname);
f385ff65
KS
133
134 attr_list = sysfs_get_classdev_attributes(class_dev);
135 if (attr_list == NULL) {
be9b51f6
KS
136 printf("couldn't open class device directory\n");
137 retval = -1;
138 goto exit;
139 }
f385ff65 140 print_all_attributes(attr_list);
be9b51f6 141
034f35d7 142 /* get the device link (if parent exists look here) */
be9b51f6 143 class_dev_parent = sysfs_get_classdev_parent(class_dev);
a291a14b
DS
144 if (class_dev_parent != NULL)
145 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
146 else
147 sysfs_dev = sysfs_get_classdev_device(class_dev);
148
034f35d7
KS
149 if (sysfs_dev != NULL)
150 printf("follow the class device's \"device\"\n");
151
152 /* look the device chain upwards */
153 while (sysfs_dev != NULL) {
f385ff65
KS
154 attr_list = sysfs_get_device_attributes(sysfs_dev);
155 if (attr_list == NULL) {
156 printf("couldn't open device directory\n");
157 retval = -1;
158 goto exit;
159 }
160
034f35d7
KS
161 printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
162 printf(" BUS=\"%s\"\n", sysfs_dev->bus);
163 printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
f51d8ec6 164 printf(" DRIVER=\"%s\"\n", sysfs_dev->driver_name);
be9b51f6
KS
165
166 /* open sysfs device directory and print all attributes */
f385ff65 167 print_all_attributes(attr_list);
034f35d7
KS
168
169 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
170 if (sysfs_dev_parent == NULL)
171 break;
172
034f35d7 173 sysfs_dev = sysfs_dev_parent;
be9b51f6
KS
174 }
175
176exit:
a291a14b 177 sysfs_close_class_device(class_dev);
be9b51f6
KS
178 return retval;
179}
87171e46 180
599e17a3 181static int print_dump(const char *devpath, const char *name) {
3810823b 182 printf("%s=%s/%s\n", devpath, udev_root, name);
9fe1a96d
KS
183 return 0;
184}
185
e48fc108 186int main(int argc, char *argv[], char *envp[])
87171e46 187{
9fe1a96d 188 static const char short_options[] = "adn:p:q:rVh";
87171e46 189 int option;
2b41e68a 190 struct udevice udev;
87171e46
KS
191 int root = 0;
192 int attributes = 0;
193 enum query_type query = NONE;
63f61c5c
KS
194 char path[PATH_SIZE] = "";
195 char name[PATH_SIZE] = "";
196 char temp[PATH_SIZE];
e48fc108 197 struct name_entry *name_loop;
87171e46 198 char *pos;
e48fc108
KS
199 int retval = 0;
200
201 logging_init("udevinfo");
202
203 udev_init_config();
204 udev_init_device(&udev, NULL, NULL);
87171e46
KS
205
206 /* get command line options */
207 while (1) {
af4b05d4 208 option = getopt(argc, argv, short_options);
87171e46
KS
209 if (option == -1)
210 break;
211
212 dbg("option '%c'", option);
213 switch (option) {
214 case 'n':
215 dbg("udev name: %s\n", optarg);
63f61c5c 216 strlcpy(name, optarg, sizeof(name));
87171e46
KS
217 break;
218
219 case 'p':
220 dbg("udev path: %s\n", optarg);
63f61c5c 221 strlcpy(path, optarg, sizeof(path));
87171e46
KS
222 break;
223
224 case 'q':
225 dbg("udev query: %s\n", optarg);
226
227 if (strcmp(optarg, "name") == 0) {
228 query = NAME;
229 break;
230 }
231
232 if (strcmp(optarg, "symlink") == 0) {
233 query = SYMLINK;
234 break;
235 }
236
87171e46
KS
237 if (strcmp(optarg, "path") == 0) {
238 query = PATH;
239 break;
240 }
241
8ea84a8a
KS
242 if (strcmp(optarg, "all") == 0) {
243 query = ALL;
244 break;
245 }
246
87171e46 247 printf("unknown query type\n");
e48fc108
KS
248 retval = 1;
249 goto exit;
87171e46
KS
250
251 case 'r':
252 root = 1;
253 break;
254
255 case 'a':
256 attributes = 1;
257 break;
258
9fe1a96d 259 case 'd':
599e17a3 260 udev_db_dump_names(print_dump);
e48fc108 261 goto exit;
9fe1a96d 262
87171e46 263 case 'V':
869fc2f1 264 printf("udevinfo, version %s\n", UDEV_VERSION);
e48fc108 265 goto exit;
87171e46
KS
266
267 case 'h':
e48fc108 268 retval = 2;
87171e46
KS
269 case '?':
270 default:
271 goto help;
272 }
273 }
274
275 /* process options */
276 if (query != NONE) {
87171e46
KS
277 if (path[0] != '\0') {
278 /* remove sysfs_path if given */
279 if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
280 pos = path + strlen(sysfs_path);
281 } else {
282 if (path[0] != '/') {
283 /* prepend '/' if missing */
e48fc108 284 strcpy(temp, "/");
63f61c5c 285 strlcpy(temp, path, sizeof(temp));
87171e46
KS
286 pos = temp;
287 } else {
288 pos = path;
289 }
290 }
e48fc108 291 retval = udev_db_get_device(&udev, pos);
87171e46
KS
292 if (retval != 0) {
293 printf("device not found in database\n");
294 goto exit;
295 }
296 goto print;
297 }
298
299 if (name[0] != '\0') {
63f61c5c 300 char devpath[PATH_SIZE];
e48fc108 301 int len;
2b41e68a 302
e48fc108
KS
303 /* remove udev_root if given */
304 len = strlen(udev_root);
2b41e68a
KS
305 if (strncmp(name, udev_root, len) == 0) {
306 pos = &name[len+1];
87171e46
KS
307 } else
308 pos = name;
2b41e68a 309
63f61c5c 310 retval = udev_db_search_name(devpath, sizeof(devpath), pos);
87171e46
KS
311 if (retval != 0) {
312 printf("device not found in database\n");
313 goto exit;
314 }
e48fc108 315 udev_db_get_device(&udev, devpath);
87171e46
KS
316 goto print;
317 }
318
319 printf("query needs device path(-p) or node name(-n) specified\n");
e48fc108 320 retval = 3;
87171e46
KS
321 goto exit;
322
323print:
324 switch(query) {
325 case NAME:
e48fc108
KS
326 if (root)
327 printf("%s/%s\n", udev_root, udev.name);
328 else
329 printf("%s\n", udev.name);
330 goto exit;
87171e46 331 case SYMLINK:
e48fc108
KS
332 if (list_empty(&udev.symlink_list))
333 break;
334 if (root)
335 list_for_each_entry(name_loop, &udev.symlink_list, node)
336 printf("%s/%s ", udev_root, name_loop->name);
337 else
338 list_for_each_entry(name_loop, &udev.symlink_list, node)
339 printf("%s ", name_loop->name);
340 printf("\n");
341 goto exit;
87171e46 342 case PATH:
e48fc108
KS
343 printf("%s\n", udev.devpath);
344 goto exit;
8ea84a8a 345 case ALL:
2b41e68a 346 print_record(&udev);
8ea84a8a 347 goto exit;
87171e46 348 default:
e48fc108 349 goto help;
87171e46 350 }
87171e46
KS
351 }
352
353 if (attributes) {
354 if (path[0] == '\0') {
355 printf("attribute walk on device chain needs path(-p) specified\n");
e48fc108
KS
356 retval = 4;
357 goto exit;
87171e46
KS
358 } else {
359 if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
360 /* prepend sysfs mountpoint if not given */
63f61c5c
KS
361 snprintf(temp, sizeof(temp), "%s%s", sysfs_path, path);
362 temp[sizeof(temp)-1] = '\0';
363 strlcpy(path, temp, sizeof(temp));
87171e46
KS
364 }
365 print_device_chain(path);
e48fc108 366 goto exit;
87171e46
KS
367 }
368 }
369
370 if (root) {
371 printf("%s\n", udev_root);
e48fc108 372 goto exit;
87171e46
KS
373 }
374
375help:
9af17555 376 printf("Usage: udevinfo [-anpqrVh]\n"
87171e46
KS
377 " -q TYPE query database for the specified value:\n"
378 " 'name' name of device node\n"
379 " 'symlink' pointing to node\n"
87171e46 380 " 'path' sysfs device path\n"
8ea84a8a
KS
381 " 'all' all values\n"
382 "\n"
87171e46 383 " -p PATH sysfs device path used for query or chain\n"
8ea84a8a 384 " -n NAME node/symlink name used for query\n"
87171e46
KS
385 "\n"
386 " -r print udev root\n"
2a25816f 387 " -a print all SYSFS_attributes along the device chain\n"
9fe1a96d
KS
388 " -d print the relationship of devpath and the node name for all\n"
389 " devices available in the database\n"
87171e46
KS
390 " -V print udev version\n"
391 " -h print this help text\n"
392 "\n");
7257cb18 393
e48fc108
KS
394exit:
395 udev_cleanup_device(&udev);
7257cb18 396 logging_close();
e48fc108 397 return retval;
87171e46 398}