linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: [udev] experimental (very simple) SYMLINK creation
Date: Fri, 05 Dec 2003 15:45:28 +0000	[thread overview]
Message-ID: <marc-linux-hotplug-107063917327231@msgid-missing> (raw)
In-Reply-To: <marc-linux-hotplug-107060923531865@msgid-missing>

[-- Attachment #1: Type: text/plain, Size: 773 bytes --]

On Fri, Dec 05, 2003 at 05:24:33AM +0100, Kay Sievers wrote:
> here is a experimental symlink creation patch - for discussion,
> in which direction we should go.
> It is possible now to define SYMLINK= after the NAME= in udev.rules.
> The link is relative to the node, but the path is not optimized now
> if the node and the link are in the same nested directory.
> Only one link is supported, cause i need to sleep now :)
> 
> 06-simple-symlink-creation.diff
>   simple symlink creation
>   reorganized udev-remove to have access to the symlink field
>   subdir creation/removal are functions now
>   udev-test.pl tests for link creation/removal

Eeh, the copy-paste-devil removed one of the tests from udev-test.pl and one comment :)
So here is a new patch.

thanks,
Kay

[-- Attachment #2: 06-simple-symlink-creation.diff --]
[-- Type: text/plain, Size: 11758 bytes --]

diff -Nru a/namedev.c b/namedev.c
--- a/namedev.c	Fri Dec  5 16:38:27 2003
+++ b/namedev.c	Fri Dec  5 16:38:27 2003
@@ -121,6 +121,7 @@
 		copy_string(dev, new_dev, place);
 		copy_string(dev, new_dev, kernel_name);
 		copy_string(dev, new_dev, exec_program);
+		copy_string(dev, new_dev, symlink);
 		return 0;
 	}
 
@@ -366,6 +367,7 @@
 		if (strcmp_pattern(dev->id, udev->callout_value) != 0)
 			continue;
 		strfieldcpy(udev->name, dev->name);
+		strfieldcpy(udev->symlink, dev->symlink);
 		dbg("callout returned matching value '%s', '%s' becomes '%s'",
 		    dev->id, class_dev->name, udev->name);
 		return 0;
@@ -416,6 +418,7 @@
 			continue;
 
 		strfieldcpy(udev->name, dev->name);
+		strfieldcpy(udev->symlink, dev->symlink);
 		dbg("found matching attribute '%s', '%s' becomes '%s' ",
 		    dev->sysfs_file, class_dev->name, udev->name);
 
@@ -461,6 +464,7 @@
 		if (!found)
 			continue;
 		strfieldcpy(udev->name, dev->name);
+		strfieldcpy(udev->symlink, dev->symlink);
 		dbg("found matching id '%s', '%s' becomes '%s'",
 		    dev->id, class_dev->name, udev->name);
 		return 0;
@@ -506,6 +510,7 @@
 			continue;
 
 		strfieldcpy(udev->name, dev->name);
+		strfieldcpy(udev->symlink, dev->symlink);
 		dbg("found matching place '%s', '%s' becomes '%s'",
 		    dev->place, class_dev->name, udev->name);
 		return 0;
@@ -528,6 +533,7 @@
 			continue;
 
 		strfieldcpy(udev->name, dev->name);
+		strfieldcpy(udev->symlink, dev->symlink);
 		dbg("found name, '%s' becomes '%s'", dev->kernel_name, udev->name);
 		
 		return 0;
@@ -618,8 +624,9 @@
 	goto done;
 
 found:
-	/* substitute placeholder in NAME  */
+	/* substitute placeholder */
 	apply_format(udev, udev->name);
+	apply_format(udev, udev->symlink);
 
 done:
 	perm = find_perm(udev->name);
diff -Nru a/namedev.h b/namedev.h
--- a/namedev.h	Fri Dec  5 16:38:27 2003
+++ b/namedev.h	Fri Dec  5 16:38:27 2003
@@ -63,6 +63,7 @@
 	char kernel_name[NAME_SIZE];
 	char exec_program[FILE_SIZE];
 	char name[NAME_SIZE];
+	char symlink[NAME_SIZE];
 };
 
 struct perm_device {
diff -Nru a/namedev_parse.c b/namedev_parse.c
--- a/namedev_parse.c	Fri Dec  5 16:38:27 2003
+++ b/namedev_parse.c	Fri Dec  5 16:38:27 2003
@@ -291,9 +291,11 @@
 			if (retval)
 				break;
 			strfieldcpy(dev.name, temp3);
+
 			dbg_parse("REPLACE name='%s', kernel_name='%s'",
 				  dev.name, dev.kernel_name);
 		}
+
 		if (strcasecmp(temp2, TYPE_CALLOUT) == 0) {
 			/* number type */
 			dev.type = CALLOUT;
@@ -324,10 +326,17 @@
 			if (retval)
 				break;
 			strfieldcpy(dev.name, temp3);
+
 			dbg_parse("CALLOUT name='%s', program='%s'",
 				  dev.name, dev.exec_program);
 		}
 
+		/* SYMLINK="name" */
+		temp2 = strsep(&temp, ",");
+		retval = get_value("SYMLINK", &temp, &temp3);
+		if (retval == 0)
+			strfieldcpy(dev.symlink, temp3);
+
 		retval = add_config_dev(&dev);
 		if (retval) {
 			dbg("add_config_dev returned with error %d", retval);
@@ -414,7 +423,7 @@
 			  dev.mode);
 		retval = add_perm_dev(&dev);
 		if (retval) {
-			dbg("add_config_dev returned with error %d", retval);
+			dbg("add_perm_dev returned with error %d", retval);
 			goto exit;
 		}
 	}
diff -Nru a/test/udev-test.pl b/test/udev-test.pl
--- a/test/udev-test.pl	Fri Dec  5 16:38:27 2003
+++ b/test/udev-test.pl	Fri Dec  5 16:38:27 2003
@@ -39,7 +39,7 @@
 		expected => "boot_disk" ,
 		conf     => <<EOF
 LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n"
-REPLACE, KERNEL="ttyUSB0", NAME="visor""
+REPLACE, KERNEL="ttyUSB0", NAME="visor"
 EOF
 	},
 	{
@@ -181,6 +181,33 @@
 CALLOUT, BUS="foo", PROGRAM="/bin/echo -n foo-%b", ID="*", NAME="%c"
 EOF
 	},
+	{
+		desc     => "symlink creation (node)",
+		subsys   => "tty",
+		devpath  => "class/tty/ttyUSB0",
+		expected => "ttyUSB0" ,
+		conf     => <<EOF
+REPLACE, KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="tts/USB%n"
+EOF
+	},
+	{
+		desc     => "symlink creation (link)",
+		subsys   => "tty",
+		devpath  => "class/tty/ttyUSB0",
+		expected => "tts/USB0" ,
+		conf     => <<EOF
+REPLACE, KERNEL="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="tts/USB%n"
+EOF
+	},
+	{
+		desc     => "symlink creation (link)",
+		subsys   => "block",
+		devpath  => "block/sda/sda2",
+		expected => "my/own/link2" ,
+		conf     => <<EOF
+LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="lun0/%D", SYMLINK="my/own/link%n"
+EOF
+	},
 );
 
 # set env
@@ -238,7 +265,8 @@
 	}
 
 	udev("remove", $config->{subsys}, $config->{devpath}, \$config->{conf});
-	if (-e "$PWD/$udev_root$config->{expected}") {
+	if ((-e "$PWD/$udev_root$config->{expected}") ||
+	    (-l "$PWD/$udev_root$config->{expected}")) {
 		print "remove: error\n\n";
 		system("tree $udev_root");
 		$error++;
diff -Nru a/udev-add.c b/udev-add.c
--- a/udev-add.c	Fri Dec  5 16:38:27 2003
+++ b/udev-add.c	Fri Dec  5 16:38:27 2003
@@ -72,6 +72,34 @@
 	return retval;
 }
 
+static int create_path(char *file)
+{
+	char p[NAME_SIZE];
+	char *pos;
+	int retval;
+	struct stat stats;
+	
+	strncpy(p, file, sizeof(p));
+	pos = strchr(p+1, '/');
+	while (1) {
+		pos = strchr(pos+1, '/');
+		if (pos == NULL)
+			break;
+		*pos = 0x00;
+		if (stat(p, &stats)) {
+			retval = mkdir(p, 0755);
+			if (retval) {
+				dbg("mkdir(%s) failed with error '%s'",
+				    p, strerror(errno));
+				return retval;
+			}
+			dbg("created '%s'", p);
+		}
+		*pos = '/';
+	}
+	return 0;
+}
+
 /*
  * we possibly want to add some symlinks here
  * only numeric owner/group id's are supported
@@ -79,10 +107,12 @@
 static int create_node(struct udevice *dev)
 {
 	char filename[255];
+	char linkname[255];
 	int retval = 0;
 	uid_t uid = 0;
 	gid_t gid = 0;
 	dev_t res;
+	char *pos;
 
 	strncpy(filename, udev_root, sizeof(filename));
 	strncat(filename, dev->name, sizeof(filename));
@@ -109,31 +139,9 @@
 		return -EINVAL;
 	}
 
-	/* create subdirectories if requested */
-	if (strchr(dev->name, '/')) {
-		char path[255];
-		char *pos;
-		struct stat stats;
-
-		strncpy(path, filename, sizeof(path));
-		pos = strchr(path+1, '/');
-		while (1) {
-			pos = strchr(pos+1, '/');
-			if (pos == NULL)
-				break;
-			*pos = 0x00;
-			if (stat(path, &stats)) {
-				retval = mkdir(path, 0755);
-				if (retval) {
-					dbg("mkdir(%s) failed with error '%s'",
-					    path, strerror(errno));
-					return retval;
-				}
-				dbg("created '%s'", path);
-			}
-			*pos = '/';
-		}
-	}
+	/* create parent directories if needed */
+	if (strrchr(dev->name, '/'))
+		create_path(filename);
 
 	dbg("mknod(%s, %#o, %u, %u)", filename, dev->mode, dev->major, dev->minor);
 	retval = mknod(filename, dev->mode, res);
@@ -179,8 +187,36 @@
 		dbg("chown(%s, %u, %u)", filename, uid, gid);
 		retval = chown(filename, uid, gid);
 		if (retval)
-			dbg("chown(%s, %u, %u) failed with error '%s'", filename,
-			    uid, gid, strerror(errno));
+			dbg("chown(%s, %u, %u) failed with error '%s'",
+			    filename, uid, gid, strerror(errno));
+	}
+
+
+	/* create symlink if requested */
+	if (*dev->symlink) {
+		strncpy(linkname, udev_root, sizeof(linkname));
+		strncat(linkname, dev->symlink, sizeof(linkname));
+		pos = strchr(dev->symlink, '/');
+		if (pos) {
+			create_path(linkname);
+			strcpy(filename, "../");
+			while (1) {
+				pos = strchr(pos+1, '/');
+				if (pos == NULL)
+					break;
+				strcat(filename, "../");
+			}
+		} else {
+			strcpy(filename, "./");
+		}
+		strncat(filename, dev->name, sizeof(filename));
+
+		dbg("symlink(%s, %s)", filename, linkname);
+
+		retval = symlink(filename, linkname);
+		if (retval)
+			dbg("symlink(%s, %s) failed with error '%s'",
+			    filename, linkname, strerror(errno));
 	}
 
 	return retval;
diff -Nru a/udev-remove.c b/udev-remove.c
--- a/udev-remove.c	Fri Dec  5 16:38:27 2003
+++ b/udev-remove.c	Fri Dec  5 16:38:27 2003
@@ -34,47 +34,43 @@
 #include "udevdb.h"
 #include "libsysfs/libsysfs.h"
 
-
-/*
- * Look up the sysfs path in the database to see if we have named this device
- * something different from the kernel name.  If we have, us it.  If not, use
- * the default kernel name for lack of anything else to know to do.
- */
-static char *get_name(char *path, int major, int minor)
+static int delete_path(char *path)
 {
-	static char name[100];
-	struct udevice *dev;
-	char *temp;
+	char *pos;
+	int retval;
 
-	dev = udevdb_get_dev(path);
-	if (dev != NULL) {
-		strcpy(name, dev->name);
-		goto exit;
+	pos = strrchr(path, '/');
+	while (1) {
+		*pos = '\0';
+		pos = strrchr(path, '/');
+
+		/* don't remove the last one */
+		if ((pos == path) || (pos == NULL))
+			break;
+
+		/* remove if empty */
+		retval = rmdir(path);
+		if (retval) {
+			if (errno == ENOTEMPTY)
+				return 0;
+			dbg("rmdir(%s) failed with error '%s'",
+			    path, strerror(errno));
+			break;
+		}
+		dbg("removed '%s'", path);
 	}
-
-	dbg("'%s' not found in database, falling back on default name", path);
-	temp = strrchr(path, '/');
-	if (temp == NULL)
-		return NULL;
-	strncpy(name, &temp[1], sizeof(name));
-
-exit:
-	dbg("name is '%s'", name);
-	return &name[0];
+	return 0;
 }
 
-/*
- * We also want to clean up any symlinks that were created in create_node()
- */
-static int delete_node(char *name)
+static int delete_node(struct udevice *dev)
 {
 	char filename[255];
 	int retval;
 
 	strncpy(filename, udev_root, sizeof(filename));
-	strncat(filename, name, sizeof(filename));
+	strncat(filename, dev->name, sizeof(filename));
 
-	dbg("unlinking '%s'", filename);
+	dbg("unlinking node '%s'", filename);
 	retval = unlink(filename);
 	if (retval) {
 		dbg("unlink(%s) failed with error '%s'",
@@ -83,49 +79,48 @@
 	}
 
 	/* remove subdirectories */
-	if (strchr(name, '/')) {
-		char *pos;
+	if (strchr(dev->name, '/'))
+		delete_path(filename);
 
-		pos = strrchr(filename, '/');
-		while (1) {
-			*pos = 0x00;
-			pos = strrchr(filename, '/');
-
-			/* don't remove the last one */
-			if ((pos == filename) || (pos == NULL))
-				break;
-
-			/* remove if empty */
-			retval = rmdir(filename);
-			if (retval) {
-				if (errno == ENOTEMPTY)
-					return 0;
-				dbg("rmdir(%s) failed with error '%s'",
-				    filename, strerror(errno));
-				break;
-			}
-			dbg("removed '%s'", filename);
+	if (*dev->symlink) {
+		strncpy(filename, udev_root, sizeof(filename));
+		strncat(filename, dev->symlink, sizeof(filename));
+		dbg("unlinking symlink '%s'", filename);
+		retval = unlink(filename);
+		if (retval) {
+			dbg("unlink(%s) failed with error '%s'",
+				filename, strerror(errno));
+			return retval;
+		}
+		if (strchr(dev->symlink, '/')) {
+			delete_path(filename);
 		}
 	}
+
 	return retval;
 }
 
-int udev_remove_device(char *device, char *subsystem)
+/*
+ * Look up the sysfs path in the database to see if we have named this device
+ * something different from the kernel name.  If we have, us it.  If not, use
+ * the default kernel name for lack of anything else to know to do.
+ */
+int udev_remove_device(char *path, char *subsystem)
 {
-	char *name;
-	int retval = 0;
+	char name[100];
+	struct udevice *dev;
+	char *temp;
 
-	name = get_name(device, 0, 0);
-	if (name == NULL) {
-		dbg ("get_name failed");
-		retval = -ENODEV;
-		goto exit;
+	dev = udevdb_get_dev(path);
+	if (dev == NULL) {
+		dbg("'%s' not found in database, falling back on default name", path);
+		temp = strrchr(path, '/');
+		if (temp == NULL)
+			return -ENODEV;
+		strncpy(name, &temp[1], sizeof(name));
 	}
 
-	udevdb_delete_dev(device);
-
-	return delete_node(name);
-
-exit:
-	return retval;
+	dbg("name is '%s'", dev->name);
+	udevdb_delete_dev(path);
+	return delete_node(dev);
 }
diff -Nru a/udev.h b/udev.h
--- a/udev.h	Fri Dec  5 16:38:27 2003
+++ b/udev.h	Fri Dec  5 16:38:27 2003
@@ -64,6 +64,7 @@
 	int major;
 	int minor;
 	mode_t mode;
+	char symlink[NAME_SIZE];
 
 	/* fields that help us in building strings */
 	unsigned char bus_id[SYSFS_NAME_LEN];

  reply	other threads:[~2003-12-05 15:45 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-12-05  7:26 [udev] experimental (very simple) SYMLINK creation Olaf Hering
2003-12-05 15:45 ` Kay Sievers [this message]
2003-12-07  6:02 ` Kay Sievers
2003-12-07 17:45 ` Kay Sievers
2003-12-07 17:58 ` Marco d'Itri
2003-12-10  0:43 ` Greg KH
2003-12-10  1:06 ` Greg KH
  -- strict thread matches above, loose matches on Subject: below --
2003-12-05  4:24 Kay Sievers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=marc-linux-hotplug-107063917327231@msgid-missing \
    --to=kay.sievers@vrfy.org \
    --cc=linux-hotplug@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).