Split mkfifo().
authorDavid P. Reese, Jr. <daver@dragonflybsd.org>
Thu, 13 Nov 2003 04:04:42 +0000 (04:04 +0000)
committerDavid P. Reese, Jr. <daver@dragonflybsd.org>
Thu, 13 Nov 2003 04:04:42 +0000 (04:04 +0000)
Trash the CHECKALT{CREAT,EXIST} macros and friends.  Implement
linux_copyin_path() and linux_free_path() for path translation without
using the stackgap.

Use the above and recently split syscalls to remove stackgap allocations
from linux_creat(), linux_open(), linux_lseek(), linux_llseek(),
linux_access(), linux_unlink(), linux_chdir(), linux_chmod(),
linux_mkdir(), linux_rmdir(), linux_rename(), linux_symlink(),
linux_readlink(), linux_truncate(), linux_link(), linux_chown(),
linux_lchown(), linux_uselib(), linux_utime(), linux_mknod(),
linux_newstat(), linux_newlstat(), linux_statfs(), linux_stat64(),
linux_lstat64(), linux_chown16(), linux_lchown16(), linux_execve().

Split use split syscalls to reimplement linux_fstatfs().

Implement linux_translate_path() for use in exec_linux_imgact_try().

sys/emulation/linux/i386/linux_machdep.c
sys/emulation/linux/i386/linux_sysvec.c
sys/emulation/linux/linux_file.c
sys/emulation/linux/linux_misc.c
sys/emulation/linux/linux_stats.c
sys/emulation/linux/linux_uid16.c
sys/emulation/linux/linux_util.c
sys/emulation/linux/linux_util.h
sys/kern/vfs_syscalls.c
sys/sys/kern_syscall.h

index 5c75cca..d0013e9 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/linux/linux_machdep.c,v 1.6.2.4 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/i386/linux_machdep.c,v 1.10 2003/10/24 14:10:45 daver Exp $
+ * $DragonFly: src/sys/emulation/linux/i386/linux_machdep.c,v 1.11 2003/11/13 04:04:42 daver Exp $
  */
 
 #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 @@ bsd_to_linux_sigaltstack(int bsa)
 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 738bda5..fa3d34f 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/linux/linux_sysvec.c,v 1.55.2.9 2002/01/12 11:03:30 bde Exp $
- * $DragonFly: src/sys/emulation/linux/i386/linux_sysvec.c,v 1.11 2003/11/12 01:00:33 daver Exp $
+ * $DragonFly: src/sys/emulation/linux/i386/linux_sysvec.c,v 1.12 2003/11/13 04:04:42 daver Exp $
  */
 
 /* XXX we use functions that might not exist. */
@@ -753,18 +753,8 @@ exec_linux_imgact_try(imgp)
             * 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 f2291b3..6680311 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $
- * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.13 2003/11/10 20:57:16 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.14 2003/11/13 04:04:42 daver Exp $
  */
 
 #include "opt_compat.h"
@@ -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>
 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;
+       struct thread *td = curthread;
+       struct proc *p = td->td_proc;
+       struct nameidata nd;
+       char *path;
+       int error, flags;
 
-    KKASSERT(p);
+       KKASSERT(p);
 
-    sg = stackgap_init();
-    
-    if (args->flags & LINUX_O_CREAT)
-       CHECKALTCREAT(&sg, args->path);
-    else
-       CHECKALTEXIST(&sg, args->path);
+       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];
-
-       if (fp->f_type == DTYPE_VNODE)
-           fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
+       flags = 0;
+       if (args->flags & LINUX_O_RDONLY)
+               flags |= O_RDONLY;
+       if (args->flags & LINUX_O_WRONLY)
+               flags |= O_WRONLY;
+       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);
     }
 #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 +184,11 @@ linux_llseek(struct linux_llseek_args *args)
 #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 +461,255 @@ linux_getdents64(struct linux_getdents64_args *args)
 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 +731,33 @@ linux_ftruncate(struct linux_ftruncate_args *args)
 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 +1150,46 @@ linux_fcntl64(struct linux_fcntl64_args *args)
 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 eb49403..81b6a07 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.85.2.9 2002/09/24 08:11:41 mdodd Exp $
- * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.15 2003/11/03 15:57:33 daver Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.16 2003/11/13 04:04:42 daver Exp $
  */
 
 #include "opt_compat.h"
@@ -251,18 +251,18 @@ linux_uselib(struct linux_uselib_args *args)
        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 @@ linux_uselib(struct linux_uselib_args *args)
        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 @@ cleanup:
                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 @@ struct l_utimbuf {
 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 @@ linux_wait4(struct linux_wait4_args *args)
 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 345186e..633977a 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_stats.c,v 1.22.2.3 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.10 2003/10/21 01:05:09 daver Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.11 2003/11/13 04:04:42 daver Exp $
  */
 
 #include <sys/param.h>
@@ -55,6 +55,7 @@ newstat_copyout(struct stat *buf, void *ubuf)
 {
        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 @@ newstat_copyout(struct stat *buf, void *ubuf)
                }
        }
 
-       return (copyout(&tbuf, ubuf, sizeof(tbuf)));
+       error = copyout(&tbuf, ubuf, sizeof(tbuf));
+       return (error);
 }
 
 int
@@ -95,62 +97,52 @@ linux_newstat(struct linux_newstat_args *args)
        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 @@ bsd_to_linux_ftype(const char *fstypename)
        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 @@ static int
 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 @@ stat64_copyout(struct stat *buf, void *ubuf)
         */
        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 462e7e8..f49e645 100644 (file)
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_uid16.c,v 1.4.2.1 2001/10/21 03:57:35 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_uid16.c,v 1.8 2003/08/15 06:32:51 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_uid16.c,v 1.9 2003/11/13 04:04:42 daver Exp $
  */
 
 #include "opt_compat.h"
 
 #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(setfsgid16);
 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);
 
-       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;
+       error = kern_chown(&nd, CAST_NOCHG(args->uid), CAST_NOCHG(args->gid));
+
+       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 e2b0481..6d01d69 100644 (file)
@@ -28,7 +28,7 @@
  *
  *     from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
  * $FreeBSD: src/sys/compat/linux/linux_util.c,v 1.12.2.2 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_util.c,v 1.7 2003/09/23 05:03:51 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_util.c,v 1.8 2003/11/13 04:04:42 daver Exp $
  */
 
 #include <sys/param.h>
 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;
+       *kname = buf;
 
-       for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
-               continue;
-
-       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 @@ linux_emul_find(td, sgp, prefix, path, pbuf, cflag)
                 * 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);
+                   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 ((error = namei(&ndroot)) != 0) {
-                       /* Cannot happen! */
-                       free(buf, M_TEMP);
-                       NDFREE(&nd, NDF_ONLY_PNBUF);
-                       vrele(nd.ni_vp);
-                       return error;
-               }
+               if (vat.va_fsid == vatroot.va_fsid &&
+                   vat.va_fileid == vatroot.va_fileid)
+                       goto dont_translate;
 
-               if ((error = VOP_GETATTR(nd.ni_vp, &vat, td)) != 0) {
-                       goto bad;
-               }
+               return (0);
+       default:
+               linux_free_path(kname);
+               return (EINVAL);
+       }
+       
+dont_translate:
 
-               if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td))
-                   != 0) {
-                       goto bad;
-               }
+       error = copyinstr(uname, buf, MAXPATHLEN, &dummy);
+       if (error)
+               linux_free_path(kname);
+       return (error);
+}
 
-               if (vat.va_fsid == vatroot.va_fsid &&
-                   vat.va_fileid == vatroot.va_fileid) {
-                       error = ENOENT;
-                       goto bad;
-               }
+/*
+ * 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;
 
-       }
-       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);
+       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;
        }
 
-       NDFREE(&nd, NDF_ONLY_PNBUF);
-       vrele(nd.ni_vp);
-       if (!cflag) {
-               NDFREE(&ndroot, NDF_ONLY_PNBUF);
-               vrele(ndroot.ni_vp);
-       }
-       return error;
+       /*
+        * 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:
 
-bad:
-       NDFREE(&ndroot, NDF_ONLY_PNBUF);
-       vrele(ndroot.ni_vp);
-       NDFREE(&nd, NDF_ONLY_PNBUF);
-       vrele(nd.ni_vp);
        free(buf, M_TEMP);
-       return error;
+       return (error);
 }
index dd21cb2..924aa56 100644 (file)
@@ -29,7 +29,7 @@
  * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp
  * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp
  * $FreeBSD: src/sys/compat/linux/linux_util.h,v 1.12.2.2 2000/11/02 23:31:28 obrien Exp $
- * $DragonFly: src/sys/emulation/linux/linux_util.h,v 1.5 2003/08/27 06:30:03 rob Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_util.h,v 1.6 2003/11/13 04:04:42 daver Exp $
  */
 
 /*
 #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);
 
@@ -75,23 +89,6 @@ stackgap_alloc(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                                                                    \
 linux_ ## s(struct linux_ ## s ## _args *args)                         \
index 1cb5a7d..9710d91 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
  * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.26 2003/11/12 10:11:09 daver Exp $
+ * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.27 2003/11/13 04:04:42 daver Exp $
  */
 
 #include <sys/param.h>
@@ -1172,44 +1172,56 @@ mknod(struct mknod_args *uap)
        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 8d9fca6..7504e47 100644 (file)
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/kern_syscall.h,v 1.12 2003/11/12 01:00:33 daver Exp $
+ * $DragonFly: src/sys/sys/kern_syscall.h,v 1.13 2003/11/13 04:04:42 daver Exp $
  */
 
 #ifndef _SYS_KERN_SYSCALL_H_
@@ -127,6 +127,7 @@ int kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res);
 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);