libudev: device - read database only when needed

This commit is contained in:
Kay Sievers 2008-09-26 19:43:32 +02:00
parent 5fc523db68
commit 9921484458
4 changed files with 136 additions and 105 deletions

3
TODO
View file

@ -1,9 +1,6 @@
o enumerate() - add buses and drivers
o increase ressize buffer
o lazy loading of "uevent" and db
o lazy init of selinux
o add DVB variables to kernel, and drop shell script rule
o add watershed extra
o replace list.h with ccan list.h which is gpl-v2-or-later version

View file

@ -37,11 +37,12 @@ struct udev_device {
char *syspath;
const char *devpath;
const char *sysname;
char *devname;
char *devnode;
char *subsystem;
struct list_head link_list;
struct list_head devlink_list;
struct list_head properties_list;
char *action;
int event_timeout;
char *driver;
char *devpath_old;
char *physdevpath;
@ -52,6 +53,7 @@ struct udev_device {
int devlink_priority;
int ignore_remove;
struct list_head attr_list;
int info_loaded;
};
static size_t syspath_to_db_path(struct udev_device *udev_device, char *filename, size_t len)
@ -65,6 +67,84 @@ static size_t syspath_to_db_path(struct udev_device *udev_device, char *filename
return util_path_encode(&filename[start], len - start);
}
static int device_read_db(struct udev_device *udev_device)
{
struct stat stats;
char filename[UTIL_PATH_SIZE];
char line[UTIL_LINE_SIZE];
FILE *f;
syspath_to_db_path(udev_device, filename, sizeof(filename));
if (lstat(filename, &stats) != 0) {
info(udev_device->udev, "no db file to read %s: %s\n", filename, strerror(errno));
return -1;
}
if ((stats.st_mode & S_IFMT) == S_IFLNK) {
char target[UTIL_PATH_SIZE];
int target_len;
target_len = readlink(filename, target, sizeof(target));
if (target_len > 0)
target[target_len] = '\0';
else {
info(udev_device->udev, "error reading db link %s: %s\n", filename, strerror(errno));
return -1;
}
if (asprintf(&udev_device->devnode, "%s/%s", udev_get_dev_path(udev_device->udev), target) < 0)
return -ENOMEM;
info(udev_device->udev, "device %p filled with db symlink data '%s'\n", udev_device, udev_device->devnode);
return 0;
}
f = fopen(filename, "r");
if (f == NULL) {
info(udev_device->udev, "error reading db file %s: %s\n", filename, strerror(errno));
return -1;
}
while (fgets(line, sizeof(line), f)) {
ssize_t len;
const char *val;
len = strlen(line);
if (len < 4)
break;
line[len-1] = '\0';
val = &line[2];
switch(line[0]) {
case 'N':
asprintf(&udev_device->devnode, "%s/%s", udev_get_dev_path(udev_device->udev), val);
break;
case 'S':
util_strlcpy(filename, udev_get_dev_path(udev_device->udev), sizeof(filename));
util_strlcat(filename, "/", sizeof(filename));
util_strlcat(filename, val, sizeof(filename));
device_add_devlink(udev_device, filename);
break;
case 'L':
device_set_devlink_priority(udev_device, atoi(val));
break;
case 'T':
device_set_event_timeout(udev_device, atoi(val));
break;
case 'A':
device_set_num_fake_partitions(udev_device, atoi(val));
break;
case 'R':
device_set_ignore_remove(udev_device, atoi(val));
break;
case 'E':
device_add_property_from_string(udev_device, val);
break;
}
}
fclose(f);
info(udev_device->udev, "device %p filled with db file data\n", udev_device);
return 0;
}
static int device_read_uevent_file(struct udev_device *udev_device)
{
char filename[UTIL_PATH_SIZE];
@ -101,82 +181,16 @@ static int device_read_uevent_file(struct udev_device *udev_device)
return 0;
}
static int device_read_db(struct udev_device *udev_device)
static void device_load_info(struct udev_device *device)
{
struct stat stats;
char filename[UTIL_PATH_SIZE];
char line[UTIL_LINE_SIZE];
FILE *f;
device_read_uevent_file(device);
device_read_db(device);
device->info_loaded = 1;
}
syspath_to_db_path(udev_device, filename, sizeof(filename));
if (lstat(filename, &stats) != 0) {
info(udev_device->udev, "no db file to read %s: %s\n", filename, strerror(errno));
return -1;
}
if ((stats.st_mode & S_IFMT) == S_IFLNK) {
char target[UTIL_PATH_SIZE];
int target_len;
target_len = readlink(filename, target, sizeof(target));
if (target_len > 0)
target[target_len] = '\0';
else {
info(udev_device->udev, "error reading db link %s: %s\n", filename, strerror(errno));
return -1;
}
if (asprintf(&udev_device->devname, "%s/%s", udev_get_dev_path(udev_device->udev), target) < 0)
return -ENOMEM;
info(udev_device->udev, "device %p filled with db symlink data '%s'\n", udev_device, udev_device->devname);
return 0;
}
f = fopen(filename, "r");
if (f == NULL) {
info(udev_device->udev, "error reading db file %s: %s\n", filename, strerror(errno));
return -1;
}
while (fgets(line, sizeof(line), f)) {
ssize_t len;
const char *val;
len = strlen(line);
if (len < 4)
break;
line[len-1] = '\0';
val = &line[2];
switch(line[0]) {
case 'N':
asprintf(&udev_device->devname, "%s/%s", udev_get_dev_path(udev_device->udev), val);
break;
case 'S':
util_strlcpy(filename, udev_get_dev_path(udev_device->udev), sizeof(filename));
util_strlcat(filename, "/", sizeof(filename));
util_strlcat(filename, val, sizeof(filename));
device_add_devlink(udev_device, filename);
break;
case 'L':
device_set_devlink_priority(udev_device, atoi(val));
break;
case 'T':
device_set_timeout(udev_device, atoi(val));
break;
case 'A':
device_set_num_fake_partitions(udev_device, atoi(val));
break;
case 'R':
device_set_ignore_remove(udev_device, atoi(val));
break;
case 'E':
device_add_property_from_string(udev_device, val);
break;
}
}
fclose(f);
info(udev_device->udev, "device %p filled with db file data\n", udev_device);
return 0;
void device_set_info_loaded(struct udev_device *device)
{
device->info_loaded = 1;
}
struct udev_device *device_init(struct udev *udev)
@ -192,7 +206,7 @@ struct udev_device *device_init(struct udev *udev)
memset(udev_device, 0x00, sizeof(struct udev_device));
udev_device->refcount = 1;
udev_device->udev = udev;
INIT_LIST_HEAD(&udev_device->link_list);
INIT_LIST_HEAD(&udev_device->devlink_list);
INIT_LIST_HEAD(&udev_device->properties_list);
INIT_LIST_HEAD(&udev_device->attr_list);
info(udev_device->udev, "udev_device: %p created\n", udev_device);
@ -241,8 +255,6 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *
device_set_syspath(udev_device, path);
info(udev, "device %p has devpath '%s'\n", udev_device, udev_device_get_devpath(udev_device));
device_read_uevent_file(udev_device);
device_read_db(udev_device);
return udev_device;
}
@ -381,9 +393,9 @@ void udev_device_unref(struct udev_device *udev_device)
if (udev_device->parent_device != NULL)
udev_device_unref(udev_device->parent_device);
free(udev_device->syspath);
free(udev_device->devname);
free(udev_device->devnode);
free(udev_device->subsystem);
list_cleanup(udev_device->udev, &udev_device->link_list);
list_cleanup(udev_device->udev, &udev_device->devlink_list);
list_cleanup(udev_device->udev, &udev_device->properties_list);
free(udev_device->action);
free(udev_device->driver);
@ -446,7 +458,9 @@ const char *udev_device_get_devnode(struct udev_device *udev_device)
{
if (udev_device == NULL)
return NULL;
return udev_device->devname;
if (!udev_device->info_loaded)
device_load_info(udev_device);
return udev_device->devnode;
}
/**
@ -506,7 +520,11 @@ const char *udev_device_get_subsystem(struct udev_device *udev_device)
**/
struct udev_list *udev_device_get_devlinks_list(struct udev_device *udev_device)
{
return list_get_entry(&udev_device->link_list);
if (udev_device == NULL)
return NULL;
if (!udev_device->info_loaded)
device_load_info(udev_device);
return list_get_entry(&udev_device->devlink_list);
}
/**
@ -523,6 +541,10 @@ struct udev_list *udev_device_get_devlinks_list(struct udev_device *udev_device)
**/
struct udev_list *udev_device_get_properties_list(struct udev_device *udev_device)
{
if (udev_device == NULL)
return NULL;
if (!udev_device->info_loaded)
device_load_info(udev_device);
return list_get_entry(&udev_device->properties_list);
}
@ -544,6 +566,8 @@ dev_t udev_device_get_devnum(struct udev_device *udev_device)
{
if (udev_device == NULL)
return makedev(0, 0);
if (!udev_device->info_loaded)
device_load_info(udev_device);
return udev_device->devnum;
}
@ -576,7 +600,7 @@ const char *udev_device_get_attr_value(struct udev_device *udev_device, const ch
while (list != NULL) {
if (strcmp(udev_list_get_name(list), attr) == 0) {
info(udev_device->udev, "got '%s' (%s) from cache\n", attr, udev_list_get_value(list));
return udev_list_get_name(list);
return udev_list_get_value(list);
}
list = udev_list_get_next(list);
}
@ -663,17 +687,17 @@ int device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
return 0;
}
int device_set_devname(struct udev_device *udev_device, const char *devname)
int device_set_devnode(struct udev_device *udev_device, const char *devnode)
{
udev_device->devname = strdup(devname);
if (udev_device->devname == NULL)
udev_device->devnode = strdup(devnode);
if (udev_device->devnode == NULL)
return -ENOMEM;
return 0;
}
int device_add_devlink(struct udev_device *udev_device, const char *devlink)
{
if (list_insert(udev_device->udev, &udev_device->link_list, devlink, NULL, 0) == NULL)
if (list_insert(udev_device->udev, &udev_device->devlink_list, devlink, NULL, 0) == NULL)
return -ENOMEM;
return 0;
}
@ -720,8 +744,6 @@ int device_set_driver(struct udev_device *udev_device, const char *driver)
const char *device_get_devpath_old(struct udev_device *udev_device)
{
if (udev_device == NULL)
return NULL;
return udev_device->devpath_old;
}
@ -735,8 +757,6 @@ int device_set_devpath_old(struct udev_device *udev_device, const char *devpath_
const char *device_get_physdevpath(struct udev_device *udev_device)
{
if (udev_device == NULL)
return NULL;
return udev_device->physdevpath;
}
@ -750,8 +770,6 @@ int device_set_physdevpath(struct udev_device *udev_device, const char *physdevp
int device_get_timeout(struct udev_device *udev_device)
{
if (udev_device == NULL)
return -1;
return udev_device->timeout;
}
@ -760,6 +778,18 @@ int device_set_timeout(struct udev_device *udev_device, int timeout)
udev_device->timeout = timeout;
return 0;
}
int device_get_event_timeout(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
device_load_info(udev_device);
return udev_device->event_timeout;
}
int device_set_event_timeout(struct udev_device *udev_device, int event_timeout)
{
udev_device->event_timeout = event_timeout;
return 0;
}
int device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
{
@ -775,8 +805,8 @@ int device_set_devnum(struct udev_device *udev_device, dev_t devnum)
int device_get_num_fake_partitions(struct udev_device *udev_device)
{
if (udev_device == NULL)
return -1;
if (!udev_device->info_loaded)
device_load_info(udev_device);
return udev_device->num_fake_partitions;
}
@ -788,8 +818,8 @@ int device_set_num_fake_partitions(struct udev_device *udev_device, int num)
int device_get_devlink_priority(struct udev_device *udev_device)
{
if (udev_device == NULL)
return -1;
if (!udev_device->info_loaded)
device_load_info(udev_device);
return udev_device->devlink_priority;
}
@ -801,8 +831,8 @@ int device_set_devlink_priority(struct udev_device *udev_device, int prio)
int device_get_ignore_remove(struct udev_device *udev_device)
{
if (udev_device == NULL)
return -1;
if (!udev_device->info_loaded)
device_load_info(udev_device);
return udev_device->ignore_remove;
}

View file

@ -308,7 +308,7 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito
} else if (strncmp(key, "SUBSYSTEM=", 10) == 0) {
device_set_subsystem(udev_device, &key[10]);
} else if (strncmp(key, "DEVNAME=", 8) == 0) {
device_set_devname(udev_device, &key[8]);
device_set_devnode(udev_device, &key[8]);
} else if (strncmp(key, "DEVLINKS=", 9) == 0) {
char *slink = &key[9];
char *next = strchr(slink, ' ');
@ -344,5 +344,6 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito
}
device_set_devnum(udev_device, makedev(maj, min));
device_set_info_loaded(udev_device);
return udev_device;
}

View file

@ -55,7 +55,7 @@ extern int udev_get_run(struct udev *udev);
/* libudev-device */
extern int device_set_syspath(struct udev_device *udev_device, const char *syspath);
extern int device_set_subsystem(struct udev_device *udev_device, const char *subsystem);
extern int device_set_devname(struct udev_device *udev_device, const char *devname);
extern int device_set_devnode(struct udev_device *udev_device, const char *devnode);
extern int device_add_devlink(struct udev_device *udev_device, const char *devlink);
extern int device_add_property(struct udev_device *udev_device, const char *key, const char *value);
extern int device_add_property_from_string(struct udev_device *udev_device, const char *property);
@ -67,6 +67,8 @@ extern const char *device_get_physdevpath(struct udev_device *udev_device);
extern int device_set_physdevpath(struct udev_device *udev_device, const char *physdevpath);
extern int device_get_timeout(struct udev_device *udev_device);
extern int device_set_timeout(struct udev_device *udev_device, int timeout);
extern int device_get_event_timeout(struct udev_device *udev_device);
extern int device_set_event_timeout(struct udev_device *udev_device, int event_timeout);
extern int device_set_devnum(struct udev_device *udev_device, dev_t devnum);
extern int device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum);
extern int device_get_num_fake_partitions(struct udev_device *udev_device);
@ -75,6 +77,7 @@ extern int device_get_devlink_priority(struct udev_device *udev_device);
extern int device_set_devlink_priority(struct udev_device *udev_device, int prio);
extern int device_get_ignore_remove(struct udev_device *udev_device);
extern int device_set_ignore_remove(struct udev_device *udev_device, int ignore);
extern void device_set_info_loaded(struct udev_device *device);
/* libudev-ctrl - daemon runtime setup */
struct udev_ctrl;