]> git.ipfire.org Git - thirdparty/systemd.git/blame - udevdb.c
[PATCH] add BUS= bug to TODO list so it will not get forgotten.
[thirdparty/systemd.git] / udevdb.c
CommitLineData
8dfc8dbe
GKH
1/*
2 * udevdb.c
3 *
4 * Userspace devfs
5 *
6 * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
7 * Copyright (C) 2003 IBM Corp.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
8e41d35d
DS
24/*
25 * udev database library
26 */
27#include <stdlib.h>
28#include <stdio.h>
29#include <fcntl.h>
30#include <string.h>
31#include <sys/stat.h>
32#include <errno.h>
a2822451 33#include <signal.h>
8e41d35d 34
6739707d
GKH
35#include "udev_version.h"
36#include "udev.h"
37#include "namedev.h"
8e41d35d 38#include "udevdb.h"
a2822451 39#include "tdb/tdb.h"
ca999860 40#include "libsysfs/libsysfs.h"
8e41d35d 41
dbfc520c 42static TDB_CONTEXT *udevdb;
8e41d35d
DS
43
44/**
45 * busdb_record - bus and id are keys to look up name of device
46 */
47struct busdb_record {
48 char name[NAME_SIZE];
49};
50
51/**
52 * classdb_record - class name and class device name used as keys to find
53 * device name.
54 */
55struct classdb_record {
56 char name[NAME_SIZE];
57};
58
ca999860
GKH
59struct sysfsdb_record {
60 char name[PATH_SIZE];
61};
62
8e41d35d
DS
63/**
64 * namedb_record - device name is key, remaining udevice info stored here.
65 */
66struct namedb_record {
ca999860 67 char sysfs_dev_path[PATH_SIZE];
8e41d35d
DS
68 char class_dev_name[NAME_SIZE];
69 char class_name[NAME_SIZE];
70 char bus[BUS_SIZE];
71 char id[ID_SIZE];
72 char driver[NAME_SIZE];
73 char type;
74 int major;
75 int minor;
c2405f50 76 mode_t mode;
8e41d35d
DS
77};
78
79/**
dbfc520c 80 * udevdb_close: close udev database
8e41d35d 81 */
dbfc520c 82static void udevdb_close(void)
8e41d35d 83{
dbfc520c
DS
84 if (udevdb != NULL) {
85 tdb_close(udevdb);
86 udevdb = NULL;
8e41d35d
DS
87 }
88}
89
90/**
dbfc520c
DS
91 * udevdb_open: opens udev's database
92 * @method: database can either be in memory - UDEVDB_INTERNAL - or
93 * written to a file with UDEVDB_DEFAULT.
8e41d35d 94 */
dbfc520c 95static int udevdb_open(int method)
8e41d35d 96{
6739707d
GKH
97 udevdb = tdb_open(UDEV_CONFIG_DIR UDEV_DB, 0, method, O_RDWR | O_CREAT, 0644);
98 if (udevdb == NULL) {
99 if (method == UDEVDB_INTERNAL)
100 dbg("Unable to initialize in-memory database");
101 else
102 dbg("Unable to initialize database at %s", UDEV_CONFIG_DIR UDEV_DB);
103 return -EINVAL;
104 }
8e41d35d
DS
105 return 0;
106}
107
108/**
109 * busdb_fetch
110 */
111static struct busdb_record *busdb_fetch(const char *bus, const char *id)
112{
113 TDB_DATA key, data;
114 char keystr[BUS_SIZE+ID_SIZE+2];
115 struct busdb_record *rec = NULL;
116
117 if (bus == NULL || id == NULL)
118 return NULL;
119 if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE)
120 return NULL;
121
8e41d35d
DS
122 memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
123 strcpy(keystr, bus);
124 strcat(keystr, UDEVDB_DEL);
125 strcat(keystr, id);
126
127 key.dptr = (void *)keystr;
128 key.dsize = strlen(keystr) + 1;
129
dbfc520c 130 data = tdb_fetch(udevdb, key);
8e41d35d
DS
131 if (data.dptr == NULL || data.dsize == 0)
132 return NULL;
d7e954a4 133
8e41d35d
DS
134 rec = (struct busdb_record *)malloc(sizeof(struct busdb_record));
135 if (rec == NULL) {
136 free(data.dptr);
137 return NULL;
138 }
d7e954a4 139
8e41d35d
DS
140 memcpy(rec, data.dptr, sizeof(struct busdb_record));
141 free(data.dptr);
142
143 return rec;
144}
145
146/**
147 * classdb_fetch
148 */
149static struct classdb_record *classdb_fetch(const char *cls,
150 const char *cls_dev)
151{
152 TDB_DATA key, data;
153 char keystr[NAME_SIZE+NAME_SIZE+2];
154 struct classdb_record *rec = NULL;
155
156 if (cls == NULL || cls_dev == NULL)
157 return NULL;
158 if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE)
159 return NULL;
160
8e41d35d
DS
161 memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
162 strcpy(keystr, cls);
163 strcat(keystr, UDEVDB_DEL);
164 strcat(keystr, cls_dev);
165
166 key.dptr = (void *)keystr;
167 key.dsize = strlen(keystr) + 1;
168
dbfc520c 169 data = tdb_fetch(udevdb, key);
8e41d35d
DS
170 if (data.dptr == NULL || data.dsize == 0)
171 return NULL;
172
173 rec = (struct classdb_record *)malloc(sizeof(struct classdb_record));
174 if (rec == NULL) {
175 free(data.dptr);
176 return NULL;
177 }
178
179 memcpy(rec, data.dptr, sizeof(struct classdb_record));
180 free(data.dptr);
181
182 return rec;
183}
184
ca999860
GKH
185static struct sysfsdb_record *sysfsdb_fetch(const char *path)
186{
187 TDB_DATA key, data;
188 char keystr[PATH_SIZE+2];
189 struct sysfsdb_record *rec = NULL;
190
191 if (strlen(path) >= PATH_SIZE)
192 return NULL;
193
194 memset(keystr, 0, sizeof(keystr));
195 strcpy(keystr, path);
196
197 dbg("keystr = %s", keystr);
198
199 key.dptr = (void *)keystr;
200 key.dsize = strlen(keystr) + 1;
201
202 data = tdb_fetch(udevdb, key);
203 if (data.dptr == NULL || data.dsize == 0) {
204 dbg("tdb_fetch did not work :(");
205 return NULL;
206 }
207
208 rec = (struct sysfsdb_record *)malloc(sizeof(struct sysfsdb_record));
209 if (rec == NULL) {
210 free(data.dptr);
211 return NULL;
212 }
213
214 memcpy(rec, data.dptr, sizeof(struct sysfsdb_record));
215 free(data.dptr);
216
217 return rec;
218}
219
8e41d35d
DS
220/**
221 * namedb_fetch
222 */
223static struct namedb_record *namedb_fetch(const char *name)
224{
225 TDB_DATA key, data;
226 char nm_keystr[NAME_SIZE];
227 struct namedb_record *nrec = NULL;
228
229 if (name == NULL)
230 return NULL;
231 if (strlen(name) >= NAME_SIZE)
232 return NULL;
233
8e41d35d
DS
234 memset(nm_keystr, 0, NAME_SIZE);
235 strcpy(nm_keystr, name);
236
237 key.dptr = (void *)nm_keystr;
238 key.dsize = strlen(nm_keystr) + 1;
239
dbfc520c 240 data = tdb_fetch(udevdb, key);
8e41d35d
DS
241 if (data.dptr == NULL || data.dsize == 0)
242 return NULL;
243
244 nrec = (struct namedb_record *)malloc(sizeof(struct namedb_record));
245 if (nrec == NULL) {
246 free(data.dptr);
247 return NULL;
248 }
249
250 memcpy(nrec, data.dptr, sizeof(struct namedb_record));
251 free(data.dptr);
252
253 return nrec;
254}
255
256/**
257 * busdb_store
258 */
259static int busdb_store(const struct udevice *dev)
260{
261 TDB_DATA key, data;
262 char keystr[BUS_SIZE+ID_SIZE+2];
263 struct busdb_record rec;
264 int retval = 0;
265
266 if (dev == NULL)
267 return -1;
268
8e41d35d
DS
269 memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
270 strcpy(keystr, dev->bus_name);
271 strcat(keystr, UDEVDB_DEL);
272 strcat(keystr, dev->bus_id);
273
274 key.dptr = (void *)keystr;
275 key.dsize = strlen(keystr) + 1;
276
277 strcpy(rec.name, dev->name);
278
279 data.dptr = (void *) &rec;
280 data.dsize = sizeof(rec);
281
dbfc520c 282 retval = tdb_store(udevdb, key, data, TDB_REPLACE);
8e41d35d
DS
283 return retval;
284}
285
286/**
287 * classdb_store
288 */
289static int classdb_store(const struct udevice *dev)
290{
291 TDB_DATA key, data;
292 char keystr[NAME_SIZE+NAME_SIZE+2];
293 struct classdb_record rec;
294 int retval = 0;
295
296 if (dev == NULL)
297 return -1;
298
8e41d35d
DS
299 memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
300 strcpy(keystr, dev->class_name);
301 strcat(keystr, UDEVDB_DEL);
302 strcat(keystr, dev->class_dev_name);
303
304 key.dptr = (void *)keystr;
305 key.dsize = strlen(keystr) + 1;
306
307 strcpy(rec.name, dev->name);
308
309 data.dptr = (void *) &rec;
310 data.dsize = sizeof(rec);
311
dbfc520c 312 retval = tdb_store(udevdb, key, data, TDB_REPLACE);
8e41d35d
DS
313 return retval;
314}
315
ca999860
GKH
316static int sysfs_store(const char *path, const struct udevice *dev)
317{
318 TDB_DATA key, data;
319 char keystr[PATH_SIZE+2];
320 struct sysfsdb_record rec;
321 int retval = 0;
322
323 if (dev == NULL)
324 return -ENODEV;
325
326 memset(keystr, 0, sizeof(keystr));
327 strcpy(keystr, path);
328 dbg("keystr = %s", keystr);
329
330 key.dptr = (void *)keystr;
331 key.dsize = strlen(keystr) + 1;
332
333 strcpy(rec.name, dev->name);
334
335 data.dptr = (void *) &rec;
336 data.dsize = sizeof(rec);
337
338 retval = tdb_store(udevdb, key, data, TDB_REPLACE);
339 return retval;
340}
341
8e41d35d
DS
342/**
343 * namedb_store
344 */
345static int namedb_store(const struct udevice *dev)
346{
347 TDB_DATA key, data;
348 char keystr[NAME_SIZE];
349 struct namedb_record rec;
350 int retval = 0;
351
352 if (dev == NULL)
353 return -1;
354
8e41d35d
DS
355 memset(keystr, 0, NAME_SIZE);
356 strcpy(keystr, dev->name);
357
358 key.dptr = (void *)keystr;
359 key.dsize = strlen(keystr) + 1;
360
ca999860 361 strcpy(rec.sysfs_dev_path, dev->sysfs_dev_path);
8e41d35d
DS
362 strcpy(rec.bus, dev->bus_name);
363 strcpy(rec.id, dev->bus_id);
364 strcpy(rec.class_dev_name, dev->class_dev_name);
365 strcpy(rec.class_name, dev->class_name);
366 strcpy(rec.driver, dev->driver);
367 rec.type = dev->type;
368 rec.major = dev->major;
369 rec.minor = dev->minor;
370 rec.mode = dev->mode;
371
372 data.dptr = (void *) &rec;
373 data.dsize = sizeof(rec);
374
dbfc520c 375 retval = tdb_store(udevdb, key, data, TDB_REPLACE);
8e41d35d
DS
376 return retval;
377}
378
379/**
380 * busdb_delete
381 */
382static int busdb_delete(const char *bus, const char *id)
383{
384 TDB_DATA key;
385 char keystr[BUS_SIZE+ID_SIZE+2];
386 int retval = 0;
387
388 if (bus == NULL || id == NULL)
389 return -1;
390 if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE)
391 return -1;
392
8e41d35d
DS
393 memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
394 strcpy(keystr, bus);
395 strcat(keystr, UDEVDB_DEL);
396 strcat(keystr, id);
397
398 key.dptr = (void *)keystr;
399 key.dsize = strlen(keystr) + 1;
400
dbfc520c 401 retval = tdb_delete(udevdb, key);
8e41d35d
DS
402 return retval;
403}
404
405/**
406 * classdb_delete
407 */
408static int classdb_delete(const char *cls, const char *cls_dev)
409{
410 TDB_DATA key;
411 char keystr[NAME_SIZE+NAME_SIZE+2];
412 int retval = 0;
413
414 if (cls == NULL || cls_dev == NULL)
415 return -1;
416 if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE)
417 return -1;
418
8e41d35d
DS
419 memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
420 strcpy(keystr, cls);
421 strcat(keystr, UDEVDB_DEL);
422 strcat(keystr, cls_dev);
423
424 key.dptr = (void *)keystr;
425 key.dsize = strlen(keystr) + 1;
426
dbfc520c 427 retval = tdb_delete(udevdb, key);
8e41d35d
DS
428 return retval;
429}
430
431/**
432 * namedb_delete
433 */
434static int namedb_delete(const char *name)
435{
436 TDB_DATA key;
437 char keystr[NAME_SIZE];
438 int retval = 0;
439
440 if (name == NULL)
441 return -1;
442 if (strlen(name) >= NAME_SIZE)
443 return -1;
444
8e41d35d
DS
445 memset(keystr, 0, NAME_SIZE);
446 strcpy(keystr, name);
447
448 key.dptr = (void *)keystr;
449 key.dsize = strlen(keystr) + 1;
450
dbfc520c 451 retval = tdb_delete(udevdb, key);
8e41d35d
DS
452 return retval;
453}
454
455/**
456 * udevdb_delete_udevice
457 */
458int udevdb_delete_udevice(const char *name)
459{
460 struct namedb_record *nrec = NULL;
461
462 if (name == NULL)
463 return -1;
464
465 nrec = namedb_fetch(name);
466 if (nrec == NULL)
467 return -1;
468
469 busdb_delete(nrec->bus, nrec->id);
470 classdb_delete(nrec->class_name, nrec->class_dev_name);
471 namedb_delete(name);
472 free(nrec);
473
474 return 0;
475}
476
477/**
ca999860 478 * udevdb_add_device: adds class device to database
8e41d35d 479 */
ca999860 480int udevdb_add_device(const char *device, const struct sysfs_class_device *class_dev, const char *name, char type, int major, int minor, int mode)
8e41d35d 481{
ca999860
GKH
482 struct udevice dbdev;
483
484 if (class_dev == NULL)
485 return -ENODEV;
8e41d35d 486
ca999860
GKH
487 memset(&dbdev, 0, sizeof(dbdev));
488 strncpy(dbdev.name, name, NAME_SIZE);
489 if (class_dev->sysdevice) {
490 strncpy(dbdev.sysfs_dev_path, class_dev->sysdevice->directory->path, PATH_SIZE);
491 strncpy(dbdev.bus_id, class_dev->sysdevice->bus_id, ID_SIZE);
492 }
493 strncpy(dbdev.class_dev_name, class_dev->name, NAME_SIZE);
494// if ((sysfs_get_name_from_path(subsystem, dbdev.class_name, NAME_SIZE)) != 0)
495// strcpy(dbdev.class_name, "unknown");
496 strcpy(dbdev.bus_name, "unknown");
497 if (class_dev->driver != NULL)
498 strncpy(dbdev.driver, class_dev->driver->name, NAME_SIZE);
499 else
500 strcpy(dbdev.driver, "unknown");
501 dbdev.type = type;
502 dbdev.major = major;
503 dbdev.minor = minor;
504 dbdev.mode = mode;
505
506 if ((busdb_store(&dbdev)) != 0)
8e41d35d 507 return -1;
ca999860 508 if ((classdb_store(&dbdev)) != 0)
8e41d35d 509 return -1;
ca999860
GKH
510 if ((sysfs_store(device, &dbdev)) != 0)
511 return -1;
512 if ((namedb_store(&dbdev)) != 0)
8e41d35d
DS
513 return -1;
514
515 return 0;
516}
517
518/**
519 * udevdb_get_device: grab's device by name
520 */
521struct udevice *udevdb_get_udevice(const char *name)
522{
523 struct namedb_record *nrec = NULL;
524 struct udevice *dev = NULL;
525
526 if (name == NULL)
527 return NULL;
528
529 nrec = namedb_fetch(name);
530 if (nrec == NULL)
531 return NULL;
532
533 dev = (struct udevice *)malloc(sizeof(struct udevice));
534 if (dev == NULL) {
535 free(nrec);
536 return NULL;
537 }
538
539 strcpy(dev->name, name);
ca999860 540 strcpy(dev->sysfs_dev_path, nrec->sysfs_dev_path);
8e41d35d
DS
541 strcpy(dev->class_dev_name, nrec->class_dev_name);
542 strcpy(dev->class_name, nrec->class_name);
543 strcpy(dev->bus_name, nrec->bus);
544 strcpy(dev->bus_id, nrec->id);
545 dev->type = nrec->type;
546 dev->major = nrec->major;
547 dev->minor = nrec->minor;
548 dev->mode = nrec->mode;
549
550 free(nrec);
551
552 return dev;
553}
554
555/**
556 * udevdb_get_device_by_bus
557 */
558struct udevice *udevdb_get_udevice_by_bus(const char *bus, const char *id)
559{
560 struct busdb_record *brec = NULL;
561 struct udevice *dev = NULL;
562
563 if (bus == NULL || id == NULL)
564 return NULL;
565
566 brec = busdb_fetch(bus, id);
567 if (brec == NULL)
568 return NULL;
569
570 dev = udevdb_get_udevice(brec->name);
571 free(brec);
572
573 return dev;
574}
575
576/**
577 * udevdb_get_udevice_by_class
578 */
579struct udevice *udevdb_get_udevice_by_class(const char *cls,
580 const char *cls_dev)
581{
582 struct classdb_record *crec = NULL;
583 struct udevice *dev = NULL;
584
585 if (cls == NULL || cls_dev == NULL)
586 return NULL;
587
588 crec = classdb_fetch(cls, cls_dev);
589 if (crec == NULL)
590 return NULL;
591
592 dev = udevdb_get_udevice(crec->name);
593 free(crec);
594
595 return dev;
596}
dbfc520c 597
ca999860
GKH
598
599char *udevdb_get_udevice_by_sysfs(const char *path)
600{
601 struct sysfsdb_record *crec = NULL;
602// struct udevice *dev = NULL;
603
604 if (path == NULL)
605 return NULL;
606
607 crec = sysfsdb_fetch(path);
608 if (crec == NULL)
609 return NULL;
610
611 // FIXME leak!!!
612 return crec->name;
613// dev = udevdb_get_udevice(crec->name);
614// free(crec);
615//
616// return dev;
617}
618
dbfc520c
DS
619/**
620 * udevdb_exit: closes database
621 */
622void udevdb_exit(void)
623{
624 udevdb_close();
625}
626
627/**
628 * udevdb_init: initializes database
629 */
630int udevdb_init(int init_flag)
631{
632 if (init_flag != UDEVDB_DEFAULT && init_flag != UDEVDB_INTERNAL)
633 return -1;
634
635 return udevdb_open(init_flag);
636}