From 4a539daf1e5daa17b52239478d97f8dc7a6506b6 Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Sat, 27 Mar 2004 01:21:46 -0800 Subject: [PATCH] [PATCH] dev_d.c file sorting and cleanup On Thu, Mar 25, 2004 at 02:52:13AM +0100, Kay Sievers wrote: > Please have look if it still works for you, I only did a very quick > test. Here is a unified version, with all the functions moved to udev_lib.c. We have a generic function now, to call a given fnct(char *) for every file ending with a specific suffix, sorted in lexical order. We use it to execute the dev.d/ files and read our rules.d/ files. The binary should be a bit smaller now. I've also changed it, to not do the dev.d/ exec for net devices. --- dev_d.c | 114 +++++++++++++++--------------------------------- namedev.h | 4 +- namedev_parse.c | 93 ++++++--------------------------------- udev-add.c | 6 +-- udev_lib.c | 86 ++++++++++++++++++++++++++++++++++++ udev_lib.h | 1 + udevd.c | 6 +-- udevruler.c | 8 ++-- 8 files changed, 149 insertions(+), 169 deletions(-) diff --git a/dev_d.c b/dev_d.c index 9412c3da7..9bb9507b9 100644 --- a/dev_d.c +++ b/dev_d.c @@ -1,30 +1,23 @@ /* - * dev.d multipleer + * dev_d.c - dev.d/ multiplexer * * Copyright (C) 2004 Greg Kroah-Hartman * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation version 2 of the License. - * - * Based on the klibc version of hotplug written by: - * Author(s) Christian Borntraeger - * which was based on the shell script written by: - * Greg Kroah-Hartman - * */ -/* +/* * This essentially emulates the following shell script logic in C: - DIR="/etc/dev.d" - export DEVNODE="whatever_dev_name_udev_just_gave" - for I in "${DIR}/$DEVNODE/"*.dev "${DIR}/$1/"*.dev "${DIR}/default/"*.dev ; do - if [ -f $I ]; then $I $1 ; fi - done - exit 1; + * DIR="/etc/dev.d" + * export DEVNODE="whatever_dev_name_udev_just_gave" + * for I in "${DIR}/$DEVNODE/"*.dev "${DIR}/$1/"*.dev "${DIR}/default/"*.dev ; do + * if [ -f $I ]; then $I $1 ; fi + * done + * exit 1; */ -#include #include #include #include @@ -35,73 +28,38 @@ #include "udev_lib.h" #include "logging.h" -#define HOTPLUGDIR "/etc/dev.d" -#define SUFFIX ".dev" -#define COMMENT_PREFIX '#' +#define DEVD_DIR "/etc/dev.d/" +#define DEVD_SUFFIX ".dev" -static void run_program(char *name) +static int run_program(char *name) { pid_t pid; dbg("running %s", name); pid = fork(); - - if (pid < 0) { - perror("fork"); - return; - } - - if (pid > 0) { + switch (pid) { + case 0: + /* child */ + execv(name, main_argv); + dbg("exec of child failed"); + exit(1); + case -1: + dbg("fork of child failed"); + break; + return -1; + default: wait(NULL); - return; } - execv(name, main_argv); - exit(1); + return 0; } -static void execute_dir (char *dirname) -{ - DIR *directory; - struct dirent *entry; - char filename[NAME_SIZE]; - int name_len; - - dbg("opening %s", dirname); - directory = opendir(dirname); - if (!directory) - return; - - while ((entry = readdir(directory))) { - if (entry->d_name[0] == '\0') - break; - /* Don't run the files '.', '..', or hidden files, - * or files that start with a '#' */ - if ((entry->d_name[0] == '.') || - (entry->d_name[0] == COMMENT_PREFIX)) - continue; - - /* Nor do we run files that do not end in ".dev" */ - name_len = strlen(entry->d_name); - if (name_len < strlen(SUFFIX)) - continue; - if (strcmp(&entry->d_name[name_len - sizeof (SUFFIX) + 1], SUFFIX) != 0) - continue; - - /* FIXME - need to use file_list_insert() here to run these in sorted order... */ - snprintf(filename, sizeof(filename), "%s%s", dirname, entry->d_name); - filename[sizeof(filename)-1] = '\0'; - run_program(filename); - } - - closedir(directory); -} - -/* runs files in these directories in order: - * name given by udev - * subsystem - * default +/* + * runs files in these directories in order: + * / + * subsystem/ + * default/ */ void dev_d_send(struct udevice *dev, char *subsystem) { @@ -112,15 +70,15 @@ void dev_d_send(struct udevice *dev, char *subsystem) strfieldcat(devnode, dev->name); setenv("DEVNODE", devnode, 1); - snprintf(dirname, sizeof(dirname), HOTPLUGDIR "/%s/", dev->name); - dirname[sizeof(dirname)-1] = '\0'; - execute_dir(dirname); + strcpy(dirname, DEVD_DIR); + strfieldcat(dirname, dev->name); + call_foreach_file(run_program, dirname, DEVD_SUFFIX); - snprintf(dirname, sizeof(dirname), HOTPLUGDIR "/%s/", subsystem); - dirname[sizeof(dirname)-1] = '\0'; - execute_dir(dirname); + strcpy(dirname, DEVD_DIR); + strfieldcat(dirname, subsystem); + call_foreach_file(run_program, dirname, DEVD_SUFFIX); - strcpy(dirname, HOTPLUGDIR "/default/"); - execute_dir(dirname); + strcpy(dirname, DEVD_DIR "default"); + call_foreach_file(run_program, dirname, DEVD_SUFFIX); } diff --git a/namedev.h b/namedev.h index 68100d4f6..fa924b14d 100644 --- a/namedev.h +++ b/namedev.h @@ -53,8 +53,8 @@ struct sysfs_class_device; #define MAX_SYSFS_PAIRS 5 -#define RULEFILE_EXT ".rules" -#define PERMFILE_EXT ".permissions" +#define RULEFILE_SUFFIX ".rules" +#define PERMFILE_SUFFIX ".permissions" #define set_empty_perms(dev, m, o, g) \ if (dev->mode == 0) \ diff --git a/namedev_parse.c b/namedev_parse.c index f4ffdb21d..679efae1b 100644 --- a/namedev_parse.c +++ b/namedev_parse.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "udev.h" @@ -41,8 +40,6 @@ #include "logging.h" #include "namedev.h" -LIST_HEAD(file_list); - static int add_config_dev(struct config_device *new_dev) { @@ -416,88 +413,26 @@ exit: return retval; } -struct files { - struct list_head list; - char name[NAME_SIZE]; -}; - -/* sort files in lexical order */ -static int file_list_insert(char *filename) -{ - struct files *loop_file; - struct files *new_file; - - list_for_each_entry(loop_file, &file_list, list) { - if (strcmp(loop_file->name, filename) > 0) { - break; - } - } - - new_file = malloc(sizeof(struct files)); - if (new_file == NULL) { - dbg("error malloc"); - return -ENOMEM; - } - - strfieldcpy(new_file->name, filename); - list_add_tail(&new_file->list, &loop_file->list); - return 0; -} - -/* calls function for file or every file found in directory */ -static int call_foreach_file(int parser (char *f) , char *filename, char *extension) +int namedev_init_rules() { - struct dirent *ent; - DIR *dir; - char *ext; - char file[NAME_SIZE]; struct stat stats; - struct files *loop_file; - struct files *tmp_file; - /* look if we have a plain file or a directory to scan */ - stat(filename, &stats); + stat(udev_rules_filename, &stats); if ((stats.st_mode & S_IFMT) != S_IFDIR) - return parser(filename); - - /* sort matching filename into list */ - dbg("open config as directory '%s'", filename); - dir = opendir(filename); - while (1) { - ent = readdir(dir); - if (ent == NULL || ent->d_name[0] == '\0') - break; - - dbg("found file '%s'", ent->d_name); - ext = strrchr(ent->d_name, '.'); - if (ext == NULL) - continue; - - if (strcmp(ext, extension) == 0) { - dbg("put file in list '%s'", ent->d_name); - file_list_insert(ent->d_name); - } - } - - /* parse every file in the list */ - list_for_each_entry_safe(loop_file, tmp_file, &file_list, list) { - strfieldcpy(file, filename); - strfieldcat(file, loop_file->name); - parser(file); - list_del(&loop_file->list); - free(loop_file); - } - - closedir(dir); - return 0; -} - -int namedev_init_rules() -{ - return call_foreach_file(namedev_parse_rules, udev_rules_filename, RULEFILE_EXT); + return namedev_parse_rules(udev_rules_filename); + else + return call_foreach_file(namedev_parse_rules, + udev_rules_filename, RULEFILE_SUFFIX); } int namedev_init_permissions() { - return call_foreach_file(namedev_parse_permissions, udev_permissions_filename, PERMFILE_EXT); + struct stat stats; + + stat(udev_permissions_filename, &stats); + if ((stats.st_mode & S_IFMT) != S_IFDIR) + return namedev_parse_permissions(udev_permissions_filename); + else + return call_foreach_file(namedev_parse_permissions, + udev_permissions_filename, PERMFILE_SUFFIX); } diff --git a/udev-add.c b/udev-add.c index 4aff06e15..6dfd05910 100644 --- a/udev-add.c +++ b/udev-add.c @@ -393,6 +393,7 @@ static int rename_net_if(struct udevice *dev) retval = ioctl(sk, SIOCSIFNAME, &ifr); if (retval != 0) dbg("error changing net interface name"); + close(sk); return retval; } @@ -453,6 +454,8 @@ int udev_add_device(char *path, char *subsystem, int fake) case 'b': case 'c': retval = create_node(&dev, fake); + if ((retval == 0) && (!fake)) + dev_d_send(&dev, subsystem); break; case 'n': @@ -462,9 +465,6 @@ int udev_add_device(char *path, char *subsystem, int fake) break; } - if ((retval == 0) && (!fake)) - dev_d_send(&dev, subsystem); - exit: if (class_dev) sysfs_close_class_device(class_dev); diff --git a/udev_lib.c b/udev_lib.c index 4a9eea506..e9c16c863 100644 --- a/udev_lib.c +++ b/udev_lib.c @@ -21,14 +21,19 @@ #include #include +#include #include #include +#include +#include #include #include #include "libsysfs/sysfs/libsysfs.h" #include "udev.h" +#include "logging.h" #include "udev_lib.h" +#include "list.h" char *get_action(void) @@ -136,3 +141,84 @@ size_t buf_get_line(char *buf, size_t buflen, size_t cur) return count - cur; } +struct files { + struct list_head list; + char name[NAME_SIZE]; +}; + +/* sort files in lexical order */ +static int file_list_insert(char *filename, struct list_head *file_list) +{ + struct files *loop_file; + struct files *new_file; + + list_for_each_entry(loop_file, file_list, list) { + if (strcmp(loop_file->name, filename) > 0) { + break; + } + } + + new_file = malloc(sizeof(struct files)); + if (new_file == NULL) { + dbg("error malloc"); + return -ENOMEM; + } + + strfieldcpy(new_file->name, filename); + list_add_tail(&new_file->list, &loop_file->list); + return 0; +} + +/* calls function for file or every file found in directory */ +int call_foreach_file(int fnct(char *f) , char *dirname, char *suffix) +{ + struct dirent *ent; + DIR *dir; + char *ext; + char file[NAME_SIZE]; + struct files *loop_file; + struct files *tmp_file; + LIST_HEAD(file_list); + + dbg("open directory '%s'", dirname); + dir = opendir(dirname); + if (dir == NULL) { + dbg("unable to open '%s'", dirname); + return -1; + } + + while (1) { + ent = readdir(dir); + if (ent == NULL || ent->d_name[0] == '\0') + break; + + if ((ent->d_name[0] == '.') || (ent->d_name[0] == COMMENT_CHARACTER)) + continue; + + /* look for file with specified suffix */ + ext = strrchr(ent->d_name, '.'); + if (ext == NULL) + continue; + + if (strcmp(ext, suffix) != 0) + continue; + + dbg("put file '%s/%s' in list", dirname, ent->d_name); + file_list_insert(ent->d_name, &file_list); + } + + /* call function for every file in the list */ + list_for_each_entry_safe(loop_file, tmp_file, &file_list, list) { + strfieldcpy(file, dirname); + strfieldcat(file, "/"); + strfieldcat(file, loop_file->name); + + fnct(file); + + list_del(&loop_file->list); + free(loop_file); + } + + closedir(dir); + return 0; +} diff --git a/udev_lib.h b/udev_lib.h index 90a42ffe9..e412ba96f 100644 --- a/udev_lib.h +++ b/udev_lib.h @@ -75,6 +75,7 @@ extern char get_device_type(const char *path, 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); +extern int call_foreach_file(int fnct(char *f) , char *filename, char *extension); #endif diff --git a/udevd.c b/udevd.c index 4cb3e1d40..0757dcaf3 100644 --- a/udevd.c +++ b/udevd.c @@ -45,9 +45,9 @@ static int expected_seqnum = 0; volatile static int children_waiting; volatile static int msg_q_timeout; -LIST_HEAD(msg_list); -LIST_HEAD(exec_list); -LIST_HEAD(running_list); +static LIST_HEAD(msg_list); +static LIST_HEAD(exec_list); +static LIST_HEAD(running_list); static void exec_queue_manager(void); static void msg_queue_manager(void); diff --git a/udevruler.c b/udevruler.c index b66940e94..af2cf7bb8 100644 --- a/udevruler.c +++ b/udevruler.c @@ -81,8 +81,8 @@ struct device { int added; }; -LIST_HEAD(device_list); -int device_count; +static LIST_HEAD(device_list); +static int device_count; /* callback for database dump */ static int add_record(char *path, struct udevice *udev) @@ -149,8 +149,8 @@ struct attribute { char key[NAME_SIZE]; }; -LIST_HEAD(attribute_list); -int attribute_count; +static LIST_HEAD(attribute_list); +static int attribute_count; static int add_attribute(const char *key, int level) { -- 2.30.2