[CFT] Fix DEVFS aliases in subdirectories.
Justin T. Gibbs
gibbs at scsiguy.com
Fri Jun 10 21:42:09 UTC 2011
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 at n50015b2080006ef9/type at 0/slot at 2/elmdesc at Disk_02/da6 ->
../../../../da6
lrwxr-xr-x 1 root wheel 17 Jun 9 22:44
/dev/enc at n50015b2080006ef9/type at 0/slot at 2/elmdesc at 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
-------------- next part --------------
Change 480877 by justing at 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;
More information about the freebsd-fs
mailing list