chiark / gitweb /
[PATCH] udevdb prototype
authordsteklof@us.ibm.com <dsteklof@us.ibm.com>
Wed, 6 Aug 2003 06:57:23 +0000 (23:57 -0700)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:01:40 +0000 (21:01 -0700)
Here's an "idea" of what I had in mind for udevdb. Let me preface the
code with a few remarks:

1) I was expecting to write this udevdb for udev to keep track of
devices. I was planning an external package that depends upon udev
to provide an external API to the udevdb database. The calls for the
interface would be read only access. Not sure how you want to do
packaging, if having a separate package is ok or having it included
in udev.

2) I created it as it is because udev isn't a daemon. So, the open
database call doesn't take any parameters. My plan was to create a
udevdb_init function that took arguments for initializing the db
to start, where you could specify in memory only or a file location.
This can all be filled in.

3) I hacked the Makefile to get it to work. Not sure how you'd want
that in the future.

4) This assumes TDB has been installed elsewhere, you would need to
edit your Makefile and point it to the header and library locations.
How do you want to do TDB in udev? Do you want to just reference it
and make udev dependent on that package being installed. Or should
we do what samba does and include a limited tdb version in udev?

5) Again, I hacked udev into your existing code. In the future, I'd
probably make a function around the filling out the udevice before
calling the store command. Didn't know if you wanted to change
your add device function to use struct udevice rather than having
everything separate.

6) Not sure what we should include in the udevice structure that's stored
by udev. I made a stab at a first shot - we can add and remove of course,
this was a first pass. I've come to realize - with you including libsysfs
in udev, the "external" interface that references udevdb could make
use of getting information from through libsysfs from sysfs and doesn't
need to be in udevdb.

7) I could write a namedevdb for namedev's device management if you
wanted.

namedev.h
udev-add.c
udev-remove.c
udevdb.c [new file with mode: 0644]
udevdb.h [new file with mode: 0644]

index 9d612df..d986a23 100644 (file)
--- a/namedev.h
+++ b/namedev.h
@@ -23,6 +23,7 @@
 #ifndef NAMEDEV_H
 #define NAMEDEV_H
 
+#include "udev.h"
 #include "list.h"
 
 struct sysfs_class_device;
index 586815e..5bd934a 100644 (file)
@@ -31,6 +31,7 @@
 #include "udev.h"
 #include "udev_version.h"
 #include "namedev.h"
+#include "udevdb.h"
 #include "libsysfs/libsysfs.h"
 
 
@@ -164,9 +165,31 @@ int udev_add_device(char *device, char *subsystem)
                dbg ("get_major_minor failed");
                goto exit;
        }
+       memset(&dbdev, 0, sizeof(dbdev));
+       strncpy(dbdev.name, attr.name, NAME_SIZE);
+       strncpy(dbdev.sysfs_path, class_dev->sysdevice->directory->path,
+               PATH_SIZE);
+       strncpy(dbdev.class_dev_name, class_dev->name, NAME_SIZE);
+       if ((sysfs_get_name_from_path(subsystem, dbdev.class_name, NAME_SIZE))
+           != 0)
+               strcpy(dbdev.class_name, "unkown");
+       strncpy(dbdev.bus_id, class_dev->sysdevice->bus_id, ID_SIZE);
+       strcpy(dbdev.bus_name, "unknown");
+       if (class_dev->driver != NULL)
+               strncpy(dbdev.driver, class_dev->driver->name, NAME_SIZE);
+       else
+               strcpy(dbdev.driver, "unkown");
+       dbdev.type = type;
+       dbdev.major = major;
+       dbdev.minor = minor;
+       dbdev.mode = attr.mode;
 
        sysfs_close_class_device(class_dev);
 
+       retval = udevdb_add_udevice(&dbdev);
+       if (retval != 0)
+               goto exit;
+
        return create_node(attr.name, type, major, minor, attr.mode);
 
 exit:
index cd917af..29063ef 100644 (file)
@@ -31,6 +31,7 @@
 #include "udev.h"
 #include "udev_version.h"
 #include "namedev.h"
+#include "udevdb.h"
 #include "libsysfs/libsysfs.h"
 
 
@@ -80,9 +81,10 @@ int udev_remove_device(char *device, char *subsystem)
                goto exit;
        }
 
+       udevdb_delete_udevice(name);
+
        return delete_node(name);
 
 exit:
        return retval;
 }
-
diff --git a/udevdb.c b/udevdb.c
new file mode 100644 (file)
index 0000000..b200f2f
--- /dev/null
+++ b/udevdb.c
@@ -0,0 +1,591 @@
+/*
+ * udev database library
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "udevdb.h"
+#include "tdb.h"
+
+static TDB_CONTEXT *busdb;
+static TDB_CONTEXT *classdb;
+static TDB_CONTEXT *namedb;
+
+/**
+ * busdb_record - bus and id are keys to look up name of device
+ */
+struct busdb_record {
+       char name[NAME_SIZE];
+};
+
+/**
+ * classdb_record - class name and class device name used as keys to find
+ *     device name.
+ */
+struct classdb_record {
+       char name[NAME_SIZE];
+};
+
+/**
+ * namedb_record - device name is key, remaining udevice info stored here.
+ */
+struct namedb_record {
+       char sysfs_path[PATH_SIZE];
+       char class_dev_name[NAME_SIZE];
+       char class_name[NAME_SIZE];
+       char bus[BUS_SIZE];
+       char id[ID_SIZE];
+       char driver[NAME_SIZE];
+       char type;
+       int major;
+       int minor;
+       int mode;
+};
+
+/**
+ * busdb_close: close busdb database
+ */
+static void busdb_close(void)
+{
+       if (busdb != NULL) {
+               tdb_close(busdb);
+               busdb = NULL;
+       }
+}
+
+/**
+ * classdb_close: close classdb database
+ */
+static void classdb_close(void)
+{
+       if (classdb != NULL) {
+               tdb_close(classdb);
+               classdb = NULL;
+       }
+}
+
+/**
+ * namedb_close: close name database
+ */
+static void namedb_close(void)
+{
+       if (namedb != NULL) {
+               tdb_close(namedb);
+               namedb = NULL;
+       }
+}
+
+/**
+ * busdb_open: open busdb's database
+ */
+static int busdb_open(void)
+{
+       busdb = tdb_open(BUS_DB, 0, 0, O_RDWR | O_CREAT, 0644);
+       if (busdb == NULL)
+               return -1;
+       return 0;
+}
+
+/**
+ * classdb_open: open classdb's database
+ */
+static int classdb_open(void)
+{
+       classdb = tdb_open(CLASS_DB, 0, 0, O_RDWR | O_CREAT, 0644);
+       if (classdb == NULL)
+               return -1;
+       return 0;
+}
+
+/**
+ * namedb_open: open name database
+ */
+static int namedb_open(void)
+{
+       namedb = tdb_open(NAME_DB, 0, 0, O_RDWR | O_CREAT, 0644);
+       if (namedb == NULL)
+               return -1;
+       return 0;
+}
+
+/**
+ * busdb_fetch
+ */
+static struct busdb_record *busdb_fetch(const char *bus, const char *id)
+{
+       TDB_DATA key, data;
+       char keystr[BUS_SIZE+ID_SIZE+2]; 
+       struct busdb_record *rec = NULL;
+
+       if (bus == NULL || id == NULL)
+               return NULL; 
+       if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE)
+               return NULL;
+
+       if ((busdb_open()) != 0)
+               return NULL;
+
+       memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
+       strcpy(keystr, bus);
+       strcat(keystr, UDEVDB_DEL);
+       strcat(keystr, id);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+
+       data = tdb_fetch(busdb, key);
+       busdb_close();
+       if (data.dptr == NULL || data.dsize == 0)
+               return NULL;
+       
+       rec = (struct busdb_record *)malloc(sizeof(struct busdb_record));
+       if (rec == NULL) {
+               free(data.dptr);
+               return NULL;
+       }
+       
+       memcpy(rec, data.dptr, sizeof(struct busdb_record));
+       free(data.dptr);
+
+       return rec;
+}
+
+/**
+ * classdb_fetch
+ */
+static struct classdb_record *classdb_fetch(const char *cls, 
+                                               const char *cls_dev)
+{
+       TDB_DATA key, data;
+       char keystr[NAME_SIZE+NAME_SIZE+2]; 
+       struct classdb_record *rec = NULL;
+
+       if (cls == NULL || cls_dev == NULL)
+               return NULL; 
+       if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE)
+               return NULL;
+
+       if ((classdb_open()) != 0)
+               return NULL;
+
+       memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
+       strcpy(keystr, cls);
+       strcat(keystr, UDEVDB_DEL);
+       strcat(keystr, cls_dev);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+
+       data = tdb_fetch(classdb, key);
+       classdb_close();
+       if (data.dptr == NULL || data.dsize == 0)
+               return NULL;
+       
+       rec = (struct classdb_record *)malloc(sizeof(struct classdb_record));
+       if (rec == NULL) {
+               free(data.dptr);
+               return NULL;
+       }
+       
+       memcpy(rec, data.dptr, sizeof(struct classdb_record));
+       free(data.dptr);
+
+       return rec;
+}
+
+/**
+ * namedb_fetch
+ */
+static struct namedb_record *namedb_fetch(const char *name)
+{
+       TDB_DATA key, data;
+       char nm_keystr[NAME_SIZE]; 
+       struct namedb_record *nrec = NULL;
+
+       if (name == NULL)
+               return NULL; 
+       if (strlen(name) >= NAME_SIZE)
+               return NULL;
+
+       if ((namedb_open()) != 0)
+               return NULL;
+
+       memset(nm_keystr, 0, NAME_SIZE);
+       strcpy(nm_keystr, name);
+
+       key.dptr = (void *)nm_keystr;
+       key.dsize = strlen(nm_keystr) + 1;
+
+       data = tdb_fetch(namedb, key);
+       namedb_close();
+
+       if (data.dptr == NULL || data.dsize == 0)
+               return NULL;
+
+       nrec = (struct namedb_record *)malloc(sizeof(struct namedb_record));
+       if (nrec == NULL) {
+               free(data.dptr);
+               return NULL;
+       }
+       
+       memcpy(nrec, data.dptr, sizeof(struct namedb_record));
+       free(data.dptr);
+
+       return nrec;
+}
+
+/**
+ * busdb_store
+ */
+static int busdb_store(const struct udevice *dev)
+{
+       TDB_DATA key, data;
+       char keystr[BUS_SIZE+ID_SIZE+2];
+       struct busdb_record rec;
+       int retval = 0;
+
+       if (dev == NULL)
+               return -1;
+
+       if ((retval = busdb_open()) != 0)
+               return -1;
+
+       memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
+       strcpy(keystr, dev->bus_name);
+       strcat(keystr, UDEVDB_DEL);
+       strcat(keystr, dev->bus_id);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+       
+       strcpy(rec.name, dev->name);
+
+       data.dptr = (void *) &rec;
+       data.dsize = sizeof(rec);
+       
+       retval = tdb_store(busdb, key, data, TDB_REPLACE); 
+
+       busdb_close();
+       return retval;
+}
+
+/**
+ * classdb_store
+ */
+static int classdb_store(const struct udevice *dev)
+{
+       TDB_DATA key, data;
+       char keystr[NAME_SIZE+NAME_SIZE+2];
+       struct classdb_record rec;
+       int retval = 0;
+
+       if (dev == NULL)
+               return -1;
+
+       if ((retval = classdb_open()) != 0)
+               return -1;
+
+       memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
+       strcpy(keystr, dev->class_name);
+       strcat(keystr, UDEVDB_DEL);
+       strcat(keystr, dev->class_dev_name);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+       
+       strcpy(rec.name, dev->name);
+
+       data.dptr = (void *) &rec;
+       data.dsize = sizeof(rec);
+       
+       retval = tdb_store(classdb, key, data, TDB_REPLACE); 
+
+       classdb_close();
+       return retval;
+}
+
+/**
+ * namedb_store
+ */
+static int namedb_store(const struct udevice *dev)
+{
+       TDB_DATA key, data;
+       char keystr[NAME_SIZE];
+       struct namedb_record rec;
+       int retval = 0;
+
+       if (dev == NULL)
+               return -1;
+
+       if ((retval = namedb_open()) != 0)
+               return -1;
+
+       memset(keystr, 0, NAME_SIZE);
+       strcpy(keystr, dev->name);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+       
+       strcpy(rec.sysfs_path, dev->sysfs_path);
+       strcpy(rec.bus, dev->bus_name);
+       strcpy(rec.id, dev->bus_id);
+       strcpy(rec.class_dev_name, dev->class_dev_name);
+       strcpy(rec.class_name, dev->class_name);
+       strcpy(rec.driver, dev->driver);
+       rec.type = dev->type;
+       rec.major = dev->major;
+       rec.minor = dev->minor;
+       rec.mode = dev->mode;
+
+       data.dptr = (void *) &rec;
+       data.dsize = sizeof(rec);
+       
+       retval = tdb_store(namedb, key, data, TDB_REPLACE); 
+
+       namedb_close();
+       return retval;
+}
+
+/**
+ * busdb_delete
+ */
+static int busdb_delete(const char *bus, const char *id)
+{
+       TDB_DATA key;
+       char keystr[BUS_SIZE+ID_SIZE+2]; 
+       int retval = 0;
+
+       if (bus == NULL || id == NULL)
+               return -1; 
+       if (strlen(bus) >= BUS_SIZE || strlen(id) >= ID_SIZE)
+               return -1;
+
+       if ((busdb_open()) != 0)
+               return -1;
+
+       memset(keystr, 0, (BUS_SIZE+ID_SIZE+2));
+       strcpy(keystr, bus);
+       strcat(keystr, UDEVDB_DEL);
+       strcat(keystr, id);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+
+       retval = tdb_delete(busdb, key);
+       busdb_close();
+       
+       return retval;
+}
+
+/**
+ * classdb_delete
+ */
+static int classdb_delete(const char *cls, const char *cls_dev)
+{
+       TDB_DATA key;
+       char keystr[NAME_SIZE+NAME_SIZE+2]; 
+       int retval = 0;
+
+       if (cls == NULL || cls_dev == NULL)
+               return -1; 
+       if (strlen(cls) >= NAME_SIZE || strlen(cls_dev) >= NAME_SIZE)
+               return -1;
+
+       if ((classdb_open()) != 0)
+               return -1;
+
+       memset(keystr, 0, (NAME_SIZE+NAME_SIZE+2));
+       strcpy(keystr, cls);
+       strcat(keystr, UDEVDB_DEL);
+       strcat(keystr, cls_dev);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+
+       retval = tdb_delete(classdb, key);
+       classdb_close();
+       
+       return retval;
+}
+
+/**
+ * namedb_delete
+ */
+static int namedb_delete(const char *name)
+{
+       TDB_DATA key;
+       char keystr[NAME_SIZE]; 
+       int retval = 0;
+
+       if (name == NULL)
+               return -1; 
+       if (strlen(name) >= NAME_SIZE)
+               return -1;
+
+       if ((namedb_open()) != 0)
+               return -1;
+
+       memset(keystr, 0, NAME_SIZE);
+       strcpy(keystr, name);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+
+       retval = tdb_delete(namedb, key);
+       namedb_close();
+
+       return retval;
+}
+
+/**
+ * namedb_exists
+ */
+static int namedb_exists(const char *name)
+{
+       TDB_DATA key;
+       char keystr[NAME_SIZE]; 
+       int retval = 0;
+
+       if (name == NULL)
+               return retval; 
+       if (strlen(name) >= NAME_SIZE)
+               return retval;
+
+       if ((namedb_open()) != 0)
+               return retval;
+
+       memset(keystr, 0, NAME_SIZE);
+       strcpy(keystr, name);
+
+       key.dptr = (void *)keystr;
+       key.dsize = strlen(keystr) + 1;
+
+       retval = tdb_exists(namedb, key);
+       namedb_close();
+
+       return retval;
+}
+
+/**
+ * udevdb_delete_udevice
+ */
+int udevdb_delete_udevice(const char *name)
+{
+       struct namedb_record *nrec = NULL;
+
+       if (name == NULL)
+               return -1; 
+
+       nrec = namedb_fetch(name);
+       if (nrec == NULL)
+               return -1;
+
+       busdb_delete(nrec->bus, nrec->id);
+       classdb_delete(nrec->class_name, nrec->class_dev_name);
+       namedb_delete(name);
+       free(nrec);
+
+       return 0;
+}
+
+/**
+ * udevdb_add_udevice: adds udevice to database
+ */
+int udevdb_add_udevice(const struct udevice *dev)
+{
+       if (dev == NULL) 
+               return -1;
+
+       if ((busdb_store(dev)) != 0)
+               return -1;
+       if ((classdb_store(dev)) != 0)
+               return -1;
+       if ((namedb_store(dev)) != 0)
+               return -1;
+
+       return 0;
+}
+
+/**
+ * udevdb_get_device: grab's device by name
+ */
+struct udevice *udevdb_get_udevice(const char *name)
+{
+       struct namedb_record *nrec = NULL;
+       struct udevice *dev = NULL;
+
+       if (name == NULL)
+               return NULL; 
+
+       nrec = namedb_fetch(name);
+       if (nrec == NULL)
+               return NULL;
+
+       dev = (struct udevice *)malloc(sizeof(struct udevice));
+       if (dev == NULL) {
+               free(nrec);
+               return NULL;
+       }
+
+       strcpy(dev->name, name);
+       strcpy(dev->sysfs_path, nrec->sysfs_path);
+       strcpy(dev->class_dev_name, nrec->class_dev_name);
+       strcpy(dev->class_name, nrec->class_name);
+       strcpy(dev->bus_name, nrec->bus);
+       strcpy(dev->bus_id, nrec->id);
+       dev->type = nrec->type;
+       dev->major = nrec->major;
+       dev->minor = nrec->minor;
+       dev->mode = nrec->mode;
+
+       free(nrec);
+
+       return dev;
+}
+
+/**
+ * udevdb_get_device_by_bus
+ */
+struct udevice *udevdb_get_udevice_by_bus(const char *bus, const char *id)
+{
+       struct busdb_record *brec = NULL;
+       struct udevice *dev = NULL;
+
+       if (bus == NULL || id == NULL)
+               return NULL;
+
+       brec = busdb_fetch(bus, id);
+       if (brec == NULL)
+               return NULL;
+
+       dev = udevdb_get_udevice(brec->name);
+       free(brec);
+
+       return dev;
+}
+
+/**
+ * udevdb_get_udevice_by_class
+ */
+struct udevice *udevdb_get_udevice_by_class(const char *cls, 
+                                               const char *cls_dev)
+{
+       struct classdb_record *crec = NULL;
+       struct udevice *dev = NULL;
+
+       if (cls == NULL || cls_dev == NULL)
+               return NULL;
+
+       crec = classdb_fetch(cls, cls_dev);
+       if (crec == NULL)
+               return NULL;
+
+       dev = udevdb_get_udevice(crec->name);
+       free(crec);
+
+       return dev;
+}
diff --git a/udevdb.h b/udevdb.h
new file mode 100644 (file)
index 0000000..d2c4a53
--- /dev/null
+++ b/udevdb.h
@@ -0,0 +1,41 @@
+/*
+ * udevdb header file
+ */
+#ifndef _UDEVDB_H_
+#define _UDEVDB_H_
+
+#include "namedev.h"
+#include "udev.h"
+
+#define BUS_DB         "/home/stekloff/src/udev-0.2/busdb.tdb"
+#define CLASS_DB       "/home/stekloff/src/udev-0.2/classdb.tdb"
+#define NAME_DB                "/home/stekloff/src/udev-0.2/namedb.tdb"
+
+#define PATH_SIZE      256
+
+#define UDEVDB_DEL     "#"
+
+struct udevice {
+       char name[NAME_SIZE];
+       char sysfs_path[PATH_SIZE];
+       char class_dev_name[NAME_SIZE];
+       char class_name[NAME_SIZE];
+       char bus_id[NAME_SIZE];
+       char bus_name[NAME_SIZE];
+       char driver[NAME_SIZE];
+       char type;
+       int major;
+       int minor;
+       int mode;
+};
+
+/* Function Prototypes */
+extern int udevdb_delete_udevice(const char *name);
+extern int udevdb_add_udevice(const struct udevice *dev);
+extern struct udevice *udevdb_get_udevice(const char *name);
+extern struct udevice *udevdb_get_udevice_by_bus(const char *bus, 
+                                                       const char *id);
+extern struct udevice *udevdb_get_udevice_by_class(const char *cls,
+                                                       const char *cls_dev);
+
+#endif /* _UDEVDB_H_ */