Tsort functions and remove a small #if 0 block leftover from earlier cleanup.
No functional change.
This commit is contained in:
parent
857817b9c3
commit
5382c59ae1
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_lookup.c,v 1.130 2011/01/02 05:09:31 dholland Exp $ */
|
||||
/* $NetBSD: vfs_lookup.c,v 1.131 2011/01/04 07:43:42 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.130 2011/01/02 05:09:31 dholland Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.131 2011/01/04 07:43:42 dholland Exp $");
|
||||
|
||||
#include "opt_magiclinks.h"
|
||||
|
||||
@ -193,6 +193,36 @@ symlink_magic(struct proc *p, char *cp, size_t *len)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Determine the namei hash (for cn_hash) for name.
|
||||
* If *ep != NULL, hash from name to ep-1.
|
||||
* If *ep == NULL, hash from name until the first NUL or '/', and
|
||||
* return the location of this termination character in *ep.
|
||||
*
|
||||
* This function returns an equivalent hash to the MI hash32_strn().
|
||||
* The latter isn't used because in the *ep == NULL case, determining
|
||||
* the length of the string to the first NUL or `/' and then calling
|
||||
* hash32_strn() involves unnecessary double-handling of the data.
|
||||
*/
|
||||
uint32_t
|
||||
namei_hash(const char *name, const char **ep)
|
||||
{
|
||||
uint32_t hash;
|
||||
|
||||
hash = HASH32_STR_INIT;
|
||||
if (*ep != NULL) {
|
||||
for (; name < *ep; name++)
|
||||
hash = hash * 33 + *(const uint8_t *)name;
|
||||
} else {
|
||||
for (; *name != '\0' && *name != '/'; name++)
|
||||
hash = hash * 33 + *(const uint8_t *)name;
|
||||
*ep = name;
|
||||
}
|
||||
return (hash + (hash >> 5));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Sealed abstraction for pathnames.
|
||||
*
|
||||
@ -466,11 +496,6 @@ namei_start2(struct namei_state *state)
|
||||
struct cwdinfo *cwdi; /* pointer to cwd state */
|
||||
struct lwp *self = curlwp; /* thread doing namei() */
|
||||
|
||||
#if 0 /* not any more */
|
||||
/* as both buffers are size PATH_MAX this cannot overflow */
|
||||
strcpy(cnp->cn_pnbuf, ndp->ni_pathbuf->pb_path);
|
||||
#endif
|
||||
|
||||
/* length includes null terminator (was originally from copyinstr) */
|
||||
ndp->ni_pathlen = strlen(ndp->ni_pnbuf) + 1;
|
||||
|
||||
@ -664,147 +689,6 @@ namei_follow(struct namei_state *state)
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
static int
|
||||
do_namei(struct namei_state *state)
|
||||
{
|
||||
int error;
|
||||
|
||||
struct nameidata *ndp = state->ndp;
|
||||
struct componentname *cnp = state->cnp;
|
||||
const char *savepath = NULL;
|
||||
|
||||
KASSERT(cnp == &ndp->ni_cnd);
|
||||
|
||||
namei_start1(state);
|
||||
|
||||
if (cnp->cn_flags & TRYEMULROOT) {
|
||||
savepath = pathbuf_stringcopy_get(ndp->ni_pathbuf);
|
||||
}
|
||||
|
||||
emul_retry:
|
||||
|
||||
if (savepath != NULL) {
|
||||
/* kinda gross */
|
||||
strcpy(ndp->ni_pathbuf->pb_path, savepath);
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
savepath = NULL;
|
||||
}
|
||||
|
||||
error = namei_start2(state);
|
||||
if (error) {
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Loop through symbolic links */
|
||||
for (;;) {
|
||||
if (state->namei_startdir->v_mount == NULL) {
|
||||
/* Give up if the directory is no longer mounted */
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
namei_end(state);
|
||||
return (ENOENT);
|
||||
}
|
||||
cnp->cn_nameptr = ndp->ni_pnbuf;
|
||||
error = do_lookup(state, state->namei_startdir);
|
||||
if (error != 0) {
|
||||
/* XXX this should use namei_end() */
|
||||
if (ndp->ni_dvp) {
|
||||
vput(ndp->ni_dvp);
|
||||
}
|
||||
if (ndp->ni_erootdir != NULL) {
|
||||
/* Retry the whole thing from the normal root */
|
||||
cnp->cn_flags &= ~TRYEMULROOT;
|
||||
goto emul_retry;
|
||||
}
|
||||
KASSERT(savepath == NULL);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for symbolic link
|
||||
*/
|
||||
if (namei_atsymlink(state)) {
|
||||
error = namei_follow(state);
|
||||
if (error) {
|
||||
KASSERT(ndp->ni_dvp != ndp->ni_vp);
|
||||
vput(ndp->ni_dvp);
|
||||
vput(ndp->ni_vp);
|
||||
ndp->ni_vp = NULL;
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Done
|
||||
*/
|
||||
|
||||
if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp) {
|
||||
if (ndp->ni_dvp == ndp->ni_vp) {
|
||||
vrele(ndp->ni_dvp);
|
||||
} else {
|
||||
vput(ndp->ni_dvp);
|
||||
}
|
||||
}
|
||||
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
namei(struct nameidata *ndp)
|
||||
{
|
||||
struct namei_state state;
|
||||
int error;
|
||||
|
||||
namei_init(&state, ndp);
|
||||
error = do_namei(&state);
|
||||
namei_cleanup(&state);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the namei hash (for cn_hash) for name.
|
||||
* If *ep != NULL, hash from name to ep-1.
|
||||
* If *ep == NULL, hash from name until the first NUL or '/', and
|
||||
* return the location of this termination character in *ep.
|
||||
*
|
||||
* This function returns an equivalent hash to the MI hash32_strn().
|
||||
* The latter isn't used because in the *ep == NULL case, determining
|
||||
* the length of the string to the first NUL or `/' and then calling
|
||||
* hash32_strn() involves unnecessary double-handling of the data.
|
||||
*/
|
||||
uint32_t
|
||||
namei_hash(const char *name, const char **ep)
|
||||
{
|
||||
uint32_t hash;
|
||||
|
||||
hash = HASH32_STR_INIT;
|
||||
if (*ep != NULL) {
|
||||
for (; name < *ep; name++)
|
||||
hash = hash * 33 + *(const uint8_t *)name;
|
||||
} else {
|
||||
for (; *name != '\0' && *name != '/'; name++)
|
||||
hash = hash * 33 + *(const uint8_t *)name;
|
||||
*ep = name;
|
||||
}
|
||||
return (hash + (hash >> 5));
|
||||
}
|
||||
|
||||
/*
|
||||
* Search a pathname.
|
||||
* This is a very central and rather complicated routine.
|
||||
@ -1298,6 +1182,123 @@ bad:
|
||||
return (error);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
static int
|
||||
do_namei(struct namei_state *state)
|
||||
{
|
||||
int error;
|
||||
|
||||
struct nameidata *ndp = state->ndp;
|
||||
struct componentname *cnp = state->cnp;
|
||||
const char *savepath = NULL;
|
||||
|
||||
KASSERT(cnp == &ndp->ni_cnd);
|
||||
|
||||
namei_start1(state);
|
||||
|
||||
if (cnp->cn_flags & TRYEMULROOT) {
|
||||
savepath = pathbuf_stringcopy_get(ndp->ni_pathbuf);
|
||||
}
|
||||
|
||||
emul_retry:
|
||||
|
||||
if (savepath != NULL) {
|
||||
/* kinda gross */
|
||||
strcpy(ndp->ni_pathbuf->pb_path, savepath);
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
savepath = NULL;
|
||||
}
|
||||
|
||||
error = namei_start2(state);
|
||||
if (error) {
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Loop through symbolic links */
|
||||
for (;;) {
|
||||
if (state->namei_startdir->v_mount == NULL) {
|
||||
/* Give up if the directory is no longer mounted */
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
namei_end(state);
|
||||
return (ENOENT);
|
||||
}
|
||||
cnp->cn_nameptr = ndp->ni_pnbuf;
|
||||
error = do_lookup(state, state->namei_startdir);
|
||||
if (error != 0) {
|
||||
/* XXX this should use namei_end() */
|
||||
if (ndp->ni_dvp) {
|
||||
vput(ndp->ni_dvp);
|
||||
}
|
||||
if (ndp->ni_erootdir != NULL) {
|
||||
/* Retry the whole thing from the normal root */
|
||||
cnp->cn_flags &= ~TRYEMULROOT;
|
||||
goto emul_retry;
|
||||
}
|
||||
KASSERT(savepath == NULL);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for symbolic link
|
||||
*/
|
||||
if (namei_atsymlink(state)) {
|
||||
error = namei_follow(state);
|
||||
if (error) {
|
||||
KASSERT(ndp->ni_dvp != ndp->ni_vp);
|
||||
vput(ndp->ni_dvp);
|
||||
vput(ndp->ni_vp);
|
||||
ndp->ni_vp = NULL;
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Done
|
||||
*/
|
||||
|
||||
if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp) {
|
||||
if (ndp->ni_dvp == ndp->ni_vp) {
|
||||
vrele(ndp->ni_dvp);
|
||||
} else {
|
||||
vput(ndp->ni_dvp);
|
||||
}
|
||||
}
|
||||
|
||||
if (savepath != NULL) {
|
||||
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
namei(struct nameidata *ndp)
|
||||
{
|
||||
struct namei_state state;
|
||||
int error;
|
||||
|
||||
namei_init(&state, ndp);
|
||||
error = do_namei(&state);
|
||||
namei_cleanup(&state);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Externally visible interfaces used by nfsd (bletch, yuk, XXX)
|
||||
*
|
||||
@ -1457,6 +1458,8 @@ lookup_for_nfsd_index(struct nameidata *ndp, struct vnode *startdir)
|
||||
return error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Reacquire a path name component.
|
||||
* dvp is locked on entry and exit.
|
||||
|
Loading…
Reference in New Issue
Block a user