From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrey Borzenkov Date: Mon, 26 Jan 2004 17:31:23 +0000 Subject: Re: [PATCH] multple rules files support/symlink rules support Message-Id: <200401262031.24064.arvidjaar@mail.ru> MIME-Version: 1 Content-Type: multipart/mixed; boundary="Boundary-00=_r7UFA/hxhIjHrhZ" List-Id: References: <200401172313.00189.arvidjaar@mail.ru> In-Reply-To: <200401172313.00189.arvidjaar@mail.ru> To: linux-hotplug@vger.kernel.org --Boundary-00=_r7UFA/hxhIjHrhZ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline On Thursday 22 January 2004 20:44, Svetoslav Slavtchev wrote: > > On Sat, Jan 17, 2004 at 11:13:00PM +0300, Andrey Borzenkov wrote: > > > Attached patch adds support for > > > > > > - multiple rules files. You can now do > > > > > > udev_rules="file1 dir2 file3 ..." > > > > > > directory is scanned and all files are read. Currently it does not > > > > descend > > > > > into subdirs. > > > > Ok, that is nice. I like that part of the patch. > > I do not :) the only reason to allow multiple files was to allow overriding; I had to update patch for ude-014 and sorting directory contents turned out to be quite easy so this is the final version - it takes single name which is either file or directory; directory is scanned, sorted in ascending order and read. klibc version does not support directory. > > > > I don't really understand this. Can you give an example of how this > > would work? Why do we want to have multiple symlinks from different > > rules? > distribution comes with predefined rules. Taking Mandrake (which is likely to use Svetoslav config) it ships with devfs rules that are keyed on kernel name. Now user may want to name specific device based on different criteria, e.g. serial number. I.e. you now have KERNEL="sd*" SYMLINK="ide/host..." SYSFS_serial="XYZ123" SYMLINK="my_removable" you simply can't easily merge these two rules. Allowing second rule (in second file) is much more flexible - you simply get two symlinks pointing to the same file. None of them knows or cares about device is really named as long as symlinks are correctly created. because this version assumes configuration be ordered it now ignores name only if it has not already been defined; else name with empty NAME/SYMLINK is silently ignored. > please take a look in the attached files > > - the first should create layout as the one of static /dev (00-lsb) > - the second adds devfs symlinks (01-devfs) Svetoslav did very good job making devfs compatibility config; please consider adding it to distribution. It appeears to be mostly complete; there is inherent problem with /dev/discs and /dev/cdroms that probably is not worth time spent on it (i.e. - drop it). regards -andrey > - additional one's could be used by the configuration > tools of the distribution( e.g. to create /dev/cd-writer or /dev/dvd) > - and at the end would come the personal rules of the > owner of the system > > in this way the device would be accessable from the standard > static /dev, devfs, and the additional system/personal namespaces > > in this way, if the owner changes only his rule file, he can not harm the > system > he only add's a personal symlink, devices are created as in static dev, > with symlink for devfs > > best, > > svetljo > > PS. > small example > in 00-lsb > --------------- > KERNEL="psaux", SYMLINK="psmouse" > KERNEL="video0", SYMLINK="video" > KERNEL="radio0", SYMLINK="radio" > KERNEL="vbi0", SYMLINK="vbi" > KERNEL="vtx0", SYMLINK="vtx" > ----------------- > in 01-devfs > --------------- > KERNEL="psaux", SYMLINK="misc/%k" > KERNEL="video[0-9]", SYMLINK="v4l/video%n" > KERNEL="radio[0-9]", SYMLINK="v4l/radio%n" > KERNEL="vbi[0-9]", SYMLINK="v4l/vbi%n" > KERNEL="vtx[0-9]", SYMLINK="v4l/vtx%n" --Boundary-00=_r7UFA/hxhIjHrhZ Content-Type: text/x-diff; charset="iso-8859-1"; name="udev014_multi.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="udev014_multi.patch" --- 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); --Boundary-00=_r7UFA/hxhIjHrhZ-- ------------------------------------------------------- The SF.Net email is sponsored by EclipseCon 2004 Premiere Conference on Open Tools Development and Integration See the breadth of Eclipse activity. February 3-5 in Anaheim, CA. http://www.eclipsecon.org/osdn _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel