Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Jun 2011 15:09:04 -0600
From:      "Justin T. Gibbs" <gibbs@scsiguy.com>
To:        fs@FreeBSD.org
Subject:   [CFT] Fix DEVFS aliases in subdirectories.
Message-ID:  <4DF287F0.8080301@scsiguy.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
DEVFS aliases don't work correctly when generated symlinks are not
in the DEVFS root.  For example, here's a system that provides aliases
to devices based on their physical path in a SAS enclosure:

ls -l /dev/enc\@n50015b2080006ef9/type\@0/slot\@2/elmdesc\@Disk_02/*

lrwxr-xr-x  1 root  wheel  15 Jun  9 22:44 
/dev/enc@n50015b2080006ef9/type@0/slot@2/elmdesc@Disk_02/da6 -> 
../../../../da6
lrwxr-xr-x  1 root  wheel  17 Jun  9 22:44 
/dev/enc@n50015b2080006ef9/type@0/slot@2/elmdesc@Disk_02/pass7 -> 
../../../../pass7

The aliased devs are far from the root and so must have "../" entries
added in order to function correctly.  I considered making the symlink
paths absolute, but that complicates jail handling.

Are there any objections to the attached change?

Thanks,
Justin


[-- Attachment #2 --]
Change 480877 by justing@justing-ns1 on 2011/03/03 15:48:17

	sys/fs/devfs/devfs_devs.c:
		Correct the devfs alias code to insert the correct number
		of "../"s in the target of a symlink when creating them in
		subdirectories of a devfs.

Affected files ...

... //depot/SpectraBSD/head/sys/fs/devfs/devfs_devs.c#6 edit

Differences ...

==== //depot/SpectraBSD/head/sys/fs/devfs/devfs_devs.c#6 (text) ====

@@ -488,7 +488,7 @@
 	struct devfs_dirent *de;
 	struct devfs_dirent *dd;
 	struct cdev *pdev;
-	int de_flags, j;
+	int de_flags;
 	char *q, *s;
 
 	sx_assert(&dm->dm_lock, SX_XLOCKED);
@@ -584,14 +584,43 @@
 
 		de = devfs_newdirent(s, q - s);
 		if (cdp->cdp_c.si_flags & SI_ALIAS) {
+			char *slash;
+			int depth;
+			int namelen;
+			int buflen;
+			int i;
+
+			/*
+			 * Determine depth of the link.
+			 */
+			slash = cdp->cdp_c.si_name;
+			depth = 0;
+			while ((slash = strchr(slash, '/')) != NULL) {
+				slash++;
+				depth++;
+			}
+
 			de->de_uid = 0;
 			de->de_gid = 0;
 			de->de_mode = 0755;
 			de->de_dirent->d_type = DT_LNK;
 			pdev = cdp->cdp_c.si_parent;
-			j = strlen(pdev->si_name) + 1;
-			de->de_symlink = malloc(j, M_DEVFS, M_WAITOK);
-			bcopy(pdev->si_name, de->de_symlink, j);
+			namelen = strlen(pdev->si_name) + 1;
+			buflen = (depth * 3/* "../" */) + namelen;
+			de->de_symlink = malloc(buflen, M_DEVFS, M_WAITOK);
+
+			/*
+			 * Our parent's path is relative to the root,
+			 * so our symlinked path must be relative to
+			 * the root.
+			 */
+			slash = de->de_symlink;
+			for (i = 0; i < depth; i++) {
+				bcopy("../", slash, 3);
+				slash += 3;
+			}
+
+			bcopy(pdev->si_name, slash, namelen);
 		} else {
 			de->de_uid = cdp->cdp_c.si_uid;
 			de->de_gid = cdp->cdp_c.si_gid;

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4DF287F0.8080301>