--- udev-014/namedev.c.multi 2004-01-22 03:45:22.000000000 +0300 +++ udev-014/namedev.c 2004-01-26 20:10:45.273488984 +0300 @@ -703,30 +703,54 @@ int namedev_name_device(struct sysfs_cla } } - /* check if we are instructed to ignore this device */ - if (dev->name[0] == '\0') { + /* + * check if we are instructed to ignore this device + * unless name has already beed assigned + */ + if (udev->name[0] == '\0' && dev->name[0] == '\0' && dev->symlink[0] == '\0') { dbg("instructed to ignore this device"); return -1; } - /* Yup, this rule belongs to us! */ - info("configured rule in '%s' at line %i applied, '%s' becomes '%s'", - udev_rules_filename, dev->config_line, udev->kernel_name, dev->name); - strfieldcpy(udev->name, dev->name); - strfieldcpy(udev->symlink, dev->symlink); - goto found; + /* if everything matched add symlink to list of aliases */ + if (dev->symlink[0] != '\0') { + char temp[NAME_MAX]; + + /* do not clobber dev */ + strfieldcpy(temp, dev->symlink); + apply_format(udev, temp); + if (strlen(udev->symlink) + strlen(temp) + 2 > sizeof(udev->symlink)) + dbg("could not append symlink %s for %s", + dev->symlink, udev->kernel_name); + else { + strfieldcat(udev->symlink, temp); + strfieldcat(udev->symlink, " "); + } + } + + /* is this symlink only rule? */ + if (dev->name[0] == '\0') + continue; + + /* Yup, this rule belongs to us! + * but continue to collect symlinks */ + if (udev->name[0] == '\0') { + info("configured rule in '%s' at line %i applied, '%s' becomes '%s'", + dev->config_file, dev->config_line, udev->kernel_name, dev->name); + strfieldcpy(udev->name, dev->name); + + /* substitute placeholder */ + apply_format(udev, udev->name); + } else + dbg("conflicting rule for '%s' would become '%s'", + dev->kernel, dev->name); } /* no rule was found so we use the kernel name */ - strfieldcpy(udev->name, class_dev->name); - goto done; - -found: - /* substitute placeholder */ - apply_format(udev, udev->name); - apply_format(udev, udev->symlink); + if (udev->name[0] == '\0') + strfieldcpy(udev->name, class_dev->name); + dbg("symlinks for '%s' are: '%s'", udev->name, udev->symlink); -done: perm = find_perm(udev->name); if (perm) { udev->mode = perm->mode; --- udev-014/namedev.h.multi 2004-01-22 02:34:33.000000000 +0300 +++ udev-014/namedev.h 2004-01-26 19:47:14.195005520 +0300 @@ -66,6 +66,7 @@ struct config_device { char symlink[NAME_SIZE]; struct sysfs_pair sysfs_pair[MAX_SYSFS_PAIRS]; int config_line; + char *config_file; }; struct perm_device { --- udev-014/namedev_parse.c.multi 2004-01-22 03:46:01.000000000 +0300 +++ udev-014/namedev_parse.c 2004-01-26 19:47:14.335984088 +0300 @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "udev.h" #include "logging.h" @@ -120,7 +122,8 @@ void dump_perm_dev_list(void) dump_perm_dev(dev); } -int namedev_init_rules(void) + +static int parse_rules_file(const char *file) { char line[255]; int lineno; @@ -131,15 +134,19 @@ int namedev_init_rules(void) int program_given = 0; int retval = 0; struct config_device dev; + char *p; - fd = fopen(udev_rules_filename, "r"); + fd = fopen(file, "r"); if (fd != NULL) { - dbg("reading '%s' as rules file", udev_rules_filename); + dbg("reading '%s' as rules file", file); } else { - dbg("can't open '%s' as a rules file", udev_rules_filename); + dbg("can't open '%s' as a rules file", file); return -ENODEV; } + /* Yes, this is memory leak. It won't be freed */ + p = strdup(file); + /* loop through the whole file */ lineno = 0; while (1) { @@ -250,13 +257,14 @@ int namedev_init_rules(void) } dev.config_line = lineno; + dev.config_file = p; retval = add_config_dev(&dev); if (retval) { dbg("add_config_dev returned with error %d", retval); continue; error: dbg("%s:%d:%d: parse error, rule skipped", - udev_rules_filename, lineno, temp - line); + file, lineno, temp - line); } } exit: @@ -264,7 +272,7 @@ exit: return retval; } -int namedev_init_permissions(void) +static int parse_permissions_file(const char *file) { char line[255]; char *temp; @@ -273,11 +281,11 @@ int namedev_init_permissions(void) int retval = 0; struct perm_device dev; - fd = fopen(udev_permissions_filename, "r"); + fd = fopen(file, "r"); if (fd != NULL) { - dbg("reading '%s' as permissions file", udev_permissions_filename); + dbg("reading '%s' as permissions file", file); } else { - dbg("can't open '%s' as permissions file", udev_permissions_filename); + dbg("can't open '%s' as permissions file", file); return -ENODEV; } @@ -344,5 +352,98 @@ int namedev_init_permissions(void) exit: fclose(fd); return retval; +} + +static int ends_with(const char *name, const char *suf) +{ + char *p = strstr(name, suf); + + if (!p) + return 0; + + if (p[strlen(suf)]) + return 0; + + return 1; +} + +/* + * skip + * all hidden files + * usual backup files from editor or RPM + * non-plain files + */ +static int filter(const struct dirent *dirent) +{ + char *name = dirent->d_name; + struct stat buf; + + if (name[0] == '.') + return 0; + + if (ends_with(name, ".rpmorig") || + ends_with(name, ".rpmsave") || + ends_with(name, "~") || + ends_with(name, ".orig")) + return 0; + + if (stat(name, &buf) == -1) + return 0; + + if (!S_ISREG(buf.st_mode)) + return 0; + + return 1; +} + +static int parse_rules(char *file, int (*func)(const char *)) +{ + struct stat buf; + int err = 0; + + + if (stat(file, &buf) == -1) { + err = errno; + dbg("parse_rules: can't stat %s", file); + return errno; + } + + if (S_ISREG(buf.st_mode)) + return (*func)(file); + +#ifndef __KLIBC__ + if (S_ISDIR(buf.st_mode)) { + struct dirent **dirents; + int nfiles, i; + + if ((nfiles = scandir(file, &dirents, filter, alphasort)) == -1) { + err = errno; + dbg("parse_rules: scandir '%s' error", file); + return err; + } + + for (i = 0; i < nfiles; i++) { + char temp[PATH_MAX + NAME_MAX]; + + snprintf(temp, sizeof(temp), "%s/%s", file, dirents[i]->d_name); + err = (*func)(temp); + } + + return err; + } +#endif + + dbg("parse_rules: '%s' has unknown file type %o", file, buf.st_mode); + return -EINVAL; + +} + +int namedev_init_rules(void) +{ + return parse_rules(udev_rules_filename, parse_rules_file); } +int namedev_init_permissions(void) +{ + return parse_rules(udev_permissions_filename, parse_permissions_file); +} --- udev-014/udev.h.multi 2004-01-22 03:32:55.000000000 +0300 +++ udev-014/udev.h 2004-01-26 19:47:14.473963112 +0300 @@ -56,6 +56,13 @@ do { \ strncpy(to, from, sizeof(to)-1); \ } while (0) +#define strfieldcat(to, from) \ +do { \ + to[sizeof(to)-1] = '\0'; \ + strncat(to, from, sizeof(to)-1); \ +} while (0) + + extern int udev_add_device(char *path, char *subsystem); extern int udev_remove_device(char *path, char *subsystem); extern void udev_init_config(void);