1
0
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:
kay.sievers@vrfy.org 2004-10-18 19:11:51 -07:00 committed by Greg KH
parent 8e0871196c
commit 7a947ce515
16 changed files with 193 additions and 174 deletions

18
dev_d.c
View File

@ -80,7 +80,7 @@ static int run_program(char *name)
* subsystem/ * subsystem/
* default/ * 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 dirname[256];
char env_devname[NAME_SIZE]; char env_devname[NAME_SIZE];
@ -91,17 +91,17 @@ void dev_d_send(struct udevice *dev, const char *subsystem, const char *devpath)
return; return;
memset(env_devname, 0x00, sizeof(env_devname)); 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); strfieldcpy(env_devname, udev_root);
strfieldcat(env_devname, dev->name); strfieldcat(env_devname, udev->name);
} else if (dev->type == 'n') { } else if (udev->type == 'n') {
strfieldcpy(env_devname, dev->name); strfieldcpy(env_devname, udev->name);
setenv("DEVPATH", devpath, 1); setenv("DEVPATH", udev->devpath, 1);
} }
setenv("DEVNAME", env_devname, 1); setenv("DEVNAME", env_devname, 1);
dbg("DEVNAME='%s'", env_devname); dbg("DEVNAME='%s'", env_devname);
devname = strdup(dev->name); devname = strdup(udev->name);
if (!devname) { if (!devname) {
dbg("out of memory"); dbg("out of memory");
return; return;
@ -121,11 +121,11 @@ void dev_d_send(struct udevice *dev, const char *subsystem, const char *devpath)
} }
strcpy(dirname, DEVD_DIR); strcpy(dirname, DEVD_DIR);
strfieldcat(dirname, dev->name); strfieldcat(dirname, udev->name);
call_foreach_file(run_program, dirname, DEVD_SUFFIX); call_foreach_file(run_program, dirname, DEVD_SUFFIX);
strcpy(dirname, DEVD_DIR); strcpy(dirname, DEVD_DIR);
strfieldcat(dirname, subsystem); strfieldcat(dirname, udev->subsystem);
call_foreach_file(run_program, dirname, DEVD_SUFFIX); call_foreach_file(run_program, dirname, DEVD_SUFFIX);
strcpy(dirname, DEVD_DIR "default"); strcpy(dirname, DEVD_DIR "default");

View File

@ -30,7 +30,6 @@ udevd=/sbin/udevd
run_udev () { run_udev () {
export ACTION=add export ACTION=add
export UDEV_NO_SLEEP=1
# handle block devices and their partitions # handle block devices and their partitions
for i in ${sysfs_dir}/block/*; do for i in ${sysfs_dir}/block/*; do

View File

@ -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_class_device *class_dev_parent;
struct sysfs_device *sysfs_device = NULL; 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) { 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); sysfs_device->path, sysfs_device->bus_id, sysfs_device->bus);
strfieldcpy(udev->bus_id, sysfs_device->bus_id); strfieldcpy(udev->bus_id, sysfs_device->bus_id);
strfieldcpy(udev->bus, sysfs_device->bus);
} }
strfieldcpy(udev->kernel_name, class_dev->name); strfieldcpy(udev->kernel_name, class_dev->name);

View File

@ -102,7 +102,7 @@ extern struct list_head config_device_list;
extern struct list_head perm_device_list; extern struct list_head perm_device_list;
extern int namedev_init(void); 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_permissions(void);
extern int namedev_init_rules(void); extern int namedev_init_rules(void);

View File

@ -1100,7 +1100,6 @@ EOF
$ENV{UDEV_TEST} = "yes"; $ENV{UDEV_TEST} = "yes";
$ENV{SYSFS_PATH} = $sysfs; $ENV{SYSFS_PATH} = $sysfs;
$ENV{UDEV_CONFIG_FILE} = $main_conf; $ENV{UDEV_CONFIG_FILE} = $main_conf;
$ENV{UDEV_NO_SLEEP} = "yes";
$ENV{UDEV_NO_DEVD} = "yes"; $ENV{UDEV_NO_DEVD} = "yes";

40
udev.c
View File

@ -107,9 +107,9 @@ static int subsystem_without_dev(const char *subsystem)
int main(int argc, char *argv[], char *envp[]) int main(int argc, char *argv[], char *envp[])
{ {
struct sigaction act; struct sigaction act;
char *action; struct sysfs_class_device *class_dev;
char *devpath = ""; struct udevice udev;
char *subsystem = ""; char path[SYSFS_PATH_MAX];
int retval = -EINVAL; int retval = -EINVAL;
enum { enum {
ADD, ADD,
@ -129,7 +129,10 @@ int main(int argc, char *argv[], char *envp[])
if (strstr(argv[0], "udevstart")) { if (strstr(argv[0], "udevstart")) {
act_type = UDEVSTART; act_type = UDEVSTART;
} else { } else {
action = get_action(); const char *action = get_action();
const char *devpath = get_devpath();
const char *subsystem = get_subsystem(main_argv[1]);
if (!action) { if (!action) {
dbg("no action?"); dbg("no action?");
goto exit; goto exit;
@ -139,16 +142,15 @@ int main(int argc, char *argv[], char *envp[])
} else if (strcmp(action, "remove") == 0) { } else if (strcmp(action, "remove") == 0) {
act_type = REMOVE; act_type = REMOVE;
} else { } else {
dbg("unknown action '%s'", action); dbg("no action '%s' for us", action);
goto exit; goto exit;
} }
devpath = get_devpath();
if (!devpath) { if (!devpath) {
dbg("no devpath?"); dbg("no devpath?");
goto exit; goto exit;
} }
dbg("looking at '%s'", devpath); dbg("looking at '%s'", udev.devpath);
/* we only care about class devices and block stuff */ /* we only care about class devices and block stuff */
if (!strstr(devpath, "class") && !strstr(devpath, "block")) { if (!strstr(devpath, "class") && !strstr(devpath, "block")) {
@ -156,17 +158,18 @@ int main(int argc, char *argv[], char *envp[])
goto exit; goto exit;
} }
subsystem = get_subsystem(main_argv[1]);
if (!subsystem) { if (!subsystem) {
dbg("no subsystem?"); dbg("no subsystem");
goto exit; goto exit;
} }
/* skip blacklisted subsystems */ /* skip blacklisted subsystems */
if (subsystem_without_dev(subsystem)) { if (subsystem_without_dev(subsystem)) {
dbg("don't care about '%s' devices", subsystem); dbg("don't care about '%s' devices", subsystem);
exit(0); goto exit;
}; };
udev_set_values(&udev, devpath, subsystem);
} }
/* set signal handlers */ /* set signal handlers */
@ -192,12 +195,25 @@ int main(int argc, char *argv[], char *envp[])
break; break;
case ADD: case ADD:
dbg("udev add"); dbg("udev add");
/* init rules */
namedev_init(); 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; break;
case REMOVE: case REMOVE:
dbg("udev remove"); dbg("udev remove");
retval = udev_remove_device(devpath, subsystem); retval = udev_remove_device(&udev);
} }
udevdb_exit(); udevdb_exit();

18
udev.h
View File

@ -41,11 +41,8 @@
#define LINE_SIZE 256 #define LINE_SIZE 256
#define FAKE 1
#define NOFAKE 0
/* length of public data to store in udevdb */ /* 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 { struct udevice {
char name[NAME_SIZE]; char name[NAME_SIZE];
@ -61,20 +58,23 @@ struct udevice {
char config_file[NAME_SIZE]; char config_file[NAME_SIZE];
long config_uptime; 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_id[SYSFS_NAME_LEN];
char bus[SYSFS_NAME_LEN];
char program_result[NAME_SIZE]; char program_result[NAME_SIZE];
char kernel_number[NAME_SIZE]; char kernel_number[NAME_SIZE];
char kernel_name[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_add_device(struct udevice *udev, struct sysfs_class_device *class_dev);
extern int udev_remove_device(const char *path, const char *subsystem); extern int udev_remove_device(struct udevice *udev);
extern void udev_init_config(void); extern void udev_init_config(void);
extern int udev_start(void); extern int udev_start(void);
extern int parse_get_pair(char **orig_string, char **left, char **right); extern int parse_get_pair(char **orig_string, char **left, char **right);
extern void dev_d_send(struct udevice *dev, const char *subsystem, extern void dev_d_send(struct udevice *udev);
const char *devpath);
extern char **main_argv; extern char **main_argv;
extern char **main_envp; extern char **main_envp;

View File

@ -186,7 +186,7 @@ static void set_to_local_user(char *user)
endutent(); endutent();
} }
static int create_node(struct udevice *dev, int fake) static int create_node(struct udevice *udev)
{ {
char filename[NAME_SIZE]; char filename[NAME_SIZE];
char linkname[NAME_SIZE]; char linkname[NAME_SIZE];
@ -200,90 +200,89 @@ static int create_node(struct udevice *dev, int fake)
int len; int len;
strfieldcpy(filename, udev_root); strfieldcpy(filename, udev_root);
strfieldcat(filename, dev->name); strfieldcat(filename, udev->name);
switch (dev->type) { switch (udev->type) {
case 'b': case 'b':
dev->mode |= S_IFBLK; udev->mode |= S_IFBLK;
break; break;
case 'c': case 'c':
case 'u': case 'u':
dev->mode |= S_IFCHR; udev->mode |= S_IFCHR;
break; break;
case 'p': case 'p':
dev->mode |= S_IFIFO; udev->mode |= S_IFIFO;
break; break;
default: default:
dbg("unknown node type %c\n", dev->type); dbg("unknown node type %c\n", udev->type);
return -EINVAL; return -EINVAL;
} }
/* create parent directories if needed */ /* create parent directories if needed */
if (strrchr(dev->name, '/')) if (strrchr(udev->name, '/'))
create_path(filename); create_path(filename);
if (dev->owner[0] != '\0') { if (udev->owner[0] != '\0') {
char *endptr; char *endptr;
unsigned long id = strtoul(dev->owner, &endptr, 10); unsigned long id = strtoul(udev->owner, &endptr, 10);
if (endptr[0] == '\0') if (endptr[0] == '\0')
uid = (uid_t) id; uid = (uid_t) id;
else { else {
struct passwd *pw; struct passwd *pw;
if (strncmp(dev->owner, LOCAL_USER, sizeof(LOCAL_USER)) == 0) if (strncmp(udev->owner, LOCAL_USER, sizeof(LOCAL_USER)) == 0)
set_to_local_user(dev->owner); set_to_local_user(udev->owner);
pw = getpwnam(dev->owner); pw = getpwnam(udev->owner);
if (pw == NULL) if (pw == NULL)
dbg("specified user unknown '%s'", dev->owner); dbg("specified user unknown '%s'", udev->owner);
else else
uid = pw->pw_uid; uid = pw->pw_uid;
} }
} }
if (dev->group[0] != '\0') { if (udev->group[0] != '\0') {
char *endptr; char *endptr;
unsigned long id = strtoul(dev->group, &endptr, 10); unsigned long id = strtoul(udev->group, &endptr, 10);
if (endptr[0] == '\0') if (endptr[0] == '\0')
gid = (gid_t) id; gid = (gid_t) id;
else { else {
struct group *gr = getgrnam(dev->group); struct group *gr = getgrnam(udev->group);
if (gr == NULL) if (gr == NULL)
dbg("specified group unknown '%s'", dev->group); dbg("specified group unknown '%s'", udev->group);
else else
gid = gr->gr_gid; gid = gr->gr_gid;
} }
} }
if (!fake) { if (!udev->test_run) {
info("creating device node '%s'", filename); 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; goto error;
} else { } else {
info("creating device node '%s', major = '%d', minor = '%d', " info("creating device node '%s', major = '%d', minor = '%d', "
"mode = '%#o', uid = '%d', gid = '%d'", filename, "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 */ /* create all_partitions if requested */
if (dev->partitions > 0) { if (udev->partitions > 0) {
info("creating device partition nodes '%s[1-%i]'", filename, dev->partitions); info("creating device partition nodes '%s[1-%i]'", filename, udev->partitions);
if (!fake) { if (!udev->test_run) {
for (i = 1; i <= dev->partitions; i++) { for (i = 1; i <= udev->partitions; i++) {
strfieldcpy(partitionname, filename); strfieldcpy(partitionname, filename);
strintcat(partitionname, i); strintcat(partitionname, i);
make_node(partitionname, dev->major, make_node(partitionname, udev->major, udev->minor + i, udev->mode, uid, gid);
dev->minor + i, dev->mode, uid, gid);
} }
} }
} }
/* create symlink(s) if requested */ /* create symlink(s) if requested */
foreach_strpart(dev->symlink, " ", pos, len) { foreach_strpart(udev->symlink, " ", pos, len) {
strfieldcpymax(linkname, pos, len+1); strfieldcpymax(linkname, pos, len+1);
strfieldcpy(filename, udev_root); strfieldcpy(filename, udev_root);
strfieldcat(filename, linkname); strfieldcat(filename, linkname);
dbg("symlink '%s' to node '%s' requested", filename, dev->name); dbg("symlink '%s' to node '%s' requested", filename, udev->name);
if (!fake) if (!udev->test_run)
if (strrchr(linkname, '/')) if (strrchr(linkname, '/'))
create_path(filename); create_path(filename);
@ -291,8 +290,8 @@ static int create_node(struct udevice *dev, int fake)
linktarget[0] = '\0'; linktarget[0] = '\0';
i = 0; i = 0;
tail = 0; tail = 0;
while ((dev->name[i] == linkname[i]) && dev->name[i]) { while ((udev->name[i] == linkname[i]) && udev->name[i]) {
if (dev->name[i] == '/') if (udev->name[i] == '/')
tail = i+1; tail = i+1;
i++; i++;
} }
@ -302,10 +301,10 @@ static int create_node(struct udevice *dev, int fake)
i++; i++;
} }
strfieldcat(linktarget, &dev->name[tail]); strfieldcat(linktarget, &udev->name[tail]);
dbg("symlink(%s, %s)", linktarget, filename); dbg("symlink(%s, %s)", linktarget, filename);
if (!fake) { if (!udev->test_run) {
selinux_setfscreatecon(filename, S_IFLNK); selinux_setfscreatecon(filename, S_IFLNK);
unlink(filename); unlink(filename);
if (symlink(linktarget, filename) != 0) if (symlink(linktarget, filename) != 0)
@ -319,35 +318,14 @@ error:
return -1; return -1;
} }
static struct sysfs_class_device *get_class_dev(const char *device_name) static int rename_net_if(struct udevice *udev)
{
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)
{ {
int sk; int sk;
struct ifreq ifr; struct ifreq ifr;
int retval; int retval;
dbg("changing net interface name from '%s' to '%s'", dev->kernel_name, dev->name); dbg("changing net interface name from '%s' to '%s'", udev->kernel_name, udev->name);
if (fake) if (udev->test_run)
return 0; return 0;
sk = socket(PF_INET, SOCK_DGRAM, 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)); memset(&ifr, 0x00, sizeof(struct ifreq));
strfieldcpy(ifr.ifr_name, dev->kernel_name); strfieldcpy(ifr.ifr_name, udev->kernel_name);
strfieldcpy(ifr.ifr_newname, dev->name); strfieldcpy(ifr.ifr_newname, udev->name);
retval = ioctl(sk, SIOCSIFNAME, &ifr); retval = ioctl(sk, SIOCSIFNAME, &ifr);
if (retval != 0) if (retval != 0)
@ -368,69 +346,57 @@ static int rename_net_if(struct udevice *dev, int fake)
return retval; 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; char *pos;
int retval = 0; int retval = 0;
memset(&dev, 0x00, sizeof(dev)); if (udev->type == 'b' || udev->type == 'c') {
retval = get_major_minor(class_dev, udev);
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 (retval != 0) { if (retval != 0) {
dbg("no dev-file found, do nothing"); dbg("no dev-file found, do nothing");
goto close; goto close;
} }
} }
if (namedev_name_device(class_dev, &dev) != 0) if (namedev_name_device(udev, class_dev) != 0)
goto exit; goto exit;
dbg("name='%s'", dev.name); dbg("adding name='%s'", udev->name);
selinux_init(); selinux_init();
switch (dev.type) { switch (udev->type) {
case 'b': case 'b':
case 'c': case 'c':
retval = create_node(&dev, fake); retval = create_node(udev);
if (retval != 0) if (retval != 0)
goto exit; 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 " dbg("udevdb_add_dev failed, but we are going to try "
"to create the node anyway. But remove might not " "to create the node anyway. But remove might not "
"work properly for this device."); "work properly for this device.");
dev_d_send(&dev, subsystem, path); dev_d_send(udev);
break; break;
case 'n': case 'n':
strfieldcpy(devpath, path); if (strcmp(udev->name, udev->kernel_name) != 0) {
if (strcmp(dev.name, dev.kernel_name) != 0) { retval = rename_net_if(udev);
retval = rename_net_if(&dev, fake);
if (retval != 0) if (retval != 0)
goto exit; goto exit;
/* netif's are keyed with the configured name, cause /* netif's are keyed with the configured name, cause
* the original kernel name sleeps with the fishes * the original kernel name sleeps with the fishes
*/ */
pos = strrchr(devpath, '/'); pos = strrchr(udev->devpath, '/');
if (pos != NULL) { if (pos != NULL) {
pos[1] = '\0'; 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"); dbg("udevdb_add_dev failed");
dev_d_send(&dev, subsystem, devpath); dev_d_send(udev);
break; break;
} }

View File

@ -29,7 +29,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mman.h> #include <sys/mman.h>
#include "libsysfs/sysfs/libsysfs.h"
#include "udev.h" #include "udev.h"
#include "logging.h" #include "logging.h"
#include "udev_lib.h" #include "udev_lib.h"
@ -113,6 +112,14 @@ char get_device_type(const char *path, const char *subsystem)
return '\0'; 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) int file_map(const char *filename, char **buf, size_t *bufsize)
{ {
struct stat stats; struct stat stats;

View File

@ -22,6 +22,7 @@
#ifndef _UDEV_LIB_H_ #ifndef _UDEV_LIB_H_
#define _UDEV_LIB_H_ #define _UDEV_LIB_H_
#include "udev.h"
#define strfieldcpy(to, from) \ #define strfieldcpy(to, from) \
do { \ do { \
@ -81,6 +82,7 @@ extern char *get_devname(void);
extern char *get_seqnum(void); extern char *get_seqnum(void);
extern char *get_subsystem(char *subsystem); extern char *get_subsystem(char *subsystem);
extern char get_device_type(const char *path, const 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 int file_map(const char *filename, char **buf, size_t *bufsize);
extern void file_unmap(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); extern size_t buf_get_line(char *buf, size_t buflen, size_t cur);

View File

@ -23,6 +23,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.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 * look up the sysfs path in the database to get the node name to remove
* something different from the kernel name. If we have, us it. If not, use * If we can't find it, use kernel name for lack of anything else to know to do
* the default 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; char *temp;
int retval; int retval;
memset(&dev, 0x00, sizeof(dev)); memset(&db_dev, 0x00, sizeof(struct udevice));
retval = udevdb_get_dev(path, &dev); retval = udevdb_get_dev(udev->devpath, &db_dev);
if (retval != 0) { if (retval == 0) {
dbg("'%s' not found in database, falling back on default name", path); /* get stored values in our device */
temp = strrchr(path, '/'); memcpy(udev, &db_dev, UDEVICE_DB_LEN);
} else {
/* fall back to kernel name */
temp = strrchr(udev->devpath, '/');
if (temp == NULL) if (temp == NULL)
return -ENODEV; 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(udev);
dev_d_send(&dev, subsystem, path); udevdb_delete_dev(udev->devpath);
udevdb_delete_dev(path);
if (dev.type == 'b' || dev.type == 'c') if (udev->type == 'b' || udev->type == 'c')
retval = delete_node(&dev); retval = delete_node(udev);
else if (dev.type == 'n') else
retval = 0; retval = 0;
return retval; return retval;

View File

@ -44,7 +44,7 @@
static TDB_CONTEXT *udevdb; static TDB_CONTEXT *udevdb;
sig_atomic_t gotalarm; 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; TDB_DATA key, data;
char keystr[SYSFS_PATH_MAX]; char keystr[SYSFS_PATH_MAX];
@ -52,22 +52,19 @@ int udevdb_add_dev(const char *path, const struct udevice *dev)
if (udevdb == NULL) if (udevdb == NULL)
return -1; return -1;
if ((path == NULL) || (dev == NULL)) memset(keystr, 0x00, SYSFS_PATH_MAX);
return -ENODEV; strfieldcpy(keystr, udev->devpath);
memset(keystr, 0, SYSFS_PATH_MAX);
strfieldcpy(keystr, path);
key.dptr = keystr; key.dptr = keystr;
key.dsize = strlen(keystr) + 1; key.dsize = strlen(keystr) + 1;
data.dptr = (void *)dev; data.dptr = (void *) udev;
data.dsize = UDEVICE_LEN; data.dsize = UDEVICE_DB_LEN;
dbg("store key '%s' for device '%s'", path, dev->name); dbg("store key '%s' for device '%s'", keystr, udev->name);
return tdb_store(udevdb, key, data, TDB_REPLACE); 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; 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) if (data.dptr == NULL || data.dsize == 0)
return -ENODEV; return -ENODEV;
memset(dev, 0, sizeof(struct udevice)); memset(udev, 0x00, sizeof(struct udevice));
memcpy(dev, data.dptr, UDEVICE_LEN); memcpy(udev, data.dptr, UDEVICE_DB_LEN);
return 0; return 0;
} }
@ -156,7 +154,7 @@ int udevdb_open_ro(void)
return 0; 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) 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 * 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 * @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; int retval = 0;
@ -191,27 +189,27 @@ static char *find_path;
static const char *find_name; static const char *find_name;
static int find_found; 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; char *pos;
int len; int len;
if (strncmp(dev->name, find_name, sizeof(dev->name)) == 0) { if (strncmp(udev->name, find_name, sizeof(udev->name)) == 0) {
memcpy(find_dev, dev, sizeof(struct udevice)); memcpy(find_dev, udev, sizeof(struct udevice));
strfieldcpymax(find_path, path, NAME_SIZE); strfieldcpymax(find_path, path, NAME_SIZE);
find_found = 1; find_found = 1;
/* stop search */ /* stop search */
return 1; return 1;
} }
/* look for matching symlink*/ /* look for matching symlink*/
foreach_strpart(dev->symlink, " ", pos, len) { foreach_strpart(udev->symlink, " ", pos, len) {
if (strncmp(pos, find_name, len) != 0) if (strncmp(pos, find_name, len) != 0)
continue; continue;
if (len != strlen(find_name)) if (len != strlen(find_name))
continue; continue;
memcpy(find_dev, dev, sizeof(struct udevice)); memcpy(find_dev, udev, sizeof(struct udevice));
strfieldcpymax(find_path, path, NAME_SIZE); strfieldcpymax(find_path, path, NAME_SIZE);
find_found = 1; find_found = 1;
return 1; return 1;

View File

@ -12,9 +12,9 @@
extern void udevdb_exit(void); extern void udevdb_exit(void);
extern int udevdb_init(int init_flag); extern int udevdb_init(int init_flag);
extern int udevdb_open_ro(void); 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_get_dev(const char *path, struct udevice *dev);
extern int udevdb_delete_dev(const char *path); extern int udevdb_delete_dev(const char *path);
extern int udevdb_get_dev_byname(const char *name, char *path, struct udevice *dev); extern int udevdb_get_dev_byname(const char *name, char *path, struct udevice *dev);

View File

@ -104,7 +104,7 @@ exit:
} }
/* callback for database dump */ /* 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("P: %s\n", path);
printf("N: %s\n", dev->name); printf("N: %s\n", dev->name);

View File

@ -33,6 +33,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "libsysfs/sysfs/libsysfs.h"
#include "logging.h" #include "logging.h"
#include "udev_lib.h" #include "udev_lib.h"
#include "list.h" #include "list.h"
@ -86,19 +87,32 @@ static char *first_list[] = {
NULL, 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]; char *argv[3];
/* fake argument vector and environment for callouts and dev.d/ */ /* fake argument vector and environment for callouts and dev.d/ */
argv[0] = "udev"; argv[0] = "udev";
argv[1] = subsys; argv[1] = subsystem;
argv[2] = NULL; argv[2] = NULL;
main_argv = argv; main_argv = argv;
setenv("DEVPATH", path, 1); setenv("DEVPATH", devpath, 1);
setenv("ACTION", "add", 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) 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) { list_for_each_entry_safe(loop_device, tmp_device, device_list, list) {
for (i=0; first_list[i] != NULL; i++) { for (i=0; first_list[i] != NULL; i++) {
if (strncmp(loop_device->path, first_list[i], strlen(first_list[i])) == 0) { 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); list_del(&loop_device->list);
free(loop_device); free(loop_device);
break; break;
@ -131,14 +145,14 @@ static void exec_list(struct list_head *device_list)
if (found) if (found)
continue; continue;
add_device(loop_device->path, loop_device->subsys, NOFAKE); add_device(loop_device->path, loop_device->subsys);
list_del(&loop_device->list); list_del(&loop_device->list);
free(loop_device); free(loop_device);
} }
/* handle the rest of the devices left over, if any */ /* handle the rest of the devices left over, if any */
list_for_each_entry_safe(loop_device, tmp_device, device_list, list) { 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); list_del(&loop_device->list);
free(loop_device); free(loop_device);
} }

View File

@ -55,9 +55,12 @@ void log_message (int level, const char *format, ...)
int main(int argc, char *argv[], char *envp[]) int main(int argc, char *argv[], char *envp[])
{ {
struct sysfs_class_device *class_dev;
char *devpath; char *devpath;
char path[SYSFS_PATH_MAX];
char temp[NAME_SIZE]; char temp[NAME_SIZE];
char *subsystem = ""; char *subsystem = "";
struct udevice udev;
main_argv = argv; main_argv = argv;
main_envp = envp; main_envp = envp;
@ -88,9 +91,8 @@ int main(int argc, char *argv[], char *envp[])
info("looking at '%s'", devpath); info("looking at '%s'", devpath);
/* we only care about class devices and block stuff */ /* we only care about class devices and block stuff */
if (!strstr(devpath, "class") && if (!strstr(devpath, "class") && !strstr(devpath, "block")) {
!strstr(devpath, "block")) { dbg("not a block or class device");
info("not a block or class device");
goto exit; goto exit;
} }
@ -100,8 +102,20 @@ int main(int argc, char *argv[], char *envp[])
if (argv[2] != NULL) if (argv[2] != NULL)
subsystem = argv[2]; 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 */ /* simulate node creation with fake flag */
udev_add_device(devpath, subsystem, FAKE); udev_add_device(&udev, class_dev);
exit: exit:
return 0; return 0;