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:
Ian Dowse 2002-09-02 22:40:30 +00:00
parent f2893bd9ef
commit 48b52b7a32
2 changed files with 32 additions and 18 deletions

View File

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

View File

@ -31,6 +31,8 @@
#include <sys/signal.h> #include <sys/signal.h>
#include <sys/uio.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 kern_access(struct thread *td, char *path, enum uio_seg pathseg,
int flags); int flags);
int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg); int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg);