]>
Commit | Line | Data |
---|---|---|
8e41d35d DS |
1 | /* |
2 | * udev database library | |
3 | */ | |
4 | #include <stdlib.h> | |
5 | #include <stdio.h> | |
6 | #include <fcntl.h> | |
7 | #include <string.h> | |
8 | #include <sys/stat.h> | |
9 | #include <errno.h> | |
10 | ||
11 | #include "udevdb.h" | |
12 | #include "tdb.h" | |
13 | ||
14 | static TDB_CONTEXT *busdb; | |
15 | static TDB_CONTEXT *classdb; | |
16 | static TDB_CONTEXT *namedb; | |
17 | ||
18 | /** | |
19 | * busdb_record - bus and id are keys to look up name of device | |
20 | */ | |
21 | struct busdb_record { | |
22 | char name[NAME_SIZE]; | |
23 | }; | |
24 | ||
25 | /** | |
26 | * classdb_record - class name and class device name used as keys to find | |
27 | * device name. | |
28 | */ | |
29 | struct classdb_record { | |
30 | char name[NAME_SIZE]; | |
31 | }; | |
32 | ||
33 | /** | |
34 | * namedb_record - device name is key, remaining udevice info stored here. | |
35 | */ | |
36 | struct namedb_record { | |
37 | char sysfs_path[PATH_SIZE]; | |
38 | char class_dev_name[NAME_SIZE]; | |
39 | char class_name[NAME_SIZE]; | |
40 | char bus[BUS_SIZE]; | |
41 | char id[ID_SIZE]; | |
42 | char driver[NAME_SIZE]; | |
43 | char type; | |
44 | int major; | |
45 | int minor; | |
46 | int mode; | |
47 | }; | |
48 | ||
49 | /** | |
50 | * busdb_close: close busdb database | |
51 | */ | |
52 | static void busdb_close(void) | |
53 | { | |
54 | if (busdb != NULL) { | |
55 | tdb_close(busdb); | |
56 | busdb = NULL; | |
57 | } | |
58 | } | |
59 | ||
60 | /** | |
61 | * classdb_close: close classdb database | |
62 | */ | |
63 | static void classdb_close(void) | |
64 | { | |
65 | if (classdb != NULL) { | |
66 | tdb_close(classdb); | |
67 | classdb = NULL; | |
68 | } | |
69 | } | |
70 | ||
71 | /** | |
72 | * namedb_close: close name database | |
73 | */ | |
74 | static void namedb_close(void) | |
75 | { | |
76 | if (namedb != NULL) { | |
77 | tdb_close(namedb); | |
78 | namedb = NULL; | |
79 | } | |
80 | } | |
81 | ||
82 | /** | |
83 | * busdb_open: open busdb's database | |
84 | */ | |
85 | static int busdb_open(void) | |
86 | { | |
87 | busdb = tdb_open(BUS_DB, 0, 0, O_RDWR | O_CREAT, 0644); | |
88 | if (busdb == NULL) | |
89 | return -1; | |
90 | return 0; | |
91 | } | |
92 | ||
93 | /** | |
94 | * classdb_open: open classdb's database | |
95 | */ | |
96 | static int classdb_open(void) | |
97 | { | |
98 | classdb = tdb_open(CLASS_DB, 0, 0, O_RDWR | O_CREAT, 0644); | |
99 | if (classdb == NULL) | |
100 | return -1; | |
101 | return 0; | |
102 | } | |
103 | ||
104 | /** | |
105 | * namedb_open: open name database | |
106 | */ | |
107 | static int namedb_open(void) | |
108 | { | |
109 | namedb = tdb_open(NAME_DB, 0, 0, O_RDWR | O_CREAT, 0644); | |
110 | if (namedb == NULL) | |
111 | return -1; | |
112 | return 0; | |
113 | } | |
114 | ||
115 | /** | |
116 | * busdb_fetch | |
117 | */ | |
118 | static struct busdb_record *busdb_fetch(const char *bus, const char *id) | |
119 | { | |
120 | TDB_DATA key, data; | |
121 | char keystr[BUS_SIZE+ID_SIZE+2]; | |
122 | struct busdb_record *rec = NULL; | |
123 | ||
124 | if (bus == NULL || id == NULL) | |
125 | return NULL; | |
126 | if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE) | |
127 | return NULL; | |
128 | ||
129 | if ((busdb_open()) != 0) | |
130 | return NULL; | |
131 | ||
132 | memset(keystr, 0, (BUS_SIZE+ID_SIZE+2)); | |
133 | strcpy(keystr, bus); | |
134 | strcat(keystr, UDEVDB_DEL); | |
135 | strcat(keystr, id); | |
136 | ||
137 | key.dptr = (void *)keystr; | |
138 | key.dsize = strlen(keystr) + 1; | |
139 | ||
140 | data = tdb_fetch(busdb, key); | |
141 | busdb_close(); | |
142 | if (data.dptr == NULL || data.dsize == 0) | |
143 | return NULL; | |
144 | ||
145 | rec = (struct busdb_record *)malloc(sizeof(struct busdb_record)); | |
146 | if (rec == NULL) { | |
147 | free(data.dptr); | |
148 | return NULL; | |
149 | } | |
150 | ||
151 | memcpy(rec, data.dptr, sizeof(struct busdb_record)); | |
152 | free(data.dptr); | |
153 | ||
154 | return rec; | |
155 | } | |
156 | ||
157 | /** | |
158 | * classdb_fetch | |
159 | */ | |
160 | static struct classdb_record *classdb_fetch(const char *cls, | |
161 | const char *cls_dev) | |
162 | { | |
163 | TDB_DATA key, data; | |
164 | char keystr[NAME_SIZE+NAME_SIZE+2]; | |
165 | struct classdb_record *rec = NULL; | |
166 | ||
167 | if (cls == NULL || cls_dev == NULL) | |
168 | return NULL; | |
169 | if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE) | |
170 | return NULL; | |
171 | ||
172 | if ((classdb_open()) != 0) | |
173 | return NULL; | |
174 | ||
175 | memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2)); | |
176 | strcpy(keystr, cls); | |
177 | strcat(keystr, UDEVDB_DEL); | |
178 | strcat(keystr, cls_dev); | |
179 | ||
180 | key.dptr = (void *)keystr; | |
181 | key.dsize = strlen(keystr) + 1; | |
182 | ||
183 | data = tdb_fetch(classdb, key); | |
184 | classdb_close(); | |
185 | if (data.dptr == NULL || data.dsize == 0) | |
186 | return NULL; | |
187 | ||
188 | rec = (struct classdb_record *)malloc(sizeof(struct classdb_record)); | |
189 | if (rec == NULL) { | |
190 | free(data.dptr); | |
191 | return NULL; | |
192 | } | |
193 | ||
194 | memcpy(rec, data.dptr, sizeof(struct classdb_record)); | |
195 | free(data.dptr); | |
196 | ||
197 | return rec; | |
198 | } | |
199 | ||
200 | /** | |
201 | * namedb_fetch | |
202 | */ | |
203 | static struct namedb_record *namedb_fetch(const char *name) | |
204 | { | |
205 | TDB_DATA key, data; | |
206 | char nm_keystr[NAME_SIZE]; | |
207 | struct namedb_record *nrec = NULL; | |
208 | ||
209 | if (name == NULL) | |
210 | return NULL; | |
211 | if (strlen(name) >= NAME_SIZE) | |
212 | return NULL; | |
213 | ||
214 | if ((namedb_open()) != 0) | |
215 | return NULL; | |
216 | ||
217 | memset(nm_keystr, 0, NAME_SIZE); | |
218 | strcpy(nm_keystr, name); | |
219 | ||
220 | key.dptr = (void *)nm_keystr; | |
221 | key.dsize = strlen(nm_keystr) + 1; | |
222 | ||
223 | data = tdb_fetch(namedb, key); | |
224 | namedb_close(); | |
225 | ||
226 | if (data.dptr == NULL || data.dsize == 0) | |
227 | return NULL; | |
228 | ||
229 | nrec = (struct namedb_record *)malloc(sizeof(struct namedb_record)); | |
230 | if (nrec == NULL) { | |
231 | free(data.dptr); | |
232 | return NULL; | |
233 | } | |
234 | ||
235 | memcpy(nrec, data.dptr, sizeof(struct namedb_record)); | |
236 | free(data.dptr); | |
237 | ||
238 | return nrec; | |
239 | } | |
240 | ||
241 | /** | |
242 | * busdb_store | |
243 | */ | |
244 | static int busdb_store(const struct udevice *dev) | |
245 | { | |
246 | TDB_DATA key, data; | |
247 | char keystr[BUS_SIZE+ID_SIZE+2]; | |
248 | struct busdb_record rec; | |
249 | int retval = 0; | |
250 | ||
251 | if (dev == NULL) | |
252 | return -1; | |
253 | ||
254 | if ((retval = busdb_open()) != 0) | |
255 | return -1; | |
256 | ||
257 | memset(keystr, 0, (BUS_SIZE+ID_SIZE+2)); | |
258 | strcpy(keystr, dev->bus_name); | |
259 | strcat(keystr, UDEVDB_DEL); | |
260 | strcat(keystr, dev->bus_id); | |
261 | ||
262 | key.dptr = (void *)keystr; | |
263 | key.dsize = strlen(keystr) + 1; | |
264 | ||
265 | strcpy(rec.name, dev->name); | |
266 | ||
267 | data.dptr = (void *) &rec; | |
268 | data.dsize = sizeof(rec); | |
269 | ||
270 | retval = tdb_store(busdb, key, data, TDB_REPLACE); | |
271 | ||
272 | busdb_close(); | |
273 | return retval; | |
274 | } | |
275 | ||
276 | /** | |
277 | * classdb_store | |
278 | */ | |
279 | static int classdb_store(const struct udevice *dev) | |
280 | { | |
281 | TDB_DATA key, data; | |
282 | char keystr[NAME_SIZE+NAME_SIZE+2]; | |
283 | struct classdb_record rec; | |
284 | int retval = 0; | |
285 | ||
286 | if (dev == NULL) | |
287 | return -1; | |
288 | ||
289 | if ((retval = classdb_open()) != 0) | |
290 | return -1; | |
291 | ||
292 | memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2)); | |
293 | strcpy(keystr, dev->class_name); | |
294 | strcat(keystr, UDEVDB_DEL); | |
295 | strcat(keystr, dev->class_dev_name); | |
296 | ||
297 | key.dptr = (void *)keystr; | |
298 | key.dsize = strlen(keystr) + 1; | |
299 | ||
300 | strcpy(rec.name, dev->name); | |
301 | ||
302 | data.dptr = (void *) &rec; | |
303 | data.dsize = sizeof(rec); | |
304 | ||
305 | retval = tdb_store(classdb, key, data, TDB_REPLACE); | |
306 | ||
307 | classdb_close(); | |
308 | return retval; | |
309 | } | |
310 | ||
311 | /** | |
312 | * namedb_store | |
313 | */ | |
314 | static int namedb_store(const struct udevice *dev) | |
315 | { | |
316 | TDB_DATA key, data; | |
317 | char keystr[NAME_SIZE]; | |
318 | struct namedb_record rec; | |
319 | int retval = 0; | |
320 | ||
321 | if (dev == NULL) | |
322 | return -1; | |
323 | ||
324 | if ((retval = namedb_open()) != 0) | |
325 | return -1; | |
326 | ||
327 | memset(keystr, 0, NAME_SIZE); | |
328 | strcpy(keystr, dev->name); | |
329 | ||
330 | key.dptr = (void *)keystr; | |
331 | key.dsize = strlen(keystr) + 1; | |
332 | ||
333 | strcpy(rec.sysfs_path, dev->sysfs_path); | |
334 | strcpy(rec.bus, dev->bus_name); | |
335 | strcpy(rec.id, dev->bus_id); | |
336 | strcpy(rec.class_dev_name, dev->class_dev_name); | |
337 | strcpy(rec.class_name, dev->class_name); | |
338 | strcpy(rec.driver, dev->driver); | |
339 | rec.type = dev->type; | |
340 | rec.major = dev->major; | |
341 | rec.minor = dev->minor; | |
342 | rec.mode = dev->mode; | |
343 | ||
344 | data.dptr = (void *) &rec; | |
345 | data.dsize = sizeof(rec); | |
346 | ||
347 | retval = tdb_store(namedb, key, data, TDB_REPLACE); | |
348 | ||
349 | namedb_close(); | |
350 | return retval; | |
351 | } | |
352 | ||
353 | /** | |
354 | * busdb_delete | |
355 | */ | |
356 | static int busdb_delete(const char *bus, const char *id) | |
357 | { | |
358 | TDB_DATA key; | |
359 | char keystr[BUS_SIZE+ID_SIZE+2]; | |
360 | int retval = 0; | |
361 | ||
362 | if (bus == NULL || id == NULL) | |
363 | return -1; | |
364 | if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE) | |
365 | return -1; | |
366 | ||
367 | if ((busdb_open()) != 0) | |
368 | return -1; | |
369 | ||
370 | memset(keystr, 0, (BUS_SIZE+ID_SIZE+2)); | |
371 | strcpy(keystr, bus); | |
372 | strcat(keystr, UDEVDB_DEL); | |
373 | strcat(keystr, id); | |
374 | ||
375 | key.dptr = (void *)keystr; | |
376 | key.dsize = strlen(keystr) + 1; | |
377 | ||
378 | retval = tdb_delete(busdb, key); | |
379 | busdb_close(); | |
380 | ||
381 | return retval; | |
382 | } | |
383 | ||
384 | /** | |
385 | * classdb_delete | |
386 | */ | |
387 | static int classdb_delete(const char *cls, const char *cls_dev) | |
388 | { | |
389 | TDB_DATA key; | |
390 | char keystr[NAME_SIZE+NAME_SIZE+2]; | |
391 | int retval = 0; | |
392 | ||
393 | if (cls == NULL || cls_dev == NULL) | |
394 | return -1; | |
395 | if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE) | |
396 | return -1; | |
397 | ||
398 | if ((classdb_open()) != 0) | |
399 | return -1; | |
400 | ||
401 | memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2)); | |
402 | strcpy(keystr, cls); | |
403 | strcat(keystr, UDEVDB_DEL); | |
404 | strcat(keystr, cls_dev); | |
405 | ||
406 | key.dptr = (void *)keystr; | |
407 | key.dsize = strlen(keystr) + 1; | |
408 | ||
409 | retval = tdb_delete(classdb, key); | |
410 | classdb_close(); | |
411 | ||
412 | return retval; | |
413 | } | |
414 | ||
415 | /** | |
416 | * namedb_delete | |
417 | */ | |
418 | static int namedb_delete(const char *name) | |
419 | { | |
420 | TDB_DATA key; | |
421 | char keystr[NAME_SIZE]; | |
422 | int retval = 0; | |
423 | ||
424 | if (name == NULL) | |
425 | return -1; | |
426 | if (strlen(name) >= NAME_SIZE) | |
427 | return -1; | |
428 | ||
429 | if ((namedb_open()) != 0) | |
430 | return -1; | |
431 | ||
432 | memset(keystr, 0, NAME_SIZE); | |
433 | strcpy(keystr, name); | |
434 | ||
435 | key.dptr = (void *)keystr; | |
436 | key.dsize = strlen(keystr) + 1; | |
437 | ||
438 | retval = tdb_delete(namedb, key); | |
439 | namedb_close(); | |
440 | ||
441 | return retval; | |
442 | } | |
443 | ||
444 | /** | |
445 | * namedb_exists | |
446 | */ | |
447 | static int namedb_exists(const char *name) | |
448 | { | |
449 | TDB_DATA key; | |
450 | char keystr[NAME_SIZE]; | |
451 | int retval = 0; | |
452 | ||
453 | if (name == NULL) | |
454 | return retval; | |
455 | if (strlen(name) >= NAME_SIZE) | |
456 | return retval; | |
457 | ||
458 | if ((namedb_open()) != 0) | |
459 | return retval; | |
460 | ||
461 | memset(keystr, 0, NAME_SIZE); | |
462 | strcpy(keystr, name); | |
463 | ||
464 | key.dptr = (void *)keystr; | |
465 | key.dsize = strlen(keystr) + 1; | |
466 | ||
467 | retval = tdb_exists(namedb, key); | |
468 | namedb_close(); | |
469 | ||
470 | return retval; | |
471 | } | |
472 | ||
473 | /** | |
474 | * udevdb_delete_udevice | |
475 | */ | |
476 | int udevdb_delete_udevice(const char *name) | |
477 | { | |
478 | struct namedb_record *nrec = NULL; | |
479 | ||
480 | if (name == NULL) | |
481 | return -1; | |
482 | ||
483 | nrec = namedb_fetch(name); | |
484 | if (nrec == NULL) | |
485 | return -1; | |
486 | ||
487 | busdb_delete(nrec->bus, nrec->id); | |
488 | classdb_delete(nrec->class_name, nrec->class_dev_name); | |
489 | namedb_delete(name); | |
490 | free(nrec); | |
491 | ||
492 | return 0; | |
493 | } | |
494 | ||
495 | /** | |
496 | * udevdb_add_udevice: adds udevice to database | |
497 | */ | |
498 | int udevdb_add_udevice(const struct udevice *dev) | |
499 | { | |
500 | if (dev == NULL) | |
501 | return -1; | |
502 | ||
503 | if ((busdb_store(dev)) != 0) | |
504 | return -1; | |
505 | if ((classdb_store(dev)) != 0) | |
506 | return -1; | |
507 | if ((namedb_store(dev)) != 0) | |
508 | return -1; | |
509 | ||
510 | return 0; | |
511 | } | |
512 | ||
513 | /** | |
514 | * udevdb_get_device: grab's device by name | |
515 | */ | |
516 | struct udevice *udevdb_get_udevice(const char *name) | |
517 | { | |
518 | struct namedb_record *nrec = NULL; | |
519 | struct udevice *dev = NULL; | |
520 | ||
521 | if (name == NULL) | |
522 | return NULL; | |
523 | ||
524 | nrec = namedb_fetch(name); | |
525 | if (nrec == NULL) | |
526 | return NULL; | |
527 | ||
528 | dev = (struct udevice *)malloc(sizeof(struct udevice)); | |
529 | if (dev == NULL) { | |
530 | free(nrec); | |
531 | return NULL; | |
532 | } | |
533 | ||
534 | strcpy(dev->name, name); | |
535 | strcpy(dev->sysfs_path, nrec->sysfs_path); | |
536 | strcpy(dev->class_dev_name, nrec->class_dev_name); | |
537 | strcpy(dev->class_name, nrec->class_name); | |
538 | strcpy(dev->bus_name, nrec->bus); | |
539 | strcpy(dev->bus_id, nrec->id); | |
540 | dev->type = nrec->type; | |
541 | dev->major = nrec->major; | |
542 | dev->minor = nrec->minor; | |
543 | dev->mode = nrec->mode; | |
544 | ||
545 | free(nrec); | |
546 | ||
547 | return dev; | |
548 | } | |
549 | ||
550 | /** | |
551 | * udevdb_get_device_by_bus | |
552 | */ | |
553 | struct udevice *udevdb_get_udevice_by_bus(const char *bus, const char *id) | |
554 | { | |
555 | struct busdb_record *brec = NULL; | |
556 | struct udevice *dev = NULL; | |
557 | ||
558 | if (bus == NULL || id == NULL) | |
559 | return NULL; | |
560 | ||
561 | brec = busdb_fetch(bus, id); | |
562 | if (brec == NULL) | |
563 | return NULL; | |
564 | ||
565 | dev = udevdb_get_udevice(brec->name); | |
566 | free(brec); | |
567 | ||
568 | return dev; | |
569 | } | |
570 | ||
571 | /** | |
572 | * udevdb_get_udevice_by_class | |
573 | */ | |
574 | struct udevice *udevdb_get_udevice_by_class(const char *cls, | |
575 | const char *cls_dev) | |
576 | { | |
577 | struct classdb_record *crec = NULL; | |
578 | struct udevice *dev = NULL; | |
579 | ||
580 | if (cls == NULL || cls_dev == NULL) | |
581 | return NULL; | |
582 | ||
583 | crec = classdb_fetch(cls, cls_dev); | |
584 | if (crec == NULL) | |
585 | return NULL; | |
586 | ||
587 | dev = udevdb_get_udevice(crec->name); | |
588 | free(crec); | |
589 | ||
590 | return dev; | |
591 | } |