Split up __getcwd so that kernel callers of the internal version

can specify whether the buffer is in user or system space.
This commit is contained in:
iedowse 2002-09-02 22:40:30 +00:00
parent b583870866
commit 70aa04c780
2 changed files with 32 additions and 18 deletions

View File

@ -47,6 +47,7 @@
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
@ -707,7 +708,14 @@ __getcwd(td, uap)
struct thread *td;
struct __getcwd_args *uap;
{
char *bp, *buf;
return (kern___getcwd(td, uap->buf, UIO_USERSPACE, uap->buflen));
}
int
kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg, u_int buflen)
{
char *bp, *tmpbuf;
int error, i, slash_prefixed;
struct filedesc *fdp;
struct namecache *ncp;
@ -716,12 +724,13 @@ __getcwd(td, uap)
numcwdcalls++;
if (disablecwd)
return (ENODEV);
if (uap->buflen < 2)
if (buflen < 2)
return (EINVAL);
if (uap->buflen > MAXPATHLEN)
uap->buflen = MAXPATHLEN;
buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK);
bp += uap->buflen - 1;
if (buflen > MAXPATHLEN)
buflen = MAXPATHLEN;
error = 0;
tmpbuf = bp = malloc(buflen, M_TEMP, M_WAITOK);
bp += buflen - 1;
*bp = '\0';
fdp = td->td_proc->p_fd;
slash_prefixed = 0;
@ -731,7 +740,7 @@ __getcwd(td, uap)
if (vp->v_vflag & VV_ROOT) {
if (vp->v_mount == NULL) { /* forced unmount */
FILEDESC_UNLOCK(fdp);
free(buf, M_TEMP);
free(tmpbuf, M_TEMP);
return (EBADF);
}
vp = vp->v_mount->mnt_vnodecovered;
@ -740,35 +749,35 @@ __getcwd(td, uap)
if (vp->v_dd->v_id != vp->v_ddid) {
FILEDESC_UNLOCK(fdp);
numcwdfail1++;
free(buf, M_TEMP);
free(tmpbuf, M_TEMP);
return (ENOTDIR);
}
ncp = TAILQ_FIRST(&vp->v_cache_dst);
if (!ncp) {
FILEDESC_UNLOCK(fdp);
numcwdfail2++;
free(buf, M_TEMP);
free(tmpbuf, M_TEMP);
return (ENOENT);
}
if (ncp->nc_dvp != vp->v_dd) {
FILEDESC_UNLOCK(fdp);
numcwdfail3++;
free(buf, M_TEMP);
free(tmpbuf, M_TEMP);
return (EBADF);
}
for (i = ncp->nc_nlen - 1; i >= 0; i--) {
if (bp == buf) {
if (bp == tmpbuf) {
FILEDESC_UNLOCK(fdp);
numcwdfail4++;
free(buf, M_TEMP);
free(tmpbuf, M_TEMP);
return (ENOMEM);
}
*--bp = ncp->nc_name[i];
}
if (bp == buf) {
if (bp == tmpbuf) {
FILEDESC_UNLOCK(fdp);
numcwdfail4++;
free(buf, M_TEMP);
free(tmpbuf, M_TEMP);
return (ENOMEM);
}
*--bp = '/';
@ -777,16 +786,19 @@ __getcwd(td, uap)
}
FILEDESC_UNLOCK(fdp);
if (!slash_prefixed) {
if (bp == buf) {
if (bp == tmpbuf) {
numcwdfail4++;
free(buf, M_TEMP);
free(tmpbuf, M_TEMP);
return (ENOMEM);
}
*--bp = '/';
}
numcwdfound++;
error = copyout(bp, uap->buf, strlen(bp) + 1);
free(buf, M_TEMP);
if (bufseg == UIO_SYSSPACE)
bcopy(bp, buf, strlen(bp) + 1);
else
error = copyout(bp, buf, strlen(bp) + 1);
free(tmpbuf, M_TEMP);
return (error);
}

View File

@ -31,6 +31,8 @@
#include <sys/signal.h>
#include <sys/uio.h>
int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
u_int buflen);
int kern_access(struct thread *td, char *path, enum uio_seg pathseg,
int flags);
int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg);