diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 98f427470d9..c76bd5beb00 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -147,6 +147,9 @@ namei(struct nameidata *ndp) cnp->cn_flags &= ~LOCKSHARED; fdp = p->p_fd; + /* We will set this ourselves if we need it. */ + cnp->cn_flags &= ~TRAILINGSLASH; + /* * Get a buffer for the name to be translated, and copy the * name into the buffer. @@ -533,6 +536,7 @@ dirloop: if (*cp == '\0') { trailing_slash = 1; *ndp->ni_next = '\0'; /* XXX for direnter() ... */ + cnp->cn_flags |= TRAILINGSLASH; } } ndp->ni_next = cp; @@ -807,14 +811,6 @@ unionlookup: goto success; } - /* - * Check for bogus trailing slashes. - */ - if (trailing_slash && dp->v_type != VDIR) { - error = ENOTDIR; - goto bad2; - } - nextname: /* * Not a symbolic link. If more pathname, @@ -837,6 +833,14 @@ nextname: vfslocked = 0; goto dirloop; } + /* + * If we're processing a path with a trailing slash, + * check that the end result is a directory. + */ + if ((cnp->cn_flags & TRAILINGSLASH) && dp->v_type != VDIR) { + error = ENOTDIR; + goto bad2; + } /* * Disallow directory write attempts on read-only filesystems. */ diff --git a/sys/sys/namei.h b/sys/sys/namei.h index efd0ac40653..f8bfcc54033 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -142,7 +142,8 @@ struct nameidata { #define GIANTHELD 0x02000000 /* namei() is holding giant. */ #define AUDITVNODE1 0x04000000 /* audit the looked up vnode information */ #define AUDITVNODE2 0x08000000 /* audit the looked up vnode information */ -#define PARAMASK 0x0ffffe00 /* mask of parameter descriptors */ +#define TRAILINGSLASH 0x10000000 /* path ended in a slash */ +#define PARAMASK 0x1ffffe00 /* mask of parameter descriptors */ #define NDHASGIANT(NDP) (((NDP)->ni_cnd.cn_flags & GIANTHELD) != 0)