diff options
author | bde <bde@FreeBSD.org> | 1995-07-31 00:35:58 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1995-07-31 00:35:58 +0000 |
commit | 3029c788afe81119f71a3c3a7ae9ca00014428a0 (patch) | |
tree | cbc95c828f2184fdca42bfb97779d4a57b8869a1 /sys | |
parent | fac592af30d777142d6c647a97be7af2f5a73dcb (diff) | |
download | FreeBSD-src-3029c788afe81119f71a3c3a7ae9ca00014428a0.zip FreeBSD-src-3029c788afe81119f71a3c3a7ae9ca00014428a0.tar.gz |
Ignore trailing slashes in pathnames that "refer to a directory",
as is required to be POSIXLY_CORRECT and "right". I interpret
"referring to a directory" as being a directory or becoming a
directory. E.g., the trailing slashes in mkdir("/nonesuch/"),
rename("/tmp", /nonesuch/") and link("/tmp", "/root_can_like_dirs/")
are ignored because the target will become a directory if the
syscall succeeds. A trailing slash on a symlink causes the symlink
to be followed (this is a bug if the symlink doesn't point to a
directory; fix later).
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/vfs_extattr.c | 7 | ||||
-rw-r--r-- | sys/kern/vfs_lookup.c | 38 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 7 | ||||
-rw-r--r-- | sys/sys/namei.h | 3 |
4 files changed, 50 insertions, 5 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 401828a..c9f62ab 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.27 1995/06/28 12:00:57 davidg Exp $ + * $Id: vfs_syscalls.c,v 1.28 1995/07/13 08:47:42 davidg Exp $ */ #include <sys/param.h> @@ -834,6 +834,8 @@ link(p, uap, retval) (error = suser(p->p_ucred, &p->p_acflag)) == 0) { nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; + if (vp->v_type == VDIR) + nd.ni_cnd.cn_flags |= WILLBEDIR; nd.ni_dirp = uap->link; error = namei(&nd); if (!error) { @@ -1819,6 +1821,8 @@ rename(p, uap, retval) fvp = fromnd.ni_vp; NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, UIO_USERSPACE, uap->to, p); + if (fromnd.ni_vp->v_type == VDIR) + tond.ni_cnd.cn_flags |= WILLBEDIR; error = namei(&tond); if (error) { VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); @@ -1904,6 +1908,7 @@ mkdir(p, uap, retval) struct nameidata nd; NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); + nd.ni_cnd.cn_flags |= WILLBEDIR; error = namei(&nd); if (error) return (error); diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index b25745c..e3c7654 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_lookup.c 8.4 (Berkeley) 2/16/94 - * $Id: vfs_lookup.c,v 1.6 1994/10/06 21:06:36 davidg Exp $ + * $Id: vfs_lookup.c,v 1.7 1995/05/30 08:06:33 rgrimes Exp $ */ #include <sys/param.h> @@ -257,6 +257,7 @@ lookup(ndp) int docache; /* == 0 do not cache last component */ int wantparent; /* 1 => wantparent or lockparent flag */ int rdonly; /* lookup read-only flag bit */ + int trailing_slash; int error = 0; struct componentname *cnp = &ndp->ni_cnd; @@ -302,6 +303,25 @@ dirloop: #endif ndp->ni_pathlen -= cnp->cn_namelen; ndp->ni_next = cp; + + /* + * Replace multiple slashes by a single slash and trailing slashes + * by a null. This must be done before VOP_LOOKUP() because some + * fs's don't know about trailing slashes. Remember if there were + * trailing slashes to handle symlinks, existing non-directories + * and non-existing files that won't be directories specially later. + */ + trailing_slash = 0; + while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) { + cp++; + ndp->ni_pathlen--; + if (*cp == '\0') { + trailing_slash = 1; + *ndp->ni_next = '\0'; /* XXX for direnter() ... */ + } + } + ndp->ni_next = cp; + cnp->cn_flags |= MAKEENTRY; if (*cp == '\0' && docache == 0) cnp->cn_flags &= ~MAKEENTRY; @@ -406,6 +426,11 @@ unionlookup: error = EROFS; goto bad; } + if (*cp == '\0' && trailing_slash && + !(cnp->cn_flags & WILLBEDIR)) { + error = ENOENT; + goto bad; + } /* * We return with ni_vp NULL to indicate that the entry * doesn't currently exist, leaving a pointer to the @@ -437,12 +462,21 @@ unionlookup: * Check for symbolic link */ if ((dp->v_type == VLNK) && - ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) { + ((cnp->cn_flags & FOLLOW) || trailing_slash || + *ndp->ni_next == '/')) { cnp->cn_flags |= ISSYMLINK; return (0); } /* + * Check for bogus trailing slashes. + */ + if (trailing_slash && dp->v_type != VDIR) { + error = ENOTDIR; + goto bad2; + } + + /* * Check to see if the vnode has been mounted on; * if so find the root of the mounted file system. */ diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 401828a..c9f62ab 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.27 1995/06/28 12:00:57 davidg Exp $ + * $Id: vfs_syscalls.c,v 1.28 1995/07/13 08:47:42 davidg Exp $ */ #include <sys/param.h> @@ -834,6 +834,8 @@ link(p, uap, retval) (error = suser(p->p_ucred, &p->p_acflag)) == 0) { nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; + if (vp->v_type == VDIR) + nd.ni_cnd.cn_flags |= WILLBEDIR; nd.ni_dirp = uap->link; error = namei(&nd); if (!error) { @@ -1819,6 +1821,8 @@ rename(p, uap, retval) fvp = fromnd.ni_vp; NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, UIO_USERSPACE, uap->to, p); + if (fromnd.ni_vp->v_type == VDIR) + tond.ni_cnd.cn_flags |= WILLBEDIR; error = namei(&tond); if (error) { VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); @@ -1904,6 +1908,7 @@ mkdir(p, uap, retval) struct nameidata nd; NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); + nd.ni_cnd.cn_flags |= WILLBEDIR; error = namei(&nd); if (error) return (error); diff --git a/sys/sys/namei.h b/sys/sys/namei.h index bd15fe2..fcd48ce 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)namei.h 8.2 (Berkeley) 1/4/94 - * $Id: namei.h,v 1.5 1995/03/09 20:27:21 phk Exp $ + * $Id: namei.h,v 1.6 1995/07/29 11:42:49 bde Exp $ */ #ifndef _SYS_NAMEI_H_ @@ -134,6 +134,7 @@ struct nameidata { #define MAKEENTRY 0x04000 /* entry is to be added to name cache */ #define ISLASTCN 0x08000 /* this is last component of pathname */ #define ISSYMLINK 0x10000 /* symlink needs interpretation */ +#define WILLBEDIR 0x20000 /* new files will be dirs; allow trailing / */ #define PARAMASK 0xfff00 /* mask of parameter descriptors */ /* * Initialization of an nameidata structure. |