4.3BSD-UWisc/src/sys/sys/vfs_pathname.c
/* @(#)vfs_pathname.c 1.1 86/02/03 SMI */
/* NFSSRC @(#)vfs_pathname.c 2.1 86/04/15 */
#include "param.h"
#include "systm.h"
#include "dir.h"
#include "uio.h"
#include "errno.h"
#include "pathname.h"
/*
* Pathname utilities.
*
* In translating file names we copy each argument file
* name into a pathname structure where we operate on it.
* Each pathname structure can hold MAXPATHLEN characters
* including a terminating null, and operations here support
* allocating and freeing pathname structures, fetching
* strings from user space, getting the next character from
* a pathname, combining two pathnames (used in symbolic
* link processing), and peeling off the first component
* of a pathname.
*/
/*
* Allocate contents of pathname structure.
* Structure itself is typically automatic
* variable in calling routine for convenience.
*/
pn_alloc(pnp)
register struct pathname *pnp;
{
pnp->pn_buf = (char *)kmem_alloc((u_int)MAXPATHLEN);
pnp->pn_path = (char *)pnp->pn_buf;
pnp->pn_pathlen = 0;
}
/*
* Pull a pathname from user user or kernel space
*/
int
pn_get(str, seg, pnp)
register struct pathname *pnp;
int seg;
register char *str;
{
u_int clen;
int error;
pn_alloc(pnp);
if (seg == UIO_SYSSPACE)
error = copystr(str, pnp->pn_path, MAXPATHLEN, &clen);
else
error = copyinstr(str, pnp->pn_path, MAXPATHLEN, &clen);
if (error) {
pn_free(pnp);
return (error);
}
pnp->pn_pathlen = clen;
if (clen < MAXPATHLEN)
return (0);
pn_free(pnp);
return (ENAMETOOLONG);
}
#ifdef notneeded
/*
* Get next character from a path.
* Return null at end forever.
*/
pn_getchar(pnp)
register struct pathname *pnp;
{
if (pnp->pn_pathlen == 0)
return (0);
pnp->pn_pathlen--;
return (*pnp->pn_path++);
}
#endif notneeded
/*
* Set pathname to argument string.
*/
pn_set(pnp, path)
register struct pathname *pnp;
register char *path;
{
register char *cp;
extern char *strncpy();
pnp->pn_path = pnp->pn_buf;
cp = strncpy(pnp->pn_path, path, MAXPATHLEN);
pnp->pn_pathlen = cp - pnp->pn_path;
if (pnp->pn_pathlen >= MAXPATHLEN)
return (ENAMETOOLONG);
return (0);
}
/*
* Combine two argument pathnames by putting
* second argument before first in first's buffer,
* and freeing second argument.
* This isn't very general: it is designed specifically
* for symbolic link processing.
*/
pn_combine(pnp, sympnp)
register struct pathname *pnp;
register struct pathname *sympnp;
{
if (pnp->pn_pathlen + sympnp->pn_pathlen >= MAXPATHLEN)
return (ENAMETOOLONG);
ovbcopy(pnp->pn_path, pnp->pn_buf + sympnp->pn_pathlen,
(u_int)pnp->pn_pathlen);
bcopy(sympnp->pn_path, pnp->pn_buf, (u_int)sympnp->pn_pathlen);
pnp->pn_pathlen += sympnp->pn_pathlen;
pnp->pn_path = pnp->pn_buf;
return (0);
}
/*
* Strip next component off a pathname and leave in
* buffer comoponent which should have room for
* MAXNAMLEN bytes and a null terminator character.
*/
pn_getcomponent(pnp, component)
register struct pathname *pnp;
register char *component;
{
register char *cp;
register int l;
register int n;
cp = pnp->pn_path;
l = pnp->pn_pathlen;
n = MAXNAMLEN;
while ((l > 0) && (*cp != '/')) {
if (--n < 0)
return(ENAMETOOLONG);
*component++ = *cp++;
--l;
}
pnp->pn_path = cp;
pnp->pn_pathlen = l;
*component = 0;
return (0);
}
/*
* skip over consecutive slashes in the pathname
*/
void
pn_skipslash(pnp)
register struct pathname *pnp;
{
while ((pnp->pn_pathlen > 0) && (*pnp->pn_path == '/')) {
pnp->pn_path++;
pnp->pn_pathlen--;
}
}
/*
* Free pathname resources.
*/
void
pn_free(pnp)
register struct pathname *pnp;
{
kmem_free((caddr_t)pnp->pn_buf, (u_int)MAXPATHLEN);
pnp->pn_buf = 0;
}