--- udev-013/namedev.c.multi 2004-01-14 03:21:03.000000000 +0300 +++ udev-013/namedev.c 2004-01-20 19:44:08.689282216 +0300 @@ -715,28 +715,50 @@ int namedev_name_device(struct sysfs_cla } /* check if we are instructed to ignore this device */ - if (dev->name[0] == '\0') { + if (dev->name[0] == '\0' && dev->symlink[0] == '\0') { dbg("instructed to ignore this device"); return -1; } - /* Yup, this rule belongs to us! */ - dbg("found matching rule, '%s' becomes '%s'", dev->kernel, 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') { + dbg("found matching rule, '%s' becomes '%s'", + dev->kernel, 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-013/namedev_parse.c.multi 2004-01-13 03:09:55.000000000 +0300 +++ udev-013/namedev_parse.c 2004-01-17 22:58:16.000000000 +0300 @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "udev.h" #include "namedev.h" @@ -120,7 +122,7 @@ void dump_perm_dev_list(void) } -int namedev_init_rules(void) +static int parse_rules_file(const char *file) { char line[255]; int lineno; @@ -132,11 +134,11 @@ int namedev_init_rules(void) int retval = 0; struct config_device dev; - 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; } @@ -263,7 +265,7 @@ exit: return retval; } -int namedev_init_permissions(void) +static int parse_permissions_file(const char *file) { char line[255]; char *temp; @@ -272,11 +274,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; } @@ -345,4 +347,67 @@ exit: return retval; } +static int parse_rules(char *var, int (*func)(const char *)) +{ + static char temp[PATH_MAX + NAME_MAX]; + static char temp1[PATH_MAX + NAME_MAX]; + char *p = temp, *file; + struct stat buf; + int err = 0; + + strfieldcpy(temp, var); + while ((file = strsep(&p, " ")) != NULL) { + dbg("parse_rules: looking at file %s", file); + + if (stat(file, &buf) == -1) { + err = errno; + dbg("parse_rules: can't stat %s", file); + goto out; + } + + if (S_ISREG(buf.st_mode)) { + err = (*func)(file); + if (err) + goto out; + } else if (S_ISDIR(buf.st_mode)) { + DIR *dir; + struct dirent *dirent; + + if ((dir = opendir(file)) == NULL) { + err = errno; + dbg("parse_rules: can't open directory %s", file); + goto out; + } + + /* FIXME: This does not check for errors */ + while ((dirent = readdir(dir)) != NULL) { + if (dirent->d_name[0] == '.') + continue; + + dbg("parse_rules: for direntry %s", dirent->d_name); + strfieldcpy(temp1, file); + strfieldcat(temp1, "/"); + strfieldcat(temp1, dirent->d_name); + err = (*func)(temp1); + /* do not skip remaining files */ + } + } else { + dbg("parse_rules: unknown file type %s", file); + err = -EINVAL; + goto out; + } + } +out: + return err; +} + +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-013/udev.h.multi 2004-01-13 03:09:55.000000000 +0300 +++ udev-013/udev.h 2004-01-17 22:58:16.000000000 +0300 @@ -80,6 +80,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);