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).
This commit is contained in:
bde 1995-07-31 00:35:58 +00:00
parent fac592af30
commit 3029c788af
4 changed files with 50 additions and 5 deletions

View File

@ -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);

View File

@ -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 @@ lookup(ndp)
#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 @@ lookup(ndp)
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,11 +462,20 @@ lookup(ndp)
* 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.

View File

@ -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);

View File

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