]> git.ipfire.org Git - thirdparty/systemd.git/blame - udevinfo.c
[PATCH] pass the whole event environment to udevd
[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 *
6 *
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.
10 *
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.
15 *
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.
19 *
20 */
21
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
034f35d7 25#include <ctype.h>
87171e46
KS
26#include <stdarg.h>
27#include <unistd.h>
28#include <errno.h>
be9b51f6 29
c80da508
GKH
30#include "libsysfs/sysfs/libsysfs.h"
31#include "libsysfs/dlist.h"
869fc2f1 32#include "udev.h"
c81b35c0 33#include "udev_lib.h"
869fc2f1
GKH
34#include "udev_version.h"
35#include "logging.h"
36#include "udevdb.h"
be9b51f6
KS
37
38
87171e46 39# define SYSFS_VALUE_MAX 200
be9b51f6
KS
40
41char **main_argv;
87171e46 42int main_argc;
be9b51f6 43
d026a35d 44#ifdef LOG
d00bd172 45unsigned char logname[LOGNAME_SIZE];
d026a35d 46void log_message (int level, const char *format, ...)
51a8bb2f 47{
d026a35d
GKH
48 va_list args;
49
50 va_start(args, format);
51 vsyslog(level, format, args);
52 va_end(args);
51a8bb2f 53}
d026a35d 54#endif
51a8bb2f 55
87171e46 56static int print_all_attributes(const char *path)
be9b51f6
KS
57{
58 struct dlist *attributes;
59 struct sysfs_attribute *attr;
60 struct sysfs_directory *sysfs_dir;
87171e46 61 char value[SYSFS_VALUE_MAX];
be9b51f6
KS
62 int len;
63 int retval = 0;
64
65 sysfs_dir = sysfs_open_directory(path);
66 if (sysfs_dir == NULL)
67 return -1;
68
69 attributes = sysfs_get_dir_attributes(sysfs_dir);
70 if (attributes == NULL) {
71 retval = -1;
72 goto exit;
73 }
74
75 dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
76 if (attr->value != NULL) {
c472e3c8 77 strfieldcpy(value, attr->value);
be9b51f6 78 len = strlen(value);
034f35d7
KS
79 if (len == 0)
80 continue;
81
82 /* remove trailing newline */
83 if (value[len-1] == '\n') {
be9b51f6 84 value[len-1] = '\0';
034f35d7
KS
85 len--;
86 }
87
88 /* skip nonprintable values */
89 while (len) {
90 if (isprint(value[len-1]) == 0)
91 break;
92 len--;
93 }
94 if (len == 0)
16378373 95 printf(" SYSFS{%s}=\"%s\"\n", attr->name, value);
be9b51f6
KS
96 }
97 }
98 printf("\n");
99
100exit:
101 sysfs_close_directory(sysfs_dir);
102
103 return retval;
104}
105
2b41e68a 106static int print_record(struct udevice *udev)
87171e46 107{
2b41e68a
KS
108 printf("P: %s\n", udev->devpath);
109 printf("N: %s\n", udev->name);
110 printf("S: %s\n", udev->symlink);
87171e46
KS
111 printf("\n");
112 return 0;
113}
114
115enum query_type {
116 NONE,
117 NAME,
118 PATH,
119 SYMLINK,
8ea84a8a 120 ALL
87171e46
KS
121};
122
123static int print_device_chain(const char *path)
be9b51f6 124{
be9b51f6
KS
125 struct sysfs_class_device *class_dev;
126 struct sysfs_class_device *class_dev_parent;
127 struct sysfs_attribute *attr;
034f35d7
KS
128 struct sysfs_device *sysfs_dev;
129 struct sysfs_device *sysfs_dev_parent;
be9b51f6 130 int retval = 0;
f61d732a
KS
131 char type;
132
133 type = get_device_type(path, "");
134 dbg("device type is %c", type);
be9b51f6 135
be9b51f6
KS
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");
140 return -1;
141 }
142
dba8c18b 143 printf("\nudevinfo starts with the device the node belongs to and then walks up the\n"
ebc39fef 144 "device chain, to print for every device found, all possibly useful attributes\n"
dba8c18b 145 "in the udev key format.\n"
ebc39fef
KS
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"
dba8c18b 148 "\n");
f61d732a
KS
149
150 if (type == 'b' || type =='c') {
151 /* read the 'dev' file for major/minor*/
152 attr = sysfs_get_classdev_attr(class_dev, "dev");
153 if (attr == NULL) {
154 printf("couldn't get the \"dev\" file\n");
155 retval = -1;
156 goto exit;
157 }
158 printf("device '%s' has major:minor %s", class_dev->path, attr->value);
159 }
be9b51f6
KS
160
161 /* open sysfs class device directory and print all attributes */
034f35d7 162 printf(" looking at class device '%s':\n", class_dev->path);
be9b51f6
KS
163 if (print_all_attributes(class_dev->path) != 0) {
164 printf("couldn't open class device directory\n");
165 retval = -1;
166 goto exit;
167 }
168
034f35d7 169 /* get the device link (if parent exists look here) */
be9b51f6 170 class_dev_parent = sysfs_get_classdev_parent(class_dev);
a291a14b
DS
171 if (class_dev_parent != NULL)
172 sysfs_dev = sysfs_get_classdev_device(class_dev_parent);
173 else
174 sysfs_dev = sysfs_get_classdev_device(class_dev);
175
034f35d7
KS
176 if (sysfs_dev != NULL)
177 printf("follow the class device's \"device\"\n");
178
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);
be9b51f6
KS
184
185 /* open sysfs device directory and print all attributes */
034f35d7
KS
186 print_all_attributes(sysfs_dev->path);
187
188 sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
189 if (sysfs_dev_parent == NULL)
190 break;
191
034f35d7 192 sysfs_dev = sysfs_dev_parent;
be9b51f6
KS
193 }
194
195exit:
a291a14b 196 sysfs_close_class_device(class_dev);
be9b51f6
KS
197 return retval;
198}
87171e46
KS
199
200static int process_options(void)
201{
202 static const char short_options[] = "adn:p:q:rVh";
203 int option;
204 int retval = 1;
2b41e68a 205 struct udevice udev;
87171e46
KS
206 int root = 0;
207 int attributes = 0;
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];
213 char *pos;
214
215 /* get command line options */
216 while (1) {
217 option = getopt(main_argc, main_argv, short_options);
218 if (option == -1)
219 break;
220
221 dbg("option '%c'", option);
222 switch (option) {
223 case 'n':
224 dbg("udev name: %s\n", optarg);
225 strfieldcpy(name, optarg);
226 break;
227
228 case 'p':
229 dbg("udev path: %s\n", optarg);
230 strfieldcpy(path, optarg);
231 break;
232
233 case 'q':
234 dbg("udev query: %s\n", optarg);
235
236 if (strcmp(optarg, "name") == 0) {
237 query = NAME;
238 break;
239 }
240
241 if (strcmp(optarg, "symlink") == 0) {
242 query = SYMLINK;
243 break;
244 }
245
87171e46
KS
246 if (strcmp(optarg, "path") == 0) {
247 query = PATH;
248 break;
249 }
250
8ea84a8a
KS
251 if (strcmp(optarg, "all") == 0) {
252 query = ALL;
253 break;
254 }
255
87171e46
KS
256 printf("unknown query type\n");
257 exit(1);
258
259 case 'r':
260 root = 1;
261 break;
262
263 case 'a':
264 attributes = 1;
265 break;
266
87171e46 267 case 'V':
869fc2f1 268 printf("udevinfo, version %s\n", UDEV_VERSION);
87171e46
KS
269 exit(0);
270
271 case 'h':
272 retval = 0;
273 case '?':
274 default:
275 goto help;
276 }
277 }
278
279 /* process options */
280 if (query != NONE) {
87171e46
KS
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);
285 } else {
286 if (path[0] != '/') {
287 /* prepend '/' if missing */
c472e3c8
KS
288 strfieldcat(temp, "/");
289 strfieldcat(temp, path);
87171e46
KS
290 pos = temp;
291 } else {
292 pos = path;
293 }
294 }
2b41e68a
KS
295 memset(&udev, 0x00, sizeof(struct udevice));
296 strfieldcpy(udev.devpath, pos);
297 retval = udevdb_get_dev(&udev);
87171e46
KS
298 if (retval != 0) {
299 printf("device not found in database\n");
300 goto exit;
301 }
302 goto print;
303 }
304
305 if (name[0] != '\0') {
306 /* remove udev_root if given */
2b41e68a
KS
307 int len = strlen(udev_root);
308
309 if (strncmp(name, udev_root, len) == 0) {
310 pos = &name[len+1];
87171e46
KS
311 } else
312 pos = name;
2b41e68a
KS
313
314 memset(&udev, 0x00, sizeof(struct udevice));
315 strfieldcpy(udev.name, pos);
316 retval = udevdb_get_dev_byname(&udev, pos);
87171e46
KS
317 if (retval != 0) {
318 printf("device not found in database\n");
319 goto exit;
320 }
2b41e68a 321
87171e46
KS
322 goto print;
323 }
324
325 printf("query needs device path(-p) or node name(-n) specified\n");
326 goto exit;
327
328print:
329 switch(query) {
330 case NAME:
2b41e68a
KS
331 if (root) {
332 snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
333 result[NAME_SIZE-1] = '\0';
334 } else {
335 strfieldcpy(result, udev.name);
336 }
87171e46
KS
337 break;
338
339 case SYMLINK:
2b41e68a 340 strfieldcpy(result, udev.symlink);
87171e46
KS
341 break;
342
343 case PATH:
344 strfieldcpy(result, path);
345 break;
346
8ea84a8a 347 case ALL:
2b41e68a 348 print_record(&udev);
8ea84a8a
KS
349 goto exit;
350
87171e46
KS
351 default:
352 goto exit;
353 }
354 printf("%s\n", result);
355
356exit:
87171e46
KS
357 return retval;
358 }
359
360 if (attributes) {
361 if (path[0] == '\0') {
362 printf("attribute walk on device chain needs path(-p) specified\n");
363 return -EINVAL;
364 } else {
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);
c472e3c8 369 strfieldcat(path, temp);
87171e46
KS
370 }
371 print_device_chain(path);
372 return 0;
373 }
374 }
375
376 if (root) {
377 printf("%s\n", udev_root);
378 return 0;
379 }
380
381help:
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"
87171e46 386 " 'path' sysfs device path\n"
8ea84a8a
KS
387 " 'all' all values\n"
388 "\n"
87171e46 389 " -p PATH sysfs device path used for query or chain\n"
8ea84a8a 390 " -n NAME node/symlink name used for query\n"
87171e46
KS
391 "\n"
392 " -r print udev root\n"
2a25816f 393 " -a print all SYSFS_attributes along the device chain\n"
87171e46
KS
394 " -V print udev version\n"
395 " -h print this help text\n"
396 "\n");
397 return retval;
398}
399
400int main(int argc, char *argv[], char *envp[])
401{
7257cb18 402 int rc = 0;
87171e46
KS
403
404 main_argv = argv;
405 main_argc = argc;
87171e46 406
7257cb18 407 logging_init("udevinfo");
95a6f4c8 408
87171e46
KS
409 /* initialize our configuration */
410 udev_init_config();
411
7257cb18
KS
412 rc = process_options();
413
414 logging_close();
415 exit(rc);
87171e46 416}