chiark / gitweb /
c2e90be32f47a71eceddc820c041e17c734ff4b6
[elogind.git] / udevdb.c
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 #include <signal.h>
11
12 #include "udevdb.h"
13 #include "tdb/tdb.h"
14
15 static TDB_CONTEXT *udevdb;
16
17 /**
18  * busdb_record - bus and id are keys to look up name of device
19  */
20 struct busdb_record {
21         char name[NAME_SIZE];
22 };
23
24 /**
25  * classdb_record - class name and class device name used as keys to find
26  *      device name.
27  */
28 struct classdb_record {
29         char name[NAME_SIZE];
30 };
31
32 /**
33  * namedb_record - device name is key, remaining udevice info stored here.
34  */
35 struct namedb_record {
36         char sysfs_path[PATH_SIZE];
37         char class_dev_name[NAME_SIZE];
38         char class_name[NAME_SIZE];
39         char bus[BUS_SIZE];
40         char id[ID_SIZE];
41         char driver[NAME_SIZE];
42         char type;
43         int major;
44         int minor;
45         int mode;
46 };
47
48 /**
49  * udevdb_close: close udev database
50  */
51 static void udevdb_close(void)
52 {
53         if (udevdb != NULL) {
54                 tdb_close(udevdb);
55                 udevdb = NULL;
56         }
57 }
58
59 /**
60  * udevdb_open: opens udev's database
61  * @method: database can either be in memory - UDEVDB_INTERNAL - or
62  *      written to a file with UDEVDB_DEFAULT.
63  */
64 static int udevdb_open(int method)
65 {
66         udevdb = tdb_open(UDEVDB, 0, method, O_RDWR | O_CREAT, 0644);
67         if (udevdb == NULL)
68                 return -1;
69         return 0;
70 }
71
72 /**
73  * busdb_fetch
74  */
75 static struct busdb_record *busdb_fetch(const char *bus, const char *id)
76 {
77         TDB_DATA key, data;
78         char keystr[BUS_SIZE+ID_SIZE+2]; 
79         struct busdb_record *rec = NULL;
80
81         if (bus == NULL || id == NULL)
82                 return NULL; 
83         if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE)
84                 return NULL;
85
86         memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
87         strcpy(keystr, bus);
88         strcat(keystr, UDEVDB_DEL);
89         strcat(keystr, id);
90
91         key.dptr = (void *)keystr;
92         key.dsize = strlen(keystr) + 1;
93
94         data = tdb_fetch(udevdb, key);
95         if (data.dptr == NULL || data.dsize == 0)
96                 return NULL;
97         
98         rec = (struct busdb_record *)malloc(sizeof(struct busdb_record));
99         if (rec == NULL) {
100                 free(data.dptr);
101                 return NULL;
102         }
103         
104         memcpy(rec, data.dptr, sizeof(struct busdb_record));
105         free(data.dptr);
106
107         return rec;
108 }
109
110 /**
111  * classdb_fetch
112  */
113 static struct classdb_record *classdb_fetch(const char *cls, 
114                                                 const char *cls_dev)
115 {
116         TDB_DATA key, data;
117         char keystr[NAME_SIZE+NAME_SIZE+2]; 
118         struct classdb_record *rec = NULL;
119
120         if (cls == NULL || cls_dev == NULL)
121                 return NULL; 
122         if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE)
123                 return NULL;
124
125         memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
126         strcpy(keystr, cls);
127         strcat(keystr, UDEVDB_DEL);
128         strcat(keystr, cls_dev);
129
130         key.dptr = (void *)keystr;
131         key.dsize = strlen(keystr) + 1;
132
133         data = tdb_fetch(udevdb, key);
134         if (data.dptr == NULL || data.dsize == 0)
135                 return NULL;
136         
137         rec = (struct classdb_record *)malloc(sizeof(struct classdb_record));
138         if (rec == NULL) {
139                 free(data.dptr);
140                 return NULL;
141         }
142         
143         memcpy(rec, data.dptr, sizeof(struct classdb_record));
144         free(data.dptr);
145
146         return rec;
147 }
148
149 /**
150  * namedb_fetch
151  */
152 static struct namedb_record *namedb_fetch(const char *name)
153 {
154         TDB_DATA key, data;
155         char nm_keystr[NAME_SIZE]; 
156         struct namedb_record *nrec = NULL;
157
158         if (name == NULL)
159                 return NULL; 
160         if (strlen(name) >= NAME_SIZE)
161                 return NULL;
162
163         memset(nm_keystr, 0, NAME_SIZE);
164         strcpy(nm_keystr, name);
165
166         key.dptr = (void *)nm_keystr;
167         key.dsize = strlen(nm_keystr) + 1;
168
169         data = tdb_fetch(udevdb, key);
170         if (data.dptr == NULL || data.dsize == 0)
171                 return NULL;
172
173         nrec = (struct namedb_record *)malloc(sizeof(struct namedb_record));
174         if (nrec == NULL) {
175                 free(data.dptr);
176                 return NULL;
177         }
178         
179         memcpy(nrec, data.dptr, sizeof(struct namedb_record));
180         free(data.dptr);
181
182         return nrec;
183 }
184
185 /**
186  * busdb_store
187  */
188 static int busdb_store(const struct udevice *dev)
189 {
190         TDB_DATA key, data;
191         char keystr[BUS_SIZE+ID_SIZE+2];
192         struct busdb_record rec;
193         int retval = 0;
194
195         if (dev == NULL)
196                 return -1;
197
198         memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
199         strcpy(keystr, dev->bus_name);
200         strcat(keystr, UDEVDB_DEL);
201         strcat(keystr, dev->bus_id);
202
203         key.dptr = (void *)keystr;
204         key.dsize = strlen(keystr) + 1;
205         
206         strcpy(rec.name, dev->name);
207
208         data.dptr = (void *) &rec;
209         data.dsize = sizeof(rec);
210         
211         retval = tdb_store(udevdb, key, data, TDB_REPLACE); 
212         return retval;
213 }
214
215 /**
216  * classdb_store
217  */
218 static int classdb_store(const struct udevice *dev)
219 {
220         TDB_DATA key, data;
221         char keystr[NAME_SIZE+NAME_SIZE+2];
222         struct classdb_record rec;
223         int retval = 0;
224
225         if (dev == NULL)
226                 return -1;
227
228         memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
229         strcpy(keystr, dev->class_name);
230         strcat(keystr, UDEVDB_DEL);
231         strcat(keystr, dev->class_dev_name);
232
233         key.dptr = (void *)keystr;
234         key.dsize = strlen(keystr) + 1;
235         
236         strcpy(rec.name, dev->name);
237
238         data.dptr = (void *) &rec;
239         data.dsize = sizeof(rec);
240         
241         retval = tdb_store(udevdb, key, data, TDB_REPLACE); 
242         return retval;
243 }
244
245 /**
246  * namedb_store
247  */
248 static int namedb_store(const struct udevice *dev)
249 {
250         TDB_DATA key, data;
251         char keystr[NAME_SIZE];
252         struct namedb_record rec;
253         int retval = 0;
254
255         if (dev == NULL)
256                 return -1;
257
258         memset(keystr, 0, NAME_SIZE);
259         strcpy(keystr, dev->name);
260
261         key.dptr = (void *)keystr;
262         key.dsize = strlen(keystr) + 1;
263         
264         strcpy(rec.sysfs_path, dev->sysfs_path);
265         strcpy(rec.bus, dev->bus_name);
266         strcpy(rec.id, dev->bus_id);
267         strcpy(rec.class_dev_name, dev->class_dev_name);
268         strcpy(rec.class_name, dev->class_name);
269         strcpy(rec.driver, dev->driver);
270         rec.type = dev->type;
271         rec.major = dev->major;
272         rec.minor = dev->minor;
273         rec.mode = dev->mode;
274
275         data.dptr = (void *) &rec;
276         data.dsize = sizeof(rec);
277         
278         retval = tdb_store(udevdb, key, data, TDB_REPLACE); 
279         return retval;
280 }
281
282 /**
283  * busdb_delete
284  */
285 static int busdb_delete(const char *bus, const char *id)
286 {
287         TDB_DATA key;
288         char keystr[BUS_SIZE+ID_SIZE+2]; 
289         int retval = 0;
290
291         if (bus == NULL || id == NULL)
292                 return -1; 
293         if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE)
294                 return -1;
295
296         memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
297         strcpy(keystr, bus);
298         strcat(keystr, UDEVDB_DEL);
299         strcat(keystr, id);
300
301         key.dptr = (void *)keystr;
302         key.dsize = strlen(keystr) + 1;
303
304         retval = tdb_delete(udevdb, key);
305         return retval;
306 }
307
308 /**
309  * classdb_delete
310  */
311 static int classdb_delete(const char *cls, const char *cls_dev)
312 {
313         TDB_DATA key;
314         char keystr[NAME_SIZE+NAME_SIZE+2]; 
315         int retval = 0;
316
317         if (cls == NULL || cls_dev == NULL)
318                 return -1; 
319         if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE)
320                 return -1;
321
322         memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
323         strcpy(keystr, cls);
324         strcat(keystr, UDEVDB_DEL);
325         strcat(keystr, cls_dev);
326
327         key.dptr = (void *)keystr;
328         key.dsize = strlen(keystr) + 1;
329
330         retval = tdb_delete(udevdb, key);
331         return retval;
332 }
333
334 /**
335  * namedb_delete
336  */
337 static int namedb_delete(const char *name)
338 {
339         TDB_DATA key;
340         char keystr[NAME_SIZE]; 
341         int retval = 0;
342
343         if (name == NULL)
344                 return -1; 
345         if (strlen(name) >= NAME_SIZE)
346                 return -1;
347
348         memset(keystr, 0, NAME_SIZE);
349         strcpy(keystr, name);
350
351         key.dptr = (void *)keystr;
352         key.dsize = strlen(keystr) + 1;
353
354         retval = tdb_delete(udevdb, key);
355         return retval;
356 }
357
358 /**
359  * udevdb_delete_udevice
360  */
361 int udevdb_delete_udevice(const char *name)
362 {
363         struct namedb_record *nrec = NULL;
364
365         if (name == NULL)
366                 return -1; 
367
368         nrec = namedb_fetch(name);
369         if (nrec == NULL)
370                 return -1;
371
372         busdb_delete(nrec->bus, nrec->id);
373         classdb_delete(nrec->class_name, nrec->class_dev_name);
374         namedb_delete(name);
375         free(nrec);
376
377         return 0;
378 }
379
380 /**
381  * udevdb_add_udevice: adds udevice to database
382  */
383 int udevdb_add_udevice(const struct udevice *dev)
384 {
385         if (dev == NULL) 
386                 return -1;
387
388         if ((busdb_store(dev)) != 0)
389                 return -1;
390         if ((classdb_store(dev)) != 0)
391                 return -1;
392         if ((namedb_store(dev)) != 0)
393                 return -1;
394
395         return 0;
396 }
397
398 /**
399  * udevdb_get_device: grab's device by name
400  */
401 struct udevice *udevdb_get_udevice(const char *name)
402 {
403         struct namedb_record *nrec = NULL;
404         struct udevice *dev = NULL;
405
406         if (name == NULL)
407                 return NULL; 
408
409         nrec = namedb_fetch(name);
410         if (nrec == NULL)
411                 return NULL;
412
413         dev = (struct udevice *)malloc(sizeof(struct udevice));
414         if (dev == NULL) {
415                 free(nrec);
416                 return NULL;
417         }
418
419         strcpy(dev->name, name);
420         strcpy(dev->sysfs_path, nrec->sysfs_path);
421         strcpy(dev->class_dev_name, nrec->class_dev_name);
422         strcpy(dev->class_name, nrec->class_name);
423         strcpy(dev->bus_name, nrec->bus);
424         strcpy(dev->bus_id, nrec->id);
425         dev->type = nrec->type;
426         dev->major = nrec->major;
427         dev->minor = nrec->minor;
428         dev->mode = nrec->mode;
429
430         free(nrec);
431
432         return dev;
433 }
434
435 /**
436  * udevdb_get_device_by_bus
437  */
438 struct udevice *udevdb_get_udevice_by_bus(const char *bus, const char *id)
439 {
440         struct busdb_record *brec = NULL;
441         struct udevice *dev = NULL;
442
443         if (bus == NULL || id == NULL)
444                 return NULL;
445
446         brec = busdb_fetch(bus, id);
447         if (brec == NULL)
448                 return NULL;
449
450         dev = udevdb_get_udevice(brec->name);
451         free(brec);
452
453         return dev;
454 }
455
456 /**
457  * udevdb_get_udevice_by_class
458  */
459 struct udevice *udevdb_get_udevice_by_class(const char *cls, 
460                                                 const char *cls_dev)
461 {
462         struct classdb_record *crec = NULL;
463         struct udevice *dev = NULL;
464
465         if (cls == NULL || cls_dev == NULL)
466                 return NULL;
467
468         crec = classdb_fetch(cls, cls_dev);
469         if (crec == NULL)
470                 return NULL;
471
472         dev = udevdb_get_udevice(crec->name);
473         free(crec);
474
475         return dev;
476 }
477
478 /**
479  * udevdb_exit: closes database
480  */
481 void udevdb_exit(void)
482 {
483         udevdb_close();
484 }
485
486 /**
487  * udevdb_init: initializes database
488  */
489 int udevdb_init(int init_flag)
490 {
491         if (init_flag != UDEVDB_DEFAULT && init_flag != UDEVDB_INTERNAL)
492                 return -1;
493
494         return udevdb_open(init_flag);
495 }