From: kay.sievers@vrfy.org Date: Tue, 19 Oct 2004 02:11:51 +0000 (-0700) Subject: [PATCH] big cleanup of internal udev api X-Git-Tag: 040~9 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=7a947ce51586fd4212447643df90580542777ab9 [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. --- diff --git a/dev_d.c b/dev_d.c index eaf9b1dc1..5580b5a36 100644 --- a/dev_d.c +++ b/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"); diff --git a/extras/start_udev b/extras/start_udev index bbf32a1bb..c2518761e 100644 --- a/extras/start_udev +++ b/extras/start_udev @@ -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 diff --git a/namedev.c b/namedev.c index 39f033726..03fc41d23 100644 --- a/namedev.c +++ b/namedev.c @@ -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); diff --git a/namedev.h b/namedev.h index fa924b14d..f1e008224 100644 --- a/namedev.h +++ b/namedev.h @@ -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); diff --git a/test/udev-test.pl b/test/udev-test.pl index 9e4e192c5..a7becf99d 100644 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -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"; diff --git a/udev.c b/udev.c index 10a937e47..8d5be0542 100644 --- a/udev.c +++ b/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(); diff --git a/udev.h b/udev.h index 642b30b51..70de729f3 100644 --- a/udev.h +++ b/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; diff --git a/udev_add.c b/udev_add.c index 08257609a..d07120de6 100644 --- a/udev_add.c +++ b/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; } diff --git a/udev_lib.c b/udev_lib.c index 4991ec3ac..bd3eeba66 100644 --- a/udev_lib.c +++ b/udev_lib.c @@ -29,7 +29,6 @@ #include #include -#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; diff --git a/udev_lib.h b/udev_lib.h index e9ff379fc..8a14ef00b 100644 --- a/udev_lib.h +++ b/udev_lib.h @@ -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); diff --git a/udev_remove.c b/udev_remove.c index d4be8bd6f..d97a2411f 100644 --- a/udev_remove.c +++ b/udev_remove.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -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; diff --git a/udevdb.c b/udevdb.c index a218b6617..3d0a9ea3c 100644 --- a/udevdb.c +++ b/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; diff --git a/udevdb.h b/udevdb.h index 6eaeb2566..6986a0a11 100644 --- a/udevdb.h +++ b/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); diff --git a/udevinfo.c b/udevinfo.c index 763cfd139..af2346c8f 100644 --- a/udevinfo.c +++ b/udevinfo.c @@ -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); diff --git a/udevstart.c b/udevstart.c index cabafb0ab..c4ec0f7b7 100644 --- a/udevstart.c +++ b/udevstart.c @@ -33,6 +33,7 @@ #include #include +#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); } diff --git a/udevtest.c b/udevtest.c index df882d2d8..fa1629af2 100644 --- a/udevtest.c +++ b/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;