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