mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
[PATCH] big cleanup of internal udev api
Here is the first patch to cleanup the internal processing of the various stages of an udev event. It should not change any behavior, but if your system depends on udev, please always test it before reboot :) We pass only one generic structure around between add, remove, namedev, db and dev_d handling and make all relevant data available to all internal stages. All udev structures are renamed to "udev". We replace the fake parameter by a flag in the udev structure. We open the class device in the main binaries and not in udev_add, to make it possible to use libsysfs for udevstart directory crawling. The last sleep parameters are removed.
This commit is contained in:
parent
8e0871196c
commit
7a947ce515
18
dev_d.c
18
dev_d.c
@ -80,7 +80,7 @@ static int run_program(char *name)
|
||||
* subsystem/
|
||||
* default/
|
||||
*/
|
||||
void dev_d_send(struct udevice *dev, const char *subsystem, const char *devpath)
|
||||
void dev_d_send(struct udevice *udev)
|
||||
{
|
||||
char dirname[256];
|
||||
char env_devname[NAME_SIZE];
|
||||
@ -91,17 +91,17 @@ void dev_d_send(struct udevice *dev, const char *subsystem, const char *devpath)
|
||||
return;
|
||||
|
||||
memset(env_devname, 0x00, sizeof(env_devname));
|
||||
if (dev->type == 'b' || dev->type == 'c') {
|
||||
if (udev->type == 'b' || udev->type == 'c') {
|
||||
strfieldcpy(env_devname, udev_root);
|
||||
strfieldcat(env_devname, dev->name);
|
||||
} else if (dev->type == 'n') {
|
||||
strfieldcpy(env_devname, dev->name);
|
||||
setenv("DEVPATH", devpath, 1);
|
||||
strfieldcat(env_devname, udev->name);
|
||||
} else if (udev->type == 'n') {
|
||||
strfieldcpy(env_devname, udev->name);
|
||||
setenv("DEVPATH", udev->devpath, 1);
|
||||
}
|
||||
setenv("DEVNAME", env_devname, 1);
|
||||
dbg("DEVNAME='%s'", env_devname);
|
||||
|
||||
devname = strdup(dev->name);
|
||||
devname = strdup(udev->name);
|
||||
if (!devname) {
|
||||
dbg("out of memory");
|
||||
return;
|
||||
@ -121,11 +121,11 @@ void dev_d_send(struct udevice *dev, const char *subsystem, const char *devpath)
|
||||
}
|
||||
|
||||
strcpy(dirname, DEVD_DIR);
|
||||
strfieldcat(dirname, dev->name);
|
||||
strfieldcat(dirname, udev->name);
|
||||
call_foreach_file(run_program, dirname, DEVD_SUFFIX);
|
||||
|
||||
strcpy(dirname, DEVD_DIR);
|
||||
strfieldcat(dirname, subsystem);
|
||||
strfieldcat(dirname, udev->subsystem);
|
||||
call_foreach_file(run_program, dirname, DEVD_SUFFIX);
|
||||
|
||||
strcpy(dirname, DEVD_DIR "default");
|
||||
|
@ -30,7 +30,6 @@ udevd=/sbin/udevd
|
||||
|
||||
run_udev () {
|
||||
export ACTION=add
|
||||
export UDEV_NO_SLEEP=1
|
||||
|
||||
# handle block devices and their partitions
|
||||
for i in ${sysfs_dir}/block/*; do
|
||||
|
@ -692,7 +692,7 @@ try_parent:
|
||||
|
||||
}
|
||||
|
||||
int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *udev)
|
||||
int namedev_name_device(struct udevice *udev, struct sysfs_class_device *class_dev)
|
||||
{
|
||||
struct sysfs_class_device *class_dev_parent;
|
||||
struct sysfs_device *sysfs_device = NULL;
|
||||
@ -718,9 +718,10 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
|
||||
}
|
||||
|
||||
if (sysfs_device) {
|
||||
dbg("found /device-device: path='%s', bus_id='%s', bus='%s'",
|
||||
dbg("found devices device: path='%s', bus_id='%s', bus='%s'",
|
||||
sysfs_device->path, sysfs_device->bus_id, sysfs_device->bus);
|
||||
strfieldcpy(udev->bus_id, sysfs_device->bus_id);
|
||||
strfieldcpy(udev->bus, sysfs_device->bus);
|
||||
}
|
||||
|
||||
strfieldcpy(udev->kernel_name, class_dev->name);
|
||||
|
@ -102,7 +102,7 @@ extern struct list_head config_device_list;
|
||||
extern struct list_head perm_device_list;
|
||||
|
||||
extern int namedev_init(void);
|
||||
extern int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *dev);
|
||||
extern int namedev_name_device(struct udevice *udev, struct sysfs_class_device *class_dev);
|
||||
extern int namedev_init_permissions(void);
|
||||
extern int namedev_init_rules(void);
|
||||
|
||||
|
@ -1100,7 +1100,6 @@ EOF
|
||||
$ENV{UDEV_TEST} = "yes";
|
||||
$ENV{SYSFS_PATH} = $sysfs;
|
||||
$ENV{UDEV_CONFIG_FILE} = $main_conf;
|
||||
$ENV{UDEV_NO_SLEEP} = "yes";
|
||||
$ENV{UDEV_NO_DEVD} = "yes";
|
||||
|
||||
|
||||
|
40
udev.c
40
udev.c
@ -107,9 +107,9 @@ static int subsystem_without_dev(const char *subsystem)
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
struct sigaction act;
|
||||
char *action;
|
||||
char *devpath = "";
|
||||
char *subsystem = "";
|
||||
struct sysfs_class_device *class_dev;
|
||||
struct udevice udev;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
int retval = -EINVAL;
|
||||
enum {
|
||||
ADD,
|
||||
@ -129,7 +129,10 @@ int main(int argc, char *argv[], char *envp[])
|
||||
if (strstr(argv[0], "udevstart")) {
|
||||
act_type = UDEVSTART;
|
||||
} else {
|
||||
action = get_action();
|
||||
const char *action = get_action();
|
||||
const char *devpath = get_devpath();
|
||||
const char *subsystem = get_subsystem(main_argv[1]);
|
||||
|
||||
if (!action) {
|
||||
dbg("no action?");
|
||||
goto exit;
|
||||
@ -139,16 +142,15 @@ int main(int argc, char *argv[], char *envp[])
|
||||
} else if (strcmp(action, "remove") == 0) {
|
||||
act_type = REMOVE;
|
||||
} else {
|
||||
dbg("unknown action '%s'", action);
|
||||
dbg("no action '%s' for us", action);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
devpath = get_devpath();
|
||||
if (!devpath) {
|
||||
dbg("no devpath?");
|
||||
goto exit;
|
||||
}
|
||||
dbg("looking at '%s'", devpath);
|
||||
dbg("looking at '%s'", udev.devpath);
|
||||
|
||||
/* we only care about class devices and block stuff */
|
||||
if (!strstr(devpath, "class") && !strstr(devpath, "block")) {
|
||||
@ -156,17 +158,18 @@ int main(int argc, char *argv[], char *envp[])
|
||||
goto exit;
|
||||
}
|
||||
|
||||
subsystem = get_subsystem(main_argv[1]);
|
||||
if (!subsystem) {
|
||||
dbg("no subsystem?");
|
||||
dbg("no subsystem");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* skip blacklisted subsystems */
|
||||
if (subsystem_without_dev(subsystem)) {
|
||||
dbg("don't care about '%s' devices", subsystem);
|
||||
exit(0);
|
||||
goto exit;
|
||||
};
|
||||
|
||||
udev_set_values(&udev, devpath, subsystem);
|
||||
}
|
||||
|
||||
/* set signal handlers */
|
||||
@ -192,12 +195,25 @@ int main(int argc, char *argv[], char *envp[])
|
||||
break;
|
||||
case ADD:
|
||||
dbg("udev add");
|
||||
|
||||
/* init rules */
|
||||
namedev_init();
|
||||
retval = udev_add_device(devpath, subsystem, NOFAKE);
|
||||
|
||||
/* open the device */
|
||||
snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath);
|
||||
class_dev = sysfs_open_class_device_path(path);
|
||||
if (class_dev == NULL) {
|
||||
dbg ("sysfs_open_class_device_path failed");
|
||||
break;
|
||||
}
|
||||
dbg("opened class_dev->name='%s'", class_dev->name);
|
||||
|
||||
/* name, create node, store in db */
|
||||
retval = udev_add_device(&udev, class_dev);
|
||||
break;
|
||||
case REMOVE:
|
||||
dbg("udev remove");
|
||||
retval = udev_remove_device(devpath, subsystem);
|
||||
retval = udev_remove_device(&udev);
|
||||
}
|
||||
|
||||
udevdb_exit();
|
||||
|
18
udev.h
18
udev.h
@ -41,11 +41,8 @@
|
||||
|
||||
#define LINE_SIZE 256
|
||||
|
||||
#define FAKE 1
|
||||
#define NOFAKE 0
|
||||
|
||||
/* length of public data to store in udevdb */
|
||||
#define UDEVICE_LEN (offsetof(struct udevice, bus_id))
|
||||
#define UDEVICE_DB_LEN (offsetof(struct udevice, devpath))
|
||||
|
||||
struct udevice {
|
||||
char name[NAME_SIZE];
|
||||
@ -61,20 +58,23 @@ struct udevice {
|
||||
char config_file[NAME_SIZE];
|
||||
long config_uptime;
|
||||
|
||||
/* private data that help us in building strings */
|
||||
/* private data, not stored in udevdb */
|
||||
char devpath[DEVPATH_SIZE];
|
||||
char subsystem[SUBSYSTEM_SIZE];
|
||||
char bus_id[SYSFS_NAME_LEN];
|
||||
char bus[SYSFS_NAME_LEN];
|
||||
char program_result[NAME_SIZE];
|
||||
char kernel_number[NAME_SIZE];
|
||||
char kernel_name[NAME_SIZE];
|
||||
int test_run;
|
||||
};
|
||||
|
||||
extern int udev_add_device(const char *path, const char *subsystem, int fake);
|
||||
extern int udev_remove_device(const char *path, const char *subsystem);
|
||||
extern int udev_add_device(struct udevice *udev, struct sysfs_class_device *class_dev);
|
||||
extern int udev_remove_device(struct udevice *udev);
|
||||
extern void udev_init_config(void);
|
||||
extern int udev_start(void);
|
||||
extern int parse_get_pair(char **orig_string, char **left, char **right);
|
||||
extern void dev_d_send(struct udevice *dev, const char *subsystem,
|
||||
const char *devpath);
|
||||
extern void dev_d_send(struct udevice *udev);
|
||||
|
||||
extern char **main_argv;
|
||||
extern char **main_envp;
|
||||
|
140
udev_add.c
140
udev_add.c
@ -186,7 +186,7 @@ static void set_to_local_user(char *user)
|
||||
endutent();
|
||||
}
|
||||
|
||||
static int create_node(struct udevice *dev, int fake)
|
||||
static int create_node(struct udevice *udev)
|
||||
{
|
||||
char filename[NAME_SIZE];
|
||||
char linkname[NAME_SIZE];
|
||||
@ -200,90 +200,89 @@ static int create_node(struct udevice *dev, int fake)
|
||||
int len;
|
||||
|
||||
strfieldcpy(filename, udev_root);
|
||||
strfieldcat(filename, dev->name);
|
||||
strfieldcat(filename, udev->name);
|
||||
|
||||
switch (dev->type) {
|
||||
switch (udev->type) {
|
||||
case 'b':
|
||||
dev->mode |= S_IFBLK;
|
||||
udev->mode |= S_IFBLK;
|
||||
break;
|
||||
case 'c':
|
||||
case 'u':
|
||||
dev->mode |= S_IFCHR;
|
||||
udev->mode |= S_IFCHR;
|
||||
break;
|
||||
case 'p':
|
||||
dev->mode |= S_IFIFO;
|
||||
udev->mode |= S_IFIFO;
|
||||
break;
|
||||
default:
|
||||
dbg("unknown node type %c\n", dev->type);
|
||||
dbg("unknown node type %c\n", udev->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* create parent directories if needed */
|
||||
if (strrchr(dev->name, '/'))
|
||||
if (strrchr(udev->name, '/'))
|
||||
create_path(filename);
|
||||
|
||||
if (dev->owner[0] != '\0') {
|
||||
if (udev->owner[0] != '\0') {
|
||||
char *endptr;
|
||||
unsigned long id = strtoul(dev->owner, &endptr, 10);
|
||||
unsigned long id = strtoul(udev->owner, &endptr, 10);
|
||||
if (endptr[0] == '\0')
|
||||
uid = (uid_t) id;
|
||||
else {
|
||||
struct passwd *pw;
|
||||
if (strncmp(dev->owner, LOCAL_USER, sizeof(LOCAL_USER)) == 0)
|
||||
set_to_local_user(dev->owner);
|
||||
if (strncmp(udev->owner, LOCAL_USER, sizeof(LOCAL_USER)) == 0)
|
||||
set_to_local_user(udev->owner);
|
||||
|
||||
pw = getpwnam(dev->owner);
|
||||
pw = getpwnam(udev->owner);
|
||||
if (pw == NULL)
|
||||
dbg("specified user unknown '%s'", dev->owner);
|
||||
dbg("specified user unknown '%s'", udev->owner);
|
||||
else
|
||||
uid = pw->pw_uid;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->group[0] != '\0') {
|
||||
if (udev->group[0] != '\0') {
|
||||
char *endptr;
|
||||
unsigned long id = strtoul(dev->group, &endptr, 10);
|
||||
unsigned long id = strtoul(udev->group, &endptr, 10);
|
||||
if (endptr[0] == '\0')
|
||||
gid = (gid_t) id;
|
||||
else {
|
||||
struct group *gr = getgrnam(dev->group);
|
||||
struct group *gr = getgrnam(udev->group);
|
||||
if (gr == NULL)
|
||||
dbg("specified group unknown '%s'", dev->group);
|
||||
dbg("specified group unknown '%s'", udev->group);
|
||||
else
|
||||
gid = gr->gr_gid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fake) {
|
||||
if (!udev->test_run) {
|
||||
info("creating device node '%s'", filename);
|
||||
if (make_node(filename, dev->major, dev->minor, dev->mode, uid, gid) != 0)
|
||||
if (make_node(filename, udev->major, udev->minor, udev->mode, uid, gid) != 0)
|
||||
goto error;
|
||||
} else {
|
||||
info("creating device node '%s', major = '%d', minor = '%d', "
|
||||
"mode = '%#o', uid = '%d', gid = '%d'", filename,
|
||||
dev->major, dev->minor, (mode_t)dev->mode, uid, gid);
|
||||
udev->major, udev->minor, (mode_t)udev->mode, uid, gid);
|
||||
}
|
||||
|
||||
/* create all_partitions if requested */
|
||||
if (dev->partitions > 0) {
|
||||
info("creating device partition nodes '%s[1-%i]'", filename, dev->partitions);
|
||||
if (!fake) {
|
||||
for (i = 1; i <= dev->partitions; i++) {
|
||||
if (udev->partitions > 0) {
|
||||
info("creating device partition nodes '%s[1-%i]'", filename, udev->partitions);
|
||||
if (!udev->test_run) {
|
||||
for (i = 1; i <= udev->partitions; i++) {
|
||||
strfieldcpy(partitionname, filename);
|
||||
strintcat(partitionname, i);
|
||||
make_node(partitionname, dev->major,
|
||||
dev->minor + i, dev->mode, uid, gid);
|
||||
make_node(partitionname, udev->major, udev->minor + i, udev->mode, uid, gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create symlink(s) if requested */
|
||||
foreach_strpart(dev->symlink, " ", pos, len) {
|
||||
foreach_strpart(udev->symlink, " ", pos, len) {
|
||||
strfieldcpymax(linkname, pos, len+1);
|
||||
strfieldcpy(filename, udev_root);
|
||||
strfieldcat(filename, linkname);
|
||||
dbg("symlink '%s' to node '%s' requested", filename, dev->name);
|
||||
if (!fake)
|
||||
dbg("symlink '%s' to node '%s' requested", filename, udev->name);
|
||||
if (!udev->test_run)
|
||||
if (strrchr(linkname, '/'))
|
||||
create_path(filename);
|
||||
|
||||
@ -291,8 +290,8 @@ static int create_node(struct udevice *dev, int fake)
|
||||
linktarget[0] = '\0';
|
||||
i = 0;
|
||||
tail = 0;
|
||||
while ((dev->name[i] == linkname[i]) && dev->name[i]) {
|
||||
if (dev->name[i] == '/')
|
||||
while ((udev->name[i] == linkname[i]) && udev->name[i]) {
|
||||
if (udev->name[i] == '/')
|
||||
tail = i+1;
|
||||
i++;
|
||||
}
|
||||
@ -302,10 +301,10 @@ static int create_node(struct udevice *dev, int fake)
|
||||
i++;
|
||||
}
|
||||
|
||||
strfieldcat(linktarget, &dev->name[tail]);
|
||||
strfieldcat(linktarget, &udev->name[tail]);
|
||||
|
||||
dbg("symlink(%s, %s)", linktarget, filename);
|
||||
if (!fake) {
|
||||
if (!udev->test_run) {
|
||||
selinux_setfscreatecon(filename, S_IFLNK);
|
||||
unlink(filename);
|
||||
if (symlink(linktarget, filename) != 0)
|
||||
@ -319,35 +318,14 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct sysfs_class_device *get_class_dev(const char *device_name)
|
||||
{
|
||||
char dev_path[SYSFS_PATH_MAX];
|
||||
struct sysfs_class_device *class_dev = NULL;
|
||||
|
||||
strfieldcpy(dev_path, sysfs_path);
|
||||
strfieldcat(dev_path, device_name);
|
||||
dbg("looking at '%s'", dev_path);
|
||||
|
||||
/* open up the sysfs class device for this thing... */
|
||||
class_dev = sysfs_open_class_device_path(dev_path);
|
||||
if (class_dev == NULL) {
|
||||
dbg ("sysfs_open_class_device_path failed");
|
||||
goto exit;
|
||||
}
|
||||
dbg("class_dev->name='%s'", class_dev->name);
|
||||
|
||||
exit:
|
||||
return class_dev;
|
||||
}
|
||||
|
||||
static int rename_net_if(struct udevice *dev, int fake)
|
||||
static int rename_net_if(struct udevice *udev)
|
||||
{
|
||||
int sk;
|
||||
struct ifreq ifr;
|
||||
int retval;
|
||||
|
||||
dbg("changing net interface name from '%s' to '%s'", dev->kernel_name, dev->name);
|
||||
if (fake)
|
||||
dbg("changing net interface name from '%s' to '%s'", udev->kernel_name, udev->name);
|
||||
if (udev->test_run)
|
||||
return 0;
|
||||
|
||||
sk = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
@ -357,8 +335,8 @@ static int rename_net_if(struct udevice *dev, int fake)
|
||||
}
|
||||
|
||||
memset(&ifr, 0x00, sizeof(struct ifreq));
|
||||
strfieldcpy(ifr.ifr_name, dev->kernel_name);
|
||||
strfieldcpy(ifr.ifr_newname, dev->name);
|
||||
strfieldcpy(ifr.ifr_name, udev->kernel_name);
|
||||
strfieldcpy(ifr.ifr_newname, udev->name);
|
||||
|
||||
retval = ioctl(sk, SIOCSIFNAME, &ifr);
|
||||
if (retval != 0)
|
||||
@ -368,69 +346,57 @@ static int rename_net_if(struct udevice *dev, int fake)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int udev_add_device(const char *path, const char *subsystem, int fake)
|
||||
int udev_add_device(struct udevice *udev, struct sysfs_class_device *class_dev)
|
||||
{
|
||||
struct sysfs_class_device *class_dev;
|
||||
struct udevice dev;
|
||||
char devpath[DEVPATH_SIZE];
|
||||
char *pos;
|
||||
int retval = 0;
|
||||
|
||||
memset(&dev, 0x00, sizeof(dev));
|
||||
|
||||
dev.type = get_device_type(path, subsystem);
|
||||
|
||||
class_dev = get_class_dev(path);
|
||||
if (class_dev == NULL)
|
||||
return -1;
|
||||
|
||||
if (dev.type == 'b' || dev.type == 'c') {
|
||||
retval = get_major_minor(class_dev, &dev);
|
||||
if (udev->type == 'b' || udev->type == 'c') {
|
||||
retval = get_major_minor(class_dev, udev);
|
||||
if (retval != 0) {
|
||||
dbg("no dev-file found, do nothing");
|
||||
goto close;
|
||||
}
|
||||
}
|
||||
|
||||
if (namedev_name_device(class_dev, &dev) != 0)
|
||||
if (namedev_name_device(udev, class_dev) != 0)
|
||||
goto exit;
|
||||
|
||||
dbg("name='%s'", dev.name);
|
||||
dbg("adding name='%s'", udev->name);
|
||||
|
||||
selinux_init();
|
||||
switch (dev.type) {
|
||||
switch (udev->type) {
|
||||
case 'b':
|
||||
case 'c':
|
||||
retval = create_node(&dev, fake);
|
||||
retval = create_node(udev);
|
||||
if (retval != 0)
|
||||
goto exit;
|
||||
if ((!fake) && (udevdb_add_dev(path, &dev) != 0))
|
||||
if ((!udev->test_run) && (udevdb_add_dev(udev) != 0))
|
||||
dbg("udevdb_add_dev failed, but we are going to try "
|
||||
"to create the node anyway. But remove might not "
|
||||
"work properly for this device.");
|
||||
|
||||
dev_d_send(&dev, subsystem, path);
|
||||
dev_d_send(udev);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
strfieldcpy(devpath, path);
|
||||
if (strcmp(dev.name, dev.kernel_name) != 0) {
|
||||
retval = rename_net_if(&dev, fake);
|
||||
if (strcmp(udev->name, udev->kernel_name) != 0) {
|
||||
retval = rename_net_if(udev);
|
||||
if (retval != 0)
|
||||
goto exit;
|
||||
/* netif's are keyed with the configured name, cause
|
||||
* the original kernel name sleeps with the fishes
|
||||
*/
|
||||
pos = strrchr(devpath, '/');
|
||||
pos = strrchr(udev->devpath, '/');
|
||||
if (pos != NULL) {
|
||||
pos[1] = '\0';
|
||||
strfieldcat(devpath, dev.name);
|
||||
strfieldcat(udev->devpath, udev->name);
|
||||
}
|
||||
}
|
||||
if ((!fake) && (udevdb_add_dev(devpath, &dev) != 0))
|
||||
if ((!udev->test_run) && (udevdb_add_dev(udev) != 0))
|
||||
dbg("udevdb_add_dev failed");
|
||||
|
||||
dev_d_send(&dev, subsystem, devpath);
|
||||
dev_d_send(udev);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "libsysfs/sysfs/libsysfs.h"
|
||||
#include "udev.h"
|
||||
#include "logging.h"
|
||||
#include "udev_lib.h"
|
||||
@ -113,6 +112,14 @@ char get_device_type(const char *path, const char *subsystem)
|
||||
return '\0';
|
||||
}
|
||||
|
||||
void udev_set_values(struct udevice *udev, const char* devpath, const char *subsystem)
|
||||
{
|
||||
memset(udev, 0x00, sizeof(struct udevice));
|
||||
strfieldcpy(udev->devpath, devpath);
|
||||
strfieldcpy(udev->subsystem, subsystem);
|
||||
udev->type = get_device_type(devpath, subsystem);
|
||||
}
|
||||
|
||||
int file_map(const char *filename, char **buf, size_t *bufsize)
|
||||
{
|
||||
struct stat stats;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#ifndef _UDEV_LIB_H_
|
||||
#define _UDEV_LIB_H_
|
||||
|
||||
#include "udev.h"
|
||||
|
||||
#define strfieldcpy(to, from) \
|
||||
do { \
|
||||
@ -81,6 +82,7 @@ extern char *get_devname(void);
|
||||
extern char *get_seqnum(void);
|
||||
extern char *get_subsystem(char *subsystem);
|
||||
extern char get_device_type(const char *path, const char *subsystem);
|
||||
extern void udev_set_values(struct udevice *udev, const char* devpath, const char *subsystem);
|
||||
extern int file_map(const char *filename, char **buf, size_t *bufsize);
|
||||
extern void file_unmap(char *buf, size_t bufsize);
|
||||
extern size_t buf_get_line(char *buf, size_t buflen, size_t cur);
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@ -161,35 +162,37 @@ static int delete_node(struct udevice *dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the sysfs path in the database to see if we have named this device
|
||||
* something different from the kernel name. If we have, us it. If not, use
|
||||
* the default kernel name for lack of anything else to know to do.
|
||||
* look up the sysfs path in the database to get the node name to remove
|
||||
* If we can't find it, use kernel name for lack of anything else to know to do
|
||||
*/
|
||||
int udev_remove_device(const char *path, const char *subsystem)
|
||||
int udev_remove_device(struct udevice *udev)
|
||||
{
|
||||
struct udevice dev;
|
||||
struct udevice db_dev;
|
||||
char *temp;
|
||||
int retval;
|
||||
|
||||
memset(&dev, 0x00, sizeof(dev));
|
||||
memset(&db_dev, 0x00, sizeof(struct udevice));
|
||||
|
||||
retval = udevdb_get_dev(path, &dev);
|
||||
if (retval != 0) {
|
||||
dbg("'%s' not found in database, falling back on default name", path);
|
||||
temp = strrchr(path, '/');
|
||||
retval = udevdb_get_dev(udev->devpath, &db_dev);
|
||||
if (retval == 0) {
|
||||
/* get stored values in our device */
|
||||
memcpy(udev, &db_dev, UDEVICE_DB_LEN);
|
||||
} else {
|
||||
/* fall back to kernel name */
|
||||
temp = strrchr(udev->devpath, '/');
|
||||
if (temp == NULL)
|
||||
return -ENODEV;
|
||||
strfieldcpy(dev.name, &temp[1]);
|
||||
strfieldcpy(udev->name, &temp[1]);
|
||||
dbg("'%s' not found in database, falling back on default name", udev->name);
|
||||
}
|
||||
dbg("name='%s'", dev.name);
|
||||
dbg("remove name='%s'", udev->name);
|
||||
|
||||
dev.type = get_device_type(path, subsystem);
|
||||
dev_d_send(&dev, subsystem, path);
|
||||
udevdb_delete_dev(path);
|
||||
dev_d_send(udev);
|
||||
udevdb_delete_dev(udev->devpath);
|
||||
|
||||
if (dev.type == 'b' || dev.type == 'c')
|
||||
retval = delete_node(&dev);
|
||||
else if (dev.type == 'n')
|
||||
if (udev->type == 'b' || udev->type == 'c')
|
||||
retval = delete_node(udev);
|
||||
else
|
||||
retval = 0;
|
||||
|
||||
return retval;
|
||||
|
36
udevdb.c
36
udevdb.c
@ -44,7 +44,7 @@
|
||||
static TDB_CONTEXT *udevdb;
|
||||
sig_atomic_t gotalarm;
|
||||
|
||||
int udevdb_add_dev(const char *path, const struct udevice *dev)
|
||||
int udevdb_add_dev(struct udevice *udev)
|
||||
{
|
||||
TDB_DATA key, data;
|
||||
char keystr[SYSFS_PATH_MAX];
|
||||
@ -52,22 +52,19 @@ int udevdb_add_dev(const char *path, const struct udevice *dev)
|
||||
if (udevdb == NULL)
|
||||
return -1;
|
||||
|
||||
if ((path == NULL) || (dev == NULL))
|
||||
return -ENODEV;
|
||||
|
||||
memset(keystr, 0, SYSFS_PATH_MAX);
|
||||
strfieldcpy(keystr, path);
|
||||
memset(keystr, 0x00, SYSFS_PATH_MAX);
|
||||
strfieldcpy(keystr, udev->devpath);
|
||||
key.dptr = keystr;
|
||||
key.dsize = strlen(keystr) + 1;
|
||||
|
||||
data.dptr = (void *)dev;
|
||||
data.dsize = UDEVICE_LEN;
|
||||
dbg("store key '%s' for device '%s'", path, dev->name);
|
||||
data.dptr = (void *) udev;
|
||||
data.dsize = UDEVICE_DB_LEN;
|
||||
dbg("store key '%s' for device '%s'", keystr, udev->name);
|
||||
|
||||
return tdb_store(udevdb, key, data, TDB_REPLACE);
|
||||
}
|
||||
|
||||
int udevdb_get_dev(const char *path, struct udevice *dev)
|
||||
int udevdb_get_dev(const char *path, struct udevice *udev)
|
||||
{
|
||||
TDB_DATA key, data;
|
||||
|
||||
@ -84,8 +81,9 @@ int udevdb_get_dev(const char *path, struct udevice *dev)
|
||||
if (data.dptr == NULL || data.dsize == 0)
|
||||
return -ENODEV;
|
||||
|
||||
memset(dev, 0, sizeof(struct udevice));
|
||||
memcpy(dev, data.dptr, UDEVICE_LEN);
|
||||
memset(udev, 0x00, sizeof(struct udevice));
|
||||
memcpy(udev, data.dptr, UDEVICE_DB_LEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -156,7 +154,7 @@ int udevdb_open_ro(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int (*user_record_callback) (char *path, struct udevice *dev);
|
||||
static int (*user_record_callback) (const char *path, struct udevice *dev);
|
||||
|
||||
static int traverse_callback(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
||||
{
|
||||
@ -167,7 +165,7 @@ static int traverse_callback(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void
|
||||
* udevdb_call_foreach: dumps whole database by passing record data to user function
|
||||
* @user_record_handler: user function called for every record in the database
|
||||
*/
|
||||
int udevdb_call_foreach(int (*user_record_handler) (char *path, struct udevice *dev))
|
||||
int udevdb_call_foreach(int (*user_record_handler) (const char *path, struct udevice *dev))
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
@ -191,27 +189,27 @@ static char *find_path;
|
||||
static const char *find_name;
|
||||
static int find_found;
|
||||
|
||||
static int find_device_by_name(char *path, struct udevice *dev)
|
||||
static int find_device_by_name(const char *path, struct udevice *udev)
|
||||
{
|
||||
char *pos;
|
||||
int len;
|
||||
|
||||
if (strncmp(dev->name, find_name, sizeof(dev->name)) == 0) {
|
||||
memcpy(find_dev, dev, sizeof(struct udevice));
|
||||
if (strncmp(udev->name, find_name, sizeof(udev->name)) == 0) {
|
||||
memcpy(find_dev, udev, sizeof(struct udevice));
|
||||
strfieldcpymax(find_path, path, NAME_SIZE);
|
||||
find_found = 1;
|
||||
/* stop search */
|
||||
return 1;
|
||||
}
|
||||
/* look for matching symlink*/
|
||||
foreach_strpart(dev->symlink, " ", pos, len) {
|
||||
foreach_strpart(udev->symlink, " ", pos, len) {
|
||||
if (strncmp(pos, find_name, len) != 0)
|
||||
continue;
|
||||
|
||||
if (len != strlen(find_name))
|
||||
continue;
|
||||
|
||||
memcpy(find_dev, dev, sizeof(struct udevice));
|
||||
memcpy(find_dev, udev, sizeof(struct udevice));
|
||||
strfieldcpymax(find_path, path, NAME_SIZE);
|
||||
find_found = 1;
|
||||
return 1;
|
||||
|
4
udevdb.h
4
udevdb.h
@ -12,9 +12,9 @@
|
||||
extern void udevdb_exit(void);
|
||||
extern int udevdb_init(int init_flag);
|
||||
extern int udevdb_open_ro(void);
|
||||
extern int udevdb_call_foreach(int (*user_record_handler) (char *path, struct udevice *dev));
|
||||
extern int udevdb_call_foreach(int (*user_record_handler) (const char *path, struct udevice *dev));
|
||||
|
||||
extern int udevdb_add_dev(const char *path, const struct udevice *dev);
|
||||
extern int udevdb_add_dev(struct udevice *dev);
|
||||
extern int udevdb_get_dev(const char *path, struct udevice *dev);
|
||||
extern int udevdb_delete_dev(const char *path);
|
||||
extern int udevdb_get_dev_byname(const char *name, char *path, struct udevice *dev);
|
||||
|
@ -104,7 +104,7 @@ exit:
|
||||
}
|
||||
|
||||
/* callback for database dump */
|
||||
static int print_record(char *path, struct udevice *dev)
|
||||
static int print_record(const char *path, struct udevice *dev)
|
||||
{
|
||||
printf("P: %s\n", path);
|
||||
printf("N: %s\n", dev->name);
|
||||
|
28
udevstart.c
28
udevstart.c
@ -33,6 +33,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libsysfs/sysfs/libsysfs.h"
|
||||
#include "logging.h"
|
||||
#include "udev_lib.h"
|
||||
#include "list.h"
|
||||
@ -86,19 +87,32 @@ static char *first_list[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void add_device(char *path, char *subsys, int fake)
|
||||
static int add_device(char *devpath, char *subsystem)
|
||||
{
|
||||
struct udevice udev;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
struct sysfs_class_device *class_dev;
|
||||
char *argv[3];
|
||||
|
||||
/* fake argument vector and environment for callouts and dev.d/ */
|
||||
argv[0] = "udev";
|
||||
argv[1] = subsys;
|
||||
argv[1] = subsystem;
|
||||
argv[2] = NULL;
|
||||
|
||||
main_argv = argv;
|
||||
setenv("DEVPATH", path, 1);
|
||||
setenv("DEVPATH", devpath, 1);
|
||||
setenv("ACTION", "add", 1);
|
||||
udev_add_device(path, subsys, fake);
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, devpath);
|
||||
class_dev = sysfs_open_class_device_path(path);
|
||||
if (class_dev == NULL) {
|
||||
dbg ("sysfs_open_class_device_path failed");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
udev_set_values(&udev, devpath, subsystem);
|
||||
|
||||
return udev_add_device(&udev, class_dev);
|
||||
}
|
||||
|
||||
static void exec_list(struct list_head *device_list)
|
||||
@ -111,7 +125,7 @@ static void exec_list(struct list_head *device_list)
|
||||
list_for_each_entry_safe(loop_device, tmp_device, device_list, list) {
|
||||
for (i=0; first_list[i] != NULL; i++) {
|
||||
if (strncmp(loop_device->path, first_list[i], strlen(first_list[i])) == 0) {
|
||||
add_device(loop_device->path, loop_device->subsys, NOFAKE);
|
||||
add_device(loop_device->path, loop_device->subsys);
|
||||
list_del(&loop_device->list);
|
||||
free(loop_device);
|
||||
break;
|
||||
@ -131,14 +145,14 @@ static void exec_list(struct list_head *device_list)
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
add_device(loop_device->path, loop_device->subsys, NOFAKE);
|
||||
add_device(loop_device->path, loop_device->subsys);
|
||||
list_del(&loop_device->list);
|
||||
free(loop_device);
|
||||
}
|
||||
|
||||
/* handle the rest of the devices left over, if any */
|
||||
list_for_each_entry_safe(loop_device, tmp_device, device_list, list) {
|
||||
add_device(loop_device->path, loop_device->subsys, NOFAKE);
|
||||
add_device(loop_device->path, loop_device->subsys);
|
||||
list_del(&loop_device->list);
|
||||
free(loop_device);
|
||||
}
|
||||
|
22
udevtest.c
22
udevtest.c
@ -55,9 +55,12 @@ void log_message (int level, const char *format, ...)
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
struct sysfs_class_device *class_dev;
|
||||
char *devpath;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
char temp[NAME_SIZE];
|
||||
char *subsystem = "";
|
||||
struct udevice udev;
|
||||
|
||||
main_argv = argv;
|
||||
main_envp = envp;
|
||||
@ -88,9 +91,8 @@ int main(int argc, char *argv[], char *envp[])
|
||||
info("looking at '%s'", devpath);
|
||||
|
||||
/* we only care about class devices and block stuff */
|
||||
if (!strstr(devpath, "class") &&
|
||||
!strstr(devpath, "block")) {
|
||||
info("not a block or class device");
|
||||
if (!strstr(devpath, "class") && !strstr(devpath, "block")) {
|
||||
dbg("not a block or class device");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -100,8 +102,20 @@ int main(int argc, char *argv[], char *envp[])
|
||||
if (argv[2] != NULL)
|
||||
subsystem = argv[2];
|
||||
|
||||
/* fill in values and test_run flag*/
|
||||
udev_set_values(&udev, devpath, subsystem);
|
||||
udev.test_run = 1;
|
||||
|
||||
/* open the device */
|
||||
snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath);
|
||||
class_dev = sysfs_open_class_device_path(path);
|
||||
if (class_dev == NULL)
|
||||
dbg ("sysfs_open_class_device_path failed");
|
||||
else
|
||||
dbg("opened class_dev->name='%s'", class_dev->name);
|
||||
|
||||
/* simulate node creation with fake flag */
|
||||
udev_add_device(devpath, subsystem, FAKE);
|
||||
udev_add_device(&udev, class_dev);
|
||||
|
||||
exit:
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user