summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_cache.c
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-09-02 22:40:30 +0000
committeriedowse <iedowse@FreeBSD.org>2002-09-02 22:40:30 +0000
commita62f952615101561de134eaa7d3540c250dd2389 (patch)
treedd0ed5506fde41ed7e9eb249ca7fe349ebe49730 /sys/kern/vfs_cache.c
parentd13db8471cf6ad561f341b1446b19a4466740e02 (diff)
downloadFreeBSD-src-a62f952615101561de134eaa7d3540c250dd2389.zip
FreeBSD-src-a62f952615101561de134eaa7d3540c250dd2389.tar.gz
Split up __getcwd so that kernel callers of the internal version
can specify whether the buffer is in user or system space.
Diffstat (limited to 'sys/kern/vfs_cache.c')
-rw-r--r--sys/kern/vfs_cache.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index a8b4dfd..80ea2f0 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -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);
}
OpenPOWER on IntegriCloud