Index: emulation/linux/linux_file.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/linux_file.c,v
retrieving revision 1.13
diff -u -u -r1.13 linux_file.c
--- emulation/linux/linux_file.c	10 Nov 2003 20:57:16 -0000	1.13
+++ emulation/linux/linux_file.c	12 Nov 2003 01:54:46 -0000
@@ -42,6 +42,7 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mount.h>
+#include <sys/namei.h>
 #include <sys/proc.h>
 #include <sys/sysproto.h>
 #include <sys/tty.h>
@@ -60,123 +61,119 @@
 int
 linux_creat(struct linux_creat_args *args)
 {
-    struct open_args bsd_open_args;
-    caddr_t sg;
-    int error;
-
-    sg = stackgap_init();
-    CHECKALTCREAT(&sg, args->path);
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
+	int error;
 
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(creat))
-		printf(ARGS(creat, "%s, %d"), args->path, args->mode);
+		printf(ARGS(creat, "%s, %d"), path, args->mode);
 #endif
-    bsd_open_args.sysmsg_result = 0;
-    bsd_open_args.path = args->path;
-    bsd_open_args.mode = args->mode;
-    bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
-    error = open(&bsd_open_args);
-    args->sysmsg_result = bsd_open_args.sysmsg_result;
-    return(error);
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
+
+	error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC, args->mode,
+	    &args->sysmsg_result);
+
+	linux_free_path(&path);
+	return(error);
 }
 #endif /*!__alpha__*/
 
 int
 linux_open(struct linux_open_args *args)
 {
-    struct open_args bsd_open_args;
-    int error;
-    caddr_t sg;
-    struct thread *td = curthread;
-    struct proc *p = td->td_proc;
-
-    KKASSERT(p);
-
-    sg = stackgap_init();
-    
-    if (args->flags & LINUX_O_CREAT)
-	CHECKALTCREAT(&sg, args->path);
-    else
-	CHECKALTEXIST(&sg, args->path);
+	struct thread *td = curthread;
+	struct proc *p = td->td_proc;
+	struct nameidata nd;
+	char *path;
+	int error, flags;
+
+	KKASSERT(p);
+
+	if (args->flags & LINUX_O_CREAT) {
+		error = linux_copyin_path(args->path, &path,
+		    LINUX_PATH_CREATE);
+	} else {
+		error = linux_copyin_path(args->path, &path,
+		    LINUX_PATH_EXISTS);
+	}
+	if (error)
+		return (error);
 
 #ifdef DEBUG
 	if (ldebug(open))
-		printf(ARGS(open, "%s, 0x%x, 0x%x"),
-		    args->path, args->flags, args->mode);
+		printf(ARGS(open, "%s, 0x%x, 0x%x"), path, args->flags,
+		    args->mode);
 #endif
-    bsd_open_args.flags = 0;
-    if (args->flags & LINUX_O_RDONLY)
-	bsd_open_args.flags |= O_RDONLY;
-    if (args->flags & LINUX_O_WRONLY) 
-	bsd_open_args.flags |= O_WRONLY;
-    if (args->flags & LINUX_O_RDWR)
-	bsd_open_args.flags |= O_RDWR;
-    if (args->flags & LINUX_O_NDELAY)
-	bsd_open_args.flags |= O_NONBLOCK;
-    if (args->flags & LINUX_O_APPEND)
-	bsd_open_args.flags |= O_APPEND;
-    if (args->flags & LINUX_O_SYNC)
-	bsd_open_args.flags |= O_FSYNC;
-    if (args->flags & LINUX_O_NONBLOCK)
-	bsd_open_args.flags |= O_NONBLOCK;
-    if (args->flags & LINUX_FASYNC)
-	bsd_open_args.flags |= O_ASYNC;
-    if (args->flags & LINUX_O_CREAT)
-	bsd_open_args.flags |= O_CREAT;
-    if (args->flags & LINUX_O_TRUNC)
-	bsd_open_args.flags |= O_TRUNC;
-    if (args->flags & LINUX_O_EXCL)
-	bsd_open_args.flags |= O_EXCL;
-    if (args->flags & LINUX_O_NOCTTY)
-	bsd_open_args.flags |= O_NOCTTY;
-    bsd_open_args.path = args->path;
-    bsd_open_args.mode = args->mode;
-    bsd_open_args.sysmsg_result = 0;
-    error = open(&bsd_open_args);
-    args->sysmsg_result = bsd_open_args.sysmsg_result;
-
-    if (!error && !(bsd_open_args.flags & O_NOCTTY) && 
-	SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
-	struct filedesc *fdp = p->p_fd;
-	struct file *fp = fdp->fd_ofiles[bsd_open_args.sysmsg_result];
+	flags = 0;
+	if (args->flags & LINUX_O_RDONLY)
+		flags |= O_RDONLY;
+	if (args->flags & LINUX_O_RDWR)
+		flags |= O_RDWR;
+	if (args->flags & LINUX_O_NDELAY)
+		flags |= O_NONBLOCK;
+	if (args->flags & LINUX_O_APPEND)
+		flags |= O_APPEND;
+	if (args->flags & LINUX_O_SYNC)
+		flags |= O_FSYNC;
+	if (args->flags & LINUX_O_NONBLOCK)
+		flags |= O_NONBLOCK;
+	if (args->flags & LINUX_FASYNC)
+		flags |= O_ASYNC;
+	if (args->flags & LINUX_O_CREAT)
+		flags |= O_CREAT;
+	if (args->flags & LINUX_O_TRUNC)
+		flags |= O_TRUNC;
+	if (args->flags & LINUX_O_EXCL)
+		flags |= O_EXCL;
+	if (args->flags & LINUX_O_NOCTTY)
+		flags |= O_NOCTTY;
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
+
+	error = kern_open(&nd, flags, args->mode, &args->sysmsg_result);
+
+	if (error == 0 && !(flags & O_NOCTTY) && 
+		SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+		struct filedesc *fdp = p->p_fd;
+		struct file *fp = fdp->fd_ofiles[args->sysmsg_result];
 
-	if (fp->f_type == DTYPE_VNODE)
-	    fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
+		if (fp->f_type == DTYPE_VNODE)
+			fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
     }
 #ifdef DEBUG
 	if (ldebug(open))
 		printf(LMSG("open returns error %d"), error);
 #endif
-    return error;
+	linux_free_path(&path);
+	return error;
 }
 
 int
 linux_lseek(struct linux_lseek_args *args)
 {
-    struct lseek_args tmp_args;
-    int error;
+	int error;
 
 #ifdef DEBUG
 	if (ldebug(lseek))
 		printf(ARGS(lseek, "%d, %ld, %d"),
 		    args->fdes, (long)args->off, args->whence);
 #endif
-    tmp_args.fd = args->fdes;
-    tmp_args.offset = (off_t)args->off;
-    tmp_args.whence = args->whence;
-    tmp_args.sysmsg_result = 0;
-    error = lseek(&tmp_args);
-    args->sysmsg_offset = tmp_args.sysmsg_offset;
-    return error;
+	error = kern_lseek(args->fdes, args->off, args->whence,
+	    &args->sysmsg_offset);
+
+	return error;
 }
 
 #ifndef __alpha__
 int
 linux_llseek(struct linux_llseek_args *args)
 {
-	struct lseek_args bsd_args;
 	int error;
-	off_t off;
+	off_t off, res;
 
 #ifdef DEBUG
 	if (ldebug(llseek))
@@ -185,19 +182,11 @@
 #endif
 	off = (args->olow) | (((off_t) args->ohigh) << 32);
 
-	bsd_args.fd = args->fd;
-	bsd_args.offset = off;
-	bsd_args.whence = args->whence;
-	bsd_args.sysmsg_offset = 0;
-
-	if ((error = lseek(&bsd_args)))
-		return error;
+	error = kern_lseek(args->fd, off, args->whence, &res);
 
-	if ((error = copyout(&bsd_args.sysmsg_offset, (caddr_t)args->res, sizeof (off_t)))) {
-		return error;
-	}
-	args->sysmsg_result = 0;
-	return 0;
+	if (error == 0)
+		error = copyout(&res, args->res, sizeof(res));
+	return (error);
 }
 #endif /*!__alpha__*/
 
@@ -470,232 +459,255 @@
 int
 linux_access(struct linux_access_args *args)
 {
-	struct access_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(access))
-		printf(ARGS(access, "%s, %d"), args->path, args->flags);
+		printf(ARGS(access, "%s, %d"), path, args->flags);
 #endif
-	bsd.path = args->path;
-	bsd.flags = args->flags;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ,
+	    UIO_SYSSPACE, path, td);
 
-	error = access(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_access(&nd, args->flags);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_unlink(struct linux_unlink_args *args)
 {
-	struct unlink_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(unlink))
-		printf(ARGS(unlink, "%s"), args->path);
+		printf(ARGS(unlink, "%s"), path);
 #endif
-	bsd.path = args->path;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT, UIO_SYSSPACE, path, td);
 
-	error = unlink(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_unlink(&nd);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_chdir(struct linux_chdir_args *args)
 {
-	struct chdir_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(chdir))
-		printf(ARGS(chdir, "%s"), args->path);
+		printf(ARGS(chdir, "%s"), path);
 #endif
-	bsd.path = args->path;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_SYSSPACE,
+	    path, td);
 
-	error = chdir(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_chdir(&nd);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_chmod(struct linux_chmod_args *args)
 {
-	struct chmod_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(chmod))
-		printf(ARGS(chmod, "%s, %d"), args->path, args->mode);
+		printf(ARGS(chmod, "%s, %d"), path, args->mode);
 #endif
-	bsd.path = args->path;
-	bsd.mode = args->mode;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
 
-	error = chmod(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_chmod(&nd, args->mode);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_mkdir(struct linux_mkdir_args *args)
 {
-	struct mkdir_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTCREAT(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(mkdir))
-		printf(ARGS(mkdir, "%s, %d"), args->path, args->mode);
+		printf(ARGS(mkdir, "%s, %d"), path, args->mode);
 #endif
-	bsd.path = args->path;
-	bsd.mode = args->mode;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_SYSSPACE, path, td);
 
-	error = mkdir(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_mkdir(&nd, args->mode);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_rmdir(struct linux_rmdir_args *args)
 {
-	struct rmdir_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(rmdir))
-		printf(ARGS(rmdir, "%s"), args->path);
+		printf(ARGS(rmdir, "%s"), path);
 #endif
-	bsd.path = args->path;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT | CNP_LOCKLEAF,
+	    UIO_SYSSPACE, path, td);
 
-	error = rmdir(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_rmdir(&nd);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_rename(struct linux_rename_args *args)
 {
-	struct rename_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata fromnd, tond;
+	char *from, *to;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->from);
-	CHECKALTCREAT(&sg, args->to);
-
+	error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
+	error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
+	if (error) {
+		linux_free_path(&from);
+		return (error);
+	}
 #ifdef DEBUG
 	if (ldebug(rename))
 		printf(ARGS(rename, "%s, %s"), args->from, args->to);
 #endif
-	bsd.from = args->from;
-	bsd.to = args->to;
-	bsd.sysmsg_result = 0;
+	NDINIT(&fromnd, NAMEI_DELETE, CNP_WANTPARENT | CNP_SAVESTART,
+	    UIO_SYSSPACE, from, td);
+	NDINIT(&tond, NAMEI_RENAME,
+	    CNP_LOCKPARENT | CNP_LOCKLEAF | CNP_NOCACHE |
+	    CNP_SAVESTART | CNP_NOOBJ,
+	    UIO_SYSSPACE, to, td);
 
-	error = rename(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_rename(&fromnd, &tond);
+
+	linux_free_path(&from);
+	linux_free_path(&to);
 	return(error);
 }
 
 int
 linux_symlink(struct linux_symlink_args *args)
 {
-	struct symlink_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path, *link;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-	CHECKALTCREAT(&sg, args->to);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
+	error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
+	if (error) {
+		linux_free_path(&path);
+		return (error);
+	}
 #ifdef DEBUG
 	if (ldebug(symlink))
-		printf(ARGS(symlink, "%s, %s"), args->path, args->to);
+		printf(ARGS(symlink, "%s, %s"), path, link);
 #endif
-	bsd.path = args->path;
-	bsd.link = args->to;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, UIO_SYSSPACE,
+	    link, td);
 
-	error = symlink(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_symlink(path, &nd);
+
+	linux_free_path(&path);
+	linux_free_path(&link);
 	return(error);
 }
 
 int
 linux_readlink(struct linux_readlink_args *args)
 {
-	struct readlink_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->name);
-
+	error = linux_copyin_path(args->name, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(readlink))
-		printf(ARGS(readlink, "%s, %p, %d"),
-		    args->name, (void *)args->buf, args->count);
+		printf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
+		    args->count);
 #endif
-	bsd.path = args->name;
-	bsd.buf = args->buf;
-	bsd.count = args->count;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ, UIO_SYSSPACE,
+	   path, td);
 
-	error = readlink(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_readlink(&nd, args->buf, args->count,
+	    &args->sysmsg_result);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_truncate(struct linux_truncate_args *args)
 {
-	struct truncate_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(truncate))
 		printf(ARGS(truncate, "%s, %ld"), args->path,
 		    (long)args->length);
 #endif
-	bsd.path = args->path;
-	bsd.length = args->length;
-	bsd.sysmsg_result = 0;
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
 
-	error = truncate(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_truncate(&nd, args->length);
+
+	linux_free_path(&path);
 	return(error);
 }
 
@@ -717,26 +729,33 @@
 int
 linux_link(struct linux_link_args *args)
 {
-    struct link_args bsd;
-    caddr_t sg;
-    int error;
-
-    sg = stackgap_init();
-    CHECKALTEXIST(&sg, args->path);
-    CHECKALTCREAT(&sg, args->to);
+	struct thread *td = curthread;
+	struct nameidata nd, linknd;
+	char *path, *link;
+	int error;
 
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
+	error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
+	if (error) {
+		linux_free_path(&path);
+		return (error);
+	}
 #ifdef DEBUG
 	if (ldebug(link))
-		printf(ARGS(link, "%s, %s"), args->path, args->to);
+		printf(ARGS(link, "%s, %s"), path, link);
 #endif
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_NOOBJ, UIO_SYSSPACE,
+	    path, td);
+	NDINIT(&linknd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ,
+	    UIO_SYSSPACE, link, td);
 
-    bsd.path = args->path;
-    bsd.link = args->to;
-    bsd.sysmsg_result = 0;
+	error = kern_link(&nd, &linknd);
 
-    error = link(&bsd);
-    args->sysmsg_result = bsd.sysmsg_result;
-    return(error);
+	linux_free_path(&path);
+	linux_free_path(&link);
+	return(error);
 }
 
 #ifndef __alpha__
@@ -1129,51 +1148,46 @@
 int
 linux_chown(struct linux_chown_args *args)
 {
-	struct chown_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(chown))
-		printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid,
-		    args->gid);
+		printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid);
 #endif
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
 
-	bsd.path = args->path;
-	bsd.uid = args->uid;
-	bsd.gid = args->gid;
-	bsd.sysmsg_result = 0;
-	error = chown(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	error = kern_chown(&nd, args->uid, args->gid);
+
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_lchown(struct linux_lchown_args *args)
 {
-	struct lchown_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(lchown))
-		printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid,
-		    args->gid);
+		printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid);
 #endif
+	NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_SYSSPACE, path, td);
 
-	bsd.path = args->path;
-	bsd.uid = args->uid;
-	bsd.gid = args->gid;
-	bsd.sysmsg_result = 0;
+	error = kern_chown(&nd, args->uid, args->gid);
 
-	error = lchown(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	linux_free_path(&path);
 	return(error);
 }
 
Index: emulation/linux/linux_misc.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/linux_misc.c,v
retrieving revision 1.15
diff -u -u -r1.15 linux_misc.c
--- emulation/linux/linux_misc.c	3 Nov 2003 15:57:33 -0000	1.15
+++ emulation/linux/linux_misc.c	11 Nov 2003 23:02:13 -0000
@@ -251,18 +251,18 @@
 	vm_offset_t buffer;
 	unsigned long bss_size;
 	int error;
-	caddr_t sg;
 	int locked;
+	char *path;
 
 	KKASSERT(td->td_proc);
 	p = td->td_proc;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->library);
-
+	error = linux_copyin_path(args->library, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(uselib))
-		printf(ARGS(uselib, "%s"), args->library);
+		printf(ARGS(uselib, "%s"), path);
 #endif
 
 	a_out = NULL;
@@ -270,7 +270,7 @@
 	vp = NULL;
 
 	NDINIT(&ni, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF,
-		UIO_USERSPACE, args->library, td);
+		UIO_SYSSPACE, path, td);
 	error = namei(&ni);
 	if (error)
 		goto cleanup;
@@ -471,6 +471,7 @@
 		vm_map_remove(kernel_map, (vm_offset_t)a_out,
 		    (vm_offset_t)a_out + PAGE_SIZE);
 
+	linux_free_path(&path);
 	return error;
 }
 
@@ -739,45 +740,37 @@
 int
 linux_utime(struct linux_utime_args *args)
 {
-	struct utimes_args /* {
-		char	*path;
-		struct	timeval *tptr;
-	} */ bsdutimes;
-	struct timeval tv[2], *tvp;
+	struct thread *td = curthread;
+	struct timeval tv[2];
 	struct l_utimbuf lut;
+	struct nameidata nd;
+	char *path;
 	int error;
-	caddr_t sg;
-
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->fname);
 
+	error = linux_copyin_path(args->fname, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(utime))
-		printf(ARGS(utime, "%s, *"), args->fname);
+		printf(ARGS(utime, "%s, *"), path);
 #endif
 
 	if (args->times) {
-		if ((error = copyin((caddr_t)args->times, &lut, sizeof lut)))
-			return error;
+		error = copyin(args->times, &lut, sizeof(lut));
+		if (error)
+			goto cleanup;
 		tv[0].tv_sec = lut.l_actime;
 		tv[0].tv_usec = 0;
 		tv[1].tv_sec = lut.l_modtime;
 		tv[1].tv_usec = 0;
-		/* so that utimes can copyin */
-		tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv));
-		if (tvp == NULL)
-			return (ENAMETOOLONG);
-		if ((error = copyout(tv, tvp, sizeof(tv))))
-			return error;
-		bsdutimes.tptr = tvp;
-	} else
-		bsdutimes.tptr = NULL;
-
-	bsdutimes.path = args->fname;
-	bsdutimes.sysmsg_result = 0;
-	error = utimes(&bsdutimes);
-	args->sysmsg_result = bsdutimes.sysmsg_result;
-	return(error);
+	}
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
+
+	error = kern_utimes(&nd, args->times ? tv : NULL);
+
+cleanup:
+	linux_free_path(&path);
+	return (error);
 }
 #endif /* __i386__ */
 
@@ -863,35 +856,28 @@
 int
 linux_mknod(struct linux_mknod_args *args)
 {
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
-	caddr_t sg;
-	struct mknod_args bsd_mknod;
-	struct mkfifo_args bsd_mkfifo;
-
-	sg = stackgap_init();
-
-	CHECKALTCREAT(&sg, args->path);
 
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(mknod))
 		printf(ARGS(mknod, "%s, %d, %d"),
-		    args->path, args->mode, args->dev);
+		    path, args->mode, args->dev);
 #endif
+	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_SYSSPACE, path, td);
 
 	if (args->mode & S_IFIFO) {
-		bsd_mkfifo.path = args->path;
-		bsd_mkfifo.mode = args->mode;
-		bsd_mkfifo.sysmsg_result = 0;
-		error = mkfifo(&bsd_mkfifo);
-		args->sysmsg_result = bsd_mkfifo.sysmsg_result;
+		error = kern_mkfifo(&nd, args->mode);
 	} else {
-		bsd_mknod.path = args->path;
-		bsd_mknod.mode = args->mode;
-		bsd_mknod.dev = args->dev;
-		bsd_mknod.sysmsg_result = 0;
-		error = mknod(&bsd_mknod);
-		args->sysmsg_result = bsd_mknod.sysmsg_result;
+		error = kern_mknod(&nd, args->mode, args->dev);
 	}
+
+	linux_free_path(&path);
 	return(error);
 }
 
Index: emulation/linux/linux_stats.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/linux_stats.c,v
retrieving revision 1.10
diff -u -u -r1.10 linux_stats.c
--- emulation/linux/linux_stats.c	21 Oct 2003 01:05:09 -0000	1.10
+++ emulation/linux/linux_stats.c	11 Nov 2003 12:55:07 -0000
@@ -55,6 +55,7 @@
 {
 	struct l_newstat tbuf;
 	dev_t dev;
+	int error;
 
 	tbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
 	tbuf.st_ino = buf->st_ino;
@@ -86,7 +87,8 @@
 		}
 	}
 
-	return (copyout(&tbuf, ubuf, sizeof(tbuf)));
+	error = copyout(&tbuf, ubuf, sizeof(tbuf));
+	return (error);
 }
 
 int
@@ -95,62 +97,52 @@
 	struct thread *td = curthread;
 	struct stat buf;
 	struct nameidata nd;
+	char *path;
 	int error;
-	caddr_t sg;
-
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
 
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(newstat))
-		printf(ARGS(newstat, "%s, *"), args->path);
+		printf(ARGS(newstat, "%s, *"), path);
 #endif
-
 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ,
-	    UIO_USERSPACE, args->path, td);
-	error = namei(&nd);
-	if (error)
-		return (error);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
+	    UIO_SYSSPACE, path, td);
 
-	error = vn_stat(nd.ni_vp, &buf, td);
-	vput(nd.ni_vp);
-	if (error)
-		return (error);
+	error = kern_stat(&nd, &buf);
 
-	return (newstat_copyout(&buf, args->buf));
+	if (error == 0)
+		error = newstat_copyout(&buf, args->buf);
+	linux_free_path(&path);
+	return (error);
 }
 
 int
 linux_newlstat(struct linux_newlstat_args *args)
 {
 	struct thread *td = curthread;
-	int error;
 	struct stat sb;
 	struct nameidata nd;
-	caddr_t sg;
-
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
+	char *path;
+	int error;
 
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(newlstat))
-		printf(ARGS(newlstat, "%s, *"), args->path);
+		printf(ARGS(newlstat, "%s, *"), path);
 #endif
-
 	NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ,
-	    UIO_USERSPACE, args->path, td);
-	error = namei(&nd);
-	if (error)
-		return (error);
-	NDFREE(&nd, NDF_ONLY_PNBUF); 
+	    UIO_SYSSPACE, path, td);
 
-	error = vn_stat(nd.ni_vp, &sb, td);
-	vput(nd.ni_vp);
-	if (error)
-		return (error);
+	error = kern_stat(&nd, &sb);
 
-	return (newstat_copyout(&sb, args->buf));
+	if (error == 0)
+		error = newstat_copyout(&sb, args->buf);
+	linux_free_path(&path);
+	return (error);
 }
 
 int
@@ -219,90 +211,68 @@
 	return (0L);
 }
 
+static int
+statfs_copyout(struct statfs *statfs, struct l_statfs_buf *buf)
+{
+	struct l_statfs linux_statfs;
+	int error;
+
+	linux_statfs.f_type = bsd_to_linux_ftype(statfs->f_fstypename);
+	linux_statfs.f_bsize = statfs->f_bsize;
+	linux_statfs.f_blocks = statfs->f_blocks;
+	linux_statfs.f_bfree = statfs->f_bfree;
+	linux_statfs.f_bavail = statfs->f_bavail;
+  	linux_statfs.f_ffree = statfs->f_ffree;
+	linux_statfs.f_files = statfs->f_files;
+	linux_statfs.f_fsid.val[0] = statfs->f_fsid.val[0];
+	linux_statfs.f_fsid.val[1] = statfs->f_fsid.val[1];
+	linux_statfs.f_namelen = MAXNAMLEN; /* Bogus */
+
+	error = copyout(&linux_statfs, buf, sizeof(linux_statfs));
+	return (error);
+}
+
 int
 linux_statfs(struct linux_statfs_args *args)
 {
 	struct thread *td = curthread;
-	struct mount *mp;
-	struct nameidata *ndp;
-	struct statfs *bsd_statfs;
+	struct statfs statfs;
 	struct nameidata nd;
-	struct l_statfs linux_statfs;
+	char *path;
 	int error;
-	caddr_t sg;
-
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
 
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(statfs))
-		printf(ARGS(statfs, "%s, *"), args->path);
+		printf(ARGS(statfs, "%s, *"), path);
 #endif
-	ndp = &nd;
-	NDINIT(ndp, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, args->path, td);
-	error = namei(ndp);
-	if (error)
-		return error;
-	NDFREE(ndp, NDF_ONLY_PNBUF);
-	mp = ndp->ni_vp->v_mount;
-	bsd_statfs = &mp->mnt_stat;
-	vrele(ndp->ni_vp);
-	error = VFS_STATFS(mp, bsd_statfs, td);
-	if (error)
-		return error;
-	bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-	linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
-	linux_statfs.f_bsize = bsd_statfs->f_bsize;
-	linux_statfs.f_blocks = bsd_statfs->f_blocks;
-	linux_statfs.f_bfree = bsd_statfs->f_bfree;
-	linux_statfs.f_bavail = bsd_statfs->f_bavail;
-  	linux_statfs.f_ffree = bsd_statfs->f_ffree;
-	linux_statfs.f_files = bsd_statfs->f_files;
-	linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
-	linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
-	linux_statfs.f_namelen = MAXNAMLEN;
-	return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
-	    sizeof(linux_statfs));
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
+
+	error = kern_statfs(&nd, &statfs);
+
+	if (error == 0)
+		error = statfs_copyout(&statfs, args->buf);
+	linux_free_path(&path);
+	return (error);
 }
 
 int
 linux_fstatfs(struct linux_fstatfs_args *args)
 {
-	struct thread *td = curthread;
-	struct proc *p = td->td_proc;
-	struct file *fp;
-	struct mount *mp;
-	struct statfs *bsd_statfs;
-	struct l_statfs linux_statfs;
+	struct statfs statfs;
 	int error;
 
-	KKASSERT(p);
-
 #ifdef DEBUG
 	if (ldebug(fstatfs))
 		printf(ARGS(fstatfs, "%d, *"), args->fd);
 #endif
-	error = getvnode(p->p_fd, args->fd, &fp);
-	if (error)
-		return error;
-	mp = ((struct vnode *)fp->f_data)->v_mount;
-	bsd_statfs = &mp->mnt_stat;
-	error = VFS_STATFS(mp, bsd_statfs, td);
-	if (error)
-		return error;
-	bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-	linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
-	linux_statfs.f_bsize = bsd_statfs->f_bsize;
-	linux_statfs.f_blocks = bsd_statfs->f_blocks;
-	linux_statfs.f_bfree = bsd_statfs->f_bfree;
-	linux_statfs.f_bavail = bsd_statfs->f_bavail;
-  	linux_statfs.f_ffree = bsd_statfs->f_ffree;
-	linux_statfs.f_files = bsd_statfs->f_files;
-	linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
-	linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
-	linux_statfs.f_namelen = MAXNAMLEN;
-	return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
-	    sizeof(linux_statfs));
+	error = kern_fstatfs(args->fd, &statfs);
+
+	if (error == 0)
+		error = statfs_copyout(&statfs, args->buf);
+	return (error);
 }
 
 struct l_ustat 
@@ -363,6 +333,7 @@
 stat64_copyout(struct stat *buf, void *ubuf)
 {
 	struct l_stat64 lbuf;
+	int error;
 
 	bzero(&lbuf, sizeof(lbuf));
 	lbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
@@ -387,71 +358,62 @@
 	 */
 	lbuf.__st_ino = buf->st_ino;
 
-	return (copyout(&lbuf, ubuf, sizeof(lbuf)));
+	error = copyout(&lbuf, ubuf, sizeof(lbuf));
+	return (error);
 }
 
 int
 linux_stat64(struct linux_stat64_args *args)
 {
 	struct thread *td = curthread;
-	struct stat buf;
 	struct nameidata nd;
+	struct stat buf;
+	char *path;
 	int error;
-	caddr_t sg;
-
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->filename);
 
+	error = linux_copyin_path(args->filename, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(stat64))
-		printf(ARGS(stat64, "%s, *"), args->filename);
+		printf(ARGS(stat64, "%s, *"), path);
 #endif
-
 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ,
-		UIO_USERSPACE, args->filename, td);
-	error = namei(&nd);
-	if (error)
-		return (error);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
+		UIO_SYSSPACE, path, td);
 
-	error = vn_stat(nd.ni_vp, &buf, td);
-	vput(nd.ni_vp);
-	if (error)
-		return (error);
+	error = kern_stat(&nd, &buf);
 
-	return (stat64_copyout(&buf, args->statbuf));
+	if (error == 0)
+		error = stat64_copyout(&buf, args->statbuf);
+	linux_free_path(&path);
+	return (error);
 }
 
 int
 linux_lstat64(struct linux_lstat64_args *args)
 {
 	struct thread *td = curthread;
-	int error;
-	struct stat sb;
 	struct nameidata nd;
-	caddr_t sg;
-
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->filename);
+	struct stat sb;
+	char *path;
+	int error;
 
+	error = linux_copyin_path(args->filename, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(lstat64))
-		printf(ARGS(lstat64, "%s, *"), args->filename);
+		printf(ARGS(lstat64, "%s, *"), path);
 #endif
-
 	NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ,
-		UIO_USERSPACE, args->filename, td);
-	error = namei(&nd);
-	if (error)
-		return (error);
-	NDFREE(&nd, NDF_ONLY_PNBUF); 
+	    UIO_SYSSPACE, path, td);
 
-	error = vn_stat(nd.ni_vp, &sb, td);
-	vput(nd.ni_vp);
-	if (error)
-		return (error);
+	error = kern_stat(&nd, &sb);
 
-	return (stat64_copyout(&sb, args->statbuf));
+	if (error == 0)
+		error = stat64_copyout(&sb, args->statbuf);
+	linux_free_path(&path);
+	return (error);
 }
 
 int
Index: emulation/linux/linux_uid16.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/linux_uid16.c,v
retrieving revision 1.8
diff -u -u -r1.8 linux_uid16.c
--- emulation/linux/linux_uid16.c	15 Aug 2003 06:32:51 -0000	1.8
+++ emulation/linux/linux_uid16.c	11 Nov 2003 21:17:51 -0000
@@ -31,8 +31,11 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/kern_syscall.h>
+#include <sys/namei.h>
 #include <sys/proc.h>
 #include <sys/sysproto.h>
+#include <sys/thread.h>
 
 #include <arch_linux/linux.h>
 #include <arch_linux/linux_proto.h>
@@ -43,56 +46,53 @@
 DUMMY(getresuid16);
 DUMMY(getresgid16);
 
-#define	CAST_NOCHG(x)	(x == 0xFFFF) ? -1 : x;
+#define	CAST_NOCHG(x)	((x == 0xFFFF) ? -1 : x)
 
 int
 linux_chown16(struct linux_chown16_args *args)
 {
-	struct chown_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(chown16))
-		printf(ARGS(chown16, "%s, %d, %d"), args->path, args->uid,
+		printf(ARGS(chown16, "%s, %d, %d"), path, args->uid,
 		    args->gid);
 #endif
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path, td);
+
+	error = kern_chown(&nd, CAST_NOCHG(args->uid), CAST_NOCHG(args->gid));
 
-	bsd.path = args->path;
-	bsd.uid = CAST_NOCHG(args->uid);
-	bsd.gid = CAST_NOCHG(args->gid);
-	bsd.sysmsg_result = 0;
-	error = chown(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	linux_free_path(&path);
 	return(error);
 }
 
 int
 linux_lchown16(struct linux_lchown16_args *args)
 {
-	struct lchown_args bsd;
-	caddr_t sg;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *path;
 	int error;
 
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
-
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(lchown16))
-		printf(ARGS(lchown16, "%s, %d, %d"), args->path, args->uid,
+		printf(ARGS(lchown16, "%s, %d, %d"), path, args->uid,
 		    args->gid);
 #endif
+	NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_SYSSPACE, path, td);
 
-	bsd.path = args->path;
-	bsd.uid = CAST_NOCHG(args->uid);
-	bsd.gid = CAST_NOCHG(args->gid);
-	bsd.sysmsg_result = 0;
+	error = kern_chown(&nd, CAST_NOCHG(args->uid), CAST_NOCHG(args->gid));
 
-	error = lchown(&bsd);
-	args->sysmsg_result = bsd.sysmsg_result;
+	linux_free_path(&path);
 	return(error);
 }
 
Index: emulation/linux/linux_util.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/linux_util.c,v
retrieving revision 1.7
diff -u -u -r1.7 linux_util.c
--- emulation/linux/linux_util.c	23 Sep 2003 05:03:51 -0000	1.7
+++ emulation/linux/linux_util.c	11 Nov 2003 23:52:04 -0000
@@ -43,88 +43,65 @@
 const char      linux_emul_path[] = "/compat/linux";
 
 /*
- * Search an alternate path before passing pathname arguments on
- * to system calls. Useful for keeping a separate 'emulation tree'.
+ * Search for an alternate path before passing pathname arguments on
+ * to system calls.
  *
- * If cflag is set, we check if an attempt can be made to create
- * the named file, i.e. we check if the directory it should
- * be in exists.
+ * Only signal an error if something really bad happens.  In most cases
+ * we can just return the untranslated path, eg. name lookup failures.
  */
 int
-linux_emul_find(td, sgp, prefix, path, pbuf, cflag)
-	struct thread	*td;
-	caddr_t		*sgp;		/* Pointer to stackgap memory */
-	const char	*prefix;
-	char		*path;
-	char		**pbuf;
-	int		cflag;
+linux_copyin_path(char *uname, char **kname, int flags)
 {
-	struct nameidata	 nd;
-	struct nameidata	 ndroot;
-	struct vattr		 vat;
-	struct vattr		 vatroot;
-	int			 error;
-	char			*ptr, *buf, *cp;
-	size_t			 sz, len;
-	struct ucred		*cred;
-
-	KKASSERT(td->td_proc);
-	cred = td->td_proc->p_ucred;
+	struct thread *td = curthread;
+	struct nameidata nd, ndroot;
+	struct vattr vat, vatroot;
+	char *buf, *cp;
+	int error, length, dummy;
 
 	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
-	*pbuf = path;
-
-	for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
-		continue;
+	*kname = buf;
 
-	sz = MAXPATHLEN - (ptr - buf);
-
-	/* 
-	 * If sgp is not given then the path is already in kernel space
+	/*
+	 * Don't bother trying to translate if the path is relative.
 	 */
-	if (sgp == NULL)
-		error = copystr(path, ptr, sz, &len);
-	else
-		error = copyinstr(path, ptr, sz, &len);
-
-	if (error) {
-		free(buf, M_TEMP);
-		return error;
-	}
-
-	if (*ptr != '/') {
-		free(buf, M_TEMP);
-		return EINVAL;
-	}
+	if (fubyte(uname) != '/')
+		goto dont_translate;
 
 	/*
-	 * We know that there is a / somewhere in this pathname.
-	 * Search backwards for it, to find the file's parent dir
-	 * to see if it exists in the alternate tree. If it does,
-	 * and we want to create a file (cflag is set). We don't
-	 * need to worry about the root comparison in this case.
+	 * The path is absolute.  Prepend the buffer with the emulation
+	 * path and copy in.
 	 */
+	length = strlen(linux_emul_path);
+	bcopy(linux_emul_path, buf, length);
+	error = copyinstr(uname, buf + length, MAXPATHLEN - length, &dummy);
+	if (error) {
+		linux_free_path(kname);
+		return (error);
+	}
 
-	if (cflag) {
-		for (cp = &ptr[len] - 1; *cp != '/'; cp--);
+	switch (flags) {
+	case LINUX_PATH_CREATE:
+		/*
+		 * Check to see if the parent directory exists in the
+		 * emulation tree.  Walk the string backwards to find
+		 * the last '/'.
+		 */
+		cp = buf + strlen(buf);
+		while (*--cp != '/');
 		*cp = '\0';
 
 		NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, buf, td);
-
-		if ((error = namei(&nd)) != 0) {
-			free(buf, M_TEMP);
-			return error;
-		}
+		error = namei(&nd);
+		if (error)
+			goto dont_translate;
 
 		*cp = '/';
-	}
-	else {
+		return (0);
+	case LINUX_PATH_EXISTS:
 		NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, buf, td);
-
-		if ((error = namei(&nd)) != 0) {
-			free(buf, M_TEMP);
-			return error;
-		}
+		error = namei(&nd);
+		if (error)
+			goto dont_translate;
 
 		/*
 		 * We now compare the vnode of the linux_root to the one
@@ -133,59 +110,82 @@
 		 * This avoids the problem of traversing "../.." to find the
 		 * root directory and never finding it, because "/" resolves
 		 * to the emulation root directory. This is expensive :-(
+		 *
+		 * The next three function calls should not return errors.
+		 * If they do something is seriously wrong, eg. the
+		 * emulation subtree does not exist.  Cross our fingers
+		 * and return the untranslated path if something happens.
 		 */
 		NDINIT(&ndroot, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE,
-			linux_emul_path, td);
-
-		if ((error = namei(&ndroot)) != 0) {
-			/* Cannot happen! */
-			free(buf, M_TEMP);
-			NDFREE(&nd, NDF_ONLY_PNBUF);
-			vrele(nd.ni_vp);
-			return error;
-		}
-
-		if ((error = VOP_GETATTR(nd.ni_vp, &vat, td)) != 0) {
-			goto bad;
-		}
-
-		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td))
-		    != 0) {
-			goto bad;
-		}
+		    linux_emul_path, td);
+		error = namei(&ndroot);
+		if (error)
+			goto dont_translate;
+		
+		error = VOP_GETATTR(nd.ni_vp, &vat, td);
+		if (error)
+			goto dont_translate;
+
+		error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td);
+		if (error)
+			goto dont_translate;
 
 		if (vat.va_fsid == vatroot.va_fsid &&
-		    vat.va_fileid == vatroot.va_fileid) {
-			error = ENOENT;
-			goto bad;
-		}
+		    vat.va_fileid == vatroot.va_fileid)
+			goto dont_translate;
 
-	}
-	if (sgp == NULL)
-		*pbuf = buf;
-	else {
-		sz = &ptr[len] - buf;
-		*pbuf = stackgap_alloc(sgp, sz + 1);
-		if (*pbuf != NULL)
-			error = copyout(buf, *pbuf, sz);
-		else
-			error = ENAMETOOLONG;
-		free(buf, M_TEMP);
-	}
+		return (0);
+	default:
+		linux_free_path(kname);
+		return (EINVAL);
+	}
+	
+dont_translate:
+
+	error = copyinstr(uname, buf, MAXPATHLEN, &dummy);
+	if (error)
+		linux_free_path(kname);
+	return (error);
+}
+
+/*
+ * Smaller version of the above for translating in kernel buffers.  Only
+ * used in exec_linux_imgact_try().  Only check is path exists.
+ */
+int
+linux_translate_path(char *path, int size)
+{
+	struct thread *td = curthread;
+	struct nameidata nd;
+	char *buf;
+	int error, length, dummy;
 
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	vrele(nd.ni_vp);
-	if (!cflag) {
-		NDFREE(&ndroot, NDF_ONLY_PNBUF);
-		vrele(ndroot.ni_vp);
+	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+	length = strlen(linux_emul_path);
+	bcopy(linux_emul_path, buf, length);
+	error = copystr(path, buf + length, MAXPATHLEN - length, &dummy);
+	if (error)
+		goto cleanup;
+	
+	/*
+	 * If this errors, then the path probably doesn't exists.
+	 */
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, buf, td);
+	error = namei(&nd);
+	if (error) {
+		error = 0;
+		goto cleanup;
 	}
-	return error;
 
-bad:
-	NDFREE(&ndroot, NDF_ONLY_PNBUF);
-	vrele(ndroot.ni_vp);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	vrele(nd.ni_vp);
+	/*
+	 * The alternate path does exist.  Return it in the buffer if
+	 * it fits.
+	 */
+	if (strlen(buf) + 1 <= size)
+		error = copystr(buf, path, size, &dummy);
+
+cleanup:
+
 	free(buf, M_TEMP);
-	return error;
+	return (error);
 }
Index: emulation/linux/linux_util.h
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/linux_util.h,v
retrieving revision 1.5
diff -u -u -r1.5 linux_util.h
--- emulation/linux/linux_util.h	27 Aug 2003 06:30:03 -0000	1.5
+++ emulation/linux/linux_util.h	11 Nov 2003 23:54:27 -0000
@@ -50,6 +50,20 @@
 #include <sys/sysent.h>
 #include <sys/cdefs.h>
 
+#define LINUX_PATH_CREATE 1
+#define LINUX_PATH_EXISTS 2
+
+int linux_translate_path(char *, int);
+int linux_copyin_path(char *, char **, int);
+
+static __inline void
+linux_free_path(char **kname) {
+	if (*kname) {
+		free(*kname, M_TEMP);
+		*kname = NULL;
+	}
+}
+
 static __inline caddr_t stackgap_init(void);
 static __inline void *stackgap_alloc(caddr_t *, size_t);
 
@@ -74,23 +88,6 @@
 	*sgp += sz;
 	return p;
 }
-
-extern const char linux_emul_path[];
-
-int linux_emul_find (struct thread *, caddr_t *, const char *, char *, char **, int);
-
-#define CHECKALT(sgp, path, i) 						\
-	do {								\
-		int _error;						\
-									\
-		_error = linux_emul_find(curthread, sgp, linux_emul_path, path, \
-		    &path, i);						\
-		if (_error == EFAULT)					\
-			return (_error);				\
-	} while (0)
-
-#define CHECKALTEXIST(sgp, path) CHECKALT(sgp, path, 0)
-#define CHECKALTCREAT(sgp, path) CHECKALT(sgp, path, 1)
 
 #define DUMMY(s)							\
 int									\
Index: emulation/linux/i386/linux_machdep.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/i386/linux_machdep.c,v
retrieving revision 1.10
diff -u -u -r1.10 linux_machdep.c
--- emulation/linux/i386/linux_machdep.c	24 Oct 2003 14:10:45 -0000	1.10
+++ emulation/linux/i386/linux_machdep.c	11 Nov 2003 22:47:10 -0000
@@ -31,9 +31,11 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/imgact.h>
 #include <sys/kern_syscall.h>
 #include <sys/lock.h>
 #include <sys/mman.h>
+#include <sys/namei.h>
 #include <sys/proc.h>
 #include <sys/resource.h>
 #include <sys/resourcevar.h>
@@ -102,28 +104,41 @@
 int
 linux_execve(struct linux_execve_args *args)
 {
-	struct execve_args bsd;
+	struct thread *td = curthread;
+	struct nameidata nd;
+	struct image_args exec_args;
+	char *path;
 	int error;
-	caddr_t sg;
-
-	sg = stackgap_init();
-	CHECKALTEXIST(&sg, args->path);
 
+	error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
+	if (error)
+		return (error);
 #ifdef DEBUG
 	if (ldebug(execve))
-		printf(ARGS(execve, "%s"), args->path);
+		printf(ARGS(execve, "%s"), path);
 #endif
+	NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_FOLLOW | CNP_SAVENAME,
+	    UIO_SYSSPACE, path, td);
+
+	error = exec_copyin_args(&exec_args, path, PATH_SYSSPACE,
+	    args->argp, args->envp);
+	if (error) {
+		linux_free_path(&path);
+		return (error);
+	}
+
+	error = kern_execve(&nd, &exec_args);
 
 	/*
-	 * Note: inherit and set the full 64 bit syscall return
-	 * value so a successful execve() sets %edx to 0.
+	 * The syscall result is returned in registers to the new program.
+	 * Linux will register %edx as an atexit function and we must be
+	 * sure to set it to 0.  XXX
 	 */
-	bsd.sysmsg_result64 = args->sysmsg_result64;
-	bsd.fname = args->path;
-	bsd.argv = args->argp;
-	bsd.envv = args->envp;
-	error = execve(&bsd);
-	args->sysmsg_result64 = bsd.sysmsg_result64;
+	if (error == 0)
+		args->sysmsg_result64 = 0;
+
+	exec_free_args(&exec_args);
+	linux_free_path(&path);
 	return(error);
 }
 
Index: emulation/linux/i386/linux_sysvec.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/linux/i386/linux_sysvec.c,v
retrieving revision 1.11
diff -u -u -r1.11 linux_sysvec.c
--- emulation/linux/i386/linux_sysvec.c	12 Nov 2003 01:00:33 -0000	1.11
+++ emulation/linux/i386/linux_sysvec.c	12 Nov 2003 00:59:07 -0000
@@ -753,18 +753,8 @@
 	     * path is found, use our stringspace to store it.
 	     */
 	    if ((error = exec_shell_imgact(imgp)) == 0) {
-		    char *rpath = NULL;
-
-		    linux_emul_find(imgp->proc->p_thread, NULL, linux_emul_path, 
-			imgp->interpreter_name, &rpath, 0);
-		    if (rpath != imgp->interpreter_name) {
-			    int len = strlen(rpath) + 1;
-
-			    if (len <= MAXSHELLCMDLEN) {
-				memcpy(imgp->interpreter_name, rpath, len);
-			    }
-			    free(rpath, M_TEMP);
-		    }
+		    linux_translate_path(imgp->interpreter_name,
+			MAXSHELLCMDLEN);
 	    }
     }
     return(error);
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.25
diff -u -u -r1.25 vfs_syscalls.c
--- kern/vfs_syscalls.c	11 Nov 2003 14:33:23 -0000	1.25
+++ kern/vfs_syscalls.c	11 Nov 2003 20:57:12 -0000
@@ -1172,44 +1172,56 @@
 	return (error);
 }
 
-/*
- * mkfifo_args(char *path, int mode)
- *
- * Create a named pipe.
- */
-/* ARGSUSED */
 int
-mkfifo(struct mkfifo_args *uap)
+kern_mkfifo(struct nameidata *nd, int mode)
 {
 	struct thread *td = curthread;
 	struct proc *p = td->td_proc;
 	struct vattr vattr;
 	int error;
-	struct nameidata nd;
 
 	bwillwrite();
-	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE,
-		SCARG(uap, path), td);
-	if ((error = namei(&nd)) != 0)
+	error = namei(nd);
+	if (error);
 		return (error);
-	if (nd.ni_vp != NULL) {
-		NDFREE(&nd, NDF_ONLY_PNBUF);
-		if (nd.ni_dvp == nd.ni_vp)
-			vrele(nd.ni_dvp);
+	if (nd->ni_vp != NULL) {
+		NDFREE(nd, NDF_ONLY_PNBUF);
+		if (nd->ni_dvp == nd->ni_vp)
+			vrele(nd->ni_dvp);
 		else
-			vput(nd.ni_dvp);
-		vrele(nd.ni_vp);
+			vput(nd->ni_dvp);
+		vrele(nd->ni_vp);
 		return (EEXIST);
 	}
 	VATTR_NULL(&vattr);
 	vattr.va_type = VFIFO;
-	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
-	VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
-	error = VOP_MKNOD(nd.ni_dvp, NCPNULL, &nd.ni_vp, &nd.ni_cnd, &vattr);
+	vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
+	VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
+	error = VOP_MKNOD(nd->ni_dvp, NCPNULL, &nd->ni_vp, &nd->ni_cnd, &vattr);
 	if (error == 0)
-		vput(nd.ni_vp);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	vput(nd.ni_dvp);
+		vput(nd->ni_vp);
+	NDFREE(nd, NDF_ONLY_PNBUF);
+	vput(nd->ni_dvp);
+	return (error);
+}
+
+/*
+ * mkfifo_args(char *path, int mode)
+ *
+ * Create a named pipe.
+ */
+int
+mkfifo(struct mkfifo_args *uap)
+{
+	struct thread *td = curthread;
+	struct nameidata nd;
+	int error;
+
+	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path,
+	    td);
+
+	error = kern_mkfifo(&nd, uap->mode);
+
 	return (error);
 }
 
Index: sys/kern_syscall.h
===================================================================
RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/sys/kern_syscall.h,v
retrieving revision 1.12
diff -u -u -r1.12 kern_syscall.h
--- sys/kern_syscall.h	12 Nov 2003 01:00:33 -0000	1.12
+++ sys/kern_syscall.h	12 Nov 2003 00:59:15 -0000
@@ -127,6 +127,7 @@
 int kern_link(struct nameidata *nd, struct nameidata *linknd);
 int kern_lseek(int fd, off_t offset, int whence, off_t *res);
 int kern_mkdir(struct nameidata *nd, int mode);
+int kern_mkfifo(struct nameidata *nd, int mode);
 int kern_mknod(struct nameidata *nd, int mode, int dev);
 int kern_open(struct nameidata *nd, int flags, int mode, int *res);
 int kern_readlink(struct nameidata *nd, char *buf, int count, int *res);
