[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-hotplug
Subject:    Re: [PATCH] multple rules files support/symlink rules support
From:       Andrey Borzenkov <arvidjaar () mail ! ru>
Date:       2004-01-26 17:31:23
Message-ID: 200401262031.24064.arvidjaar () mail ! ru
[Download RAW message or body]

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"

["udev014_multi.patch" (text/x-diff)]

--- 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 <ctype.h>
 #include <unistd.h>
 #include <errno.h>
+#include <dirent.h>
+#include <sys/stat.h>
 
 #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);

-------------------------------------------------------
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

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic