# HG changeset patch # Parent ce9001c93fecb58f58492e4023a71fec6466a37a Adjust namei internals to be able to make an external call to parse the pathname. (Basically, this means change the signature of namei_getcomponent() to pass in the directory vnode and to allow failures.) diff -r ce9001c93fec sys/kern/vfs_lookup.c --- a/sys/kern/vfs_lookup.c Tue Apr 12 00:03:06 2016 -0400 +++ b/sys/kern/vfs_lookup.c Sun Apr 17 01:11:16 2016 -0400 @@ -228,16 +228,19 @@ * Find the end of the first path component in NAME and return its * length. */ -static size_t -namei_getcomponent(const char *name) +static int +namei_getcomponent(struct vnode *dvp, const char *name, size_t *ret) { size_t pos; + (void)dvp; + pos = 0; while (name[pos] != '\0' && name[pos] != '/') { pos++; } - return pos; + *ret = pos; + return 0; } //////////////////////////////////////////////////////////// @@ -816,9 +819,10 @@ * Inspect the leading path component and update the state accordingly. */ static int -lookup_parsepath(struct namei_state *state) +lookup_parsepath(struct namei_state *state, struct vnode *searchdir) { const char *cp; /* pointer into pathname argument */ + int error; struct componentname *cnp = state->cnp; struct nameidata *ndp = state->ndp; @@ -837,7 +841,11 @@ * is held and locked. */ cnp->cn_consume = 0; - cnp->cn_namelen = namei_getcomponent(cnp->cn_nameptr); + error = namei_getcomponent(searchdir, cnp->cn_nameptr, + &cnp->cn_namelen); + if (error) { + return error; + } cp = cnp->cn_nameptr + cnp->cn_namelen; if (cnp->cn_namelen > KERNEL_NAME_MAX) { return ENAMETOOLONG; @@ -1222,7 +1230,7 @@ /* and we shouldn't have looped around if we were done */ KASSERT(cnp->cn_nameptr[0] != '\0'); - error = lookup_parsepath(state); + error = lookup_parsepath(state, searchdir); if (error) { vput(searchdir); ndp->ni_dvp = NULL; @@ -1618,7 +1626,7 @@ static int do_lookup_for_nfsd_index(struct namei_state *state) { - int error = 0; + int error; struct componentname *cnp = state->cnp; struct nameidata *ndp = state->ndp; @@ -1636,7 +1644,12 @@ ndp->ni_dvp = NULL; cnp->cn_consume = 0; - cnp->cn_namelen = namei_getcomponent(cnp->cn_nameptr); + error = namei_getcomponent(startdir, cnp->cn_nameptr, + &cnp->cn_namelen); + if (error) { + return error; + } + cp = cnp->cn_nameptr + cnp->cn_namelen; KASSERT(cnp->cn_namelen <= KERNEL_NAME_MAX); ndp->ni_pathlen -= cnp->cn_namelen; @@ -1760,7 +1773,10 @@ if ((uint32_t)newhash != (uint32_t)cnp->cn_hash) panic("relookup: bad hash"); #endif - newlen = namei_getcomponent(cnp->cn_nameptr); + error = namei_getcomponent(dvp, cnp->cn_nameptr, &newlen); + if (error) { + panic("relookup: parsepath failed with error %d", error); + } if (cnp->cn_namelen != newlen) panic("relookup: bad len"); cp = cnp->cn_nameptr + cnp->cn_namelen;