From: David P. Reese, Jr. Date: Thu, 13 Nov 2003 04:04:42 +0000 (+0000) Subject: Split mkfifo(). X-Git-Tag: v2.0.1~12649 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/136178b326fbf33f2d1bae4700fe50c5b0d2e766 Split mkfifo(). 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(). --- diff --git a/sys/emulation/linux/i386/linux_machdep.c b/sys/emulation/linux/i386/linux_machdep.c index 5c75cca71d..d0013e9d36 100644 --- a/sys/emulation/linux/i386/linux_machdep.c +++ b/sys/emulation/linux/i386/linux_machdep.c @@ -26,14 +26,16 @@ * 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 #include +#include #include #include #include +#include #include #include #include @@ -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); } diff --git a/sys/emulation/linux/i386/linux_sysvec.c b/sys/emulation/linux/i386/linux_sysvec.c index 738bda5701..fa3d34f48d 100644 --- a/sys/emulation/linux/i386/linux_sysvec.c +++ b/sys/emulation/linux/i386/linux_sysvec.c @@ -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); diff --git a/sys/emulation/linux/linux_file.c b/sys/emulation/linux/linux_file.c index f2291b39b3..6680311da8 100644 --- a/sys/emulation/linux/linux_file.c +++ b/sys/emulation/linux/linux_file.c @@ -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 #include #include +#include #include #include #include @@ -60,123 +61,121 @@ 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); } diff --git a/sys/emulation/linux/linux_misc.c b/sys/emulation/linux/linux_misc.c index eb49403e92..81b6a07808 100644 --- a/sys/emulation/linux/linux_misc.c +++ b/sys/emulation/linux/linux_misc.c @@ -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); } diff --git a/sys/emulation/linux/linux_stats.c b/sys/emulation/linux/linux_stats.c index 345186e7ba..633977a538 100644 --- a/sys/emulation/linux/linux_stats.c +++ b/sys/emulation/linux/linux_stats.c @@ -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 @@ -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 diff --git a/sys/emulation/linux/linux_uid16.c b/sys/emulation/linux/linux_uid16.c index 462e7e8256..f49e645ce8 100644 --- a/sys/emulation/linux/linux_uid16.c +++ b/sys/emulation/linux/linux_uid16.c @@ -24,15 +24,18 @@ * 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 #include +#include +#include #include #include +#include #include #include @@ -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); } diff --git a/sys/emulation/linux/linux_util.c b/sys/emulation/linux/linux_util.c index e2b0481df8..6d01d69e95 100644 --- a/sys/emulation/linux/linux_util.c +++ b/sys/emulation/linux/linux_util.c @@ -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 @@ -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; + *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); } diff --git a/sys/emulation/linux/linux_util.h b/sys/emulation/linux/linux_util.h index dd21cb226e..924aa56954 100644 --- a/sys/emulation/linux/linux_util.h +++ b/sys/emulation/linux/linux_util.h @@ -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 $ */ /* @@ -50,6 +50,20 @@ #include #include +#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) \ diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 1cb5a7d2c8..9710d91586 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -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 @@ -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); } diff --git a/sys/sys/kern_syscall.h b/sys/sys/kern_syscall.h index 8d9fca677a..7504e4727e 100644 --- a/sys/sys/kern_syscall.h +++ b/sys/sys/kern_syscall.h @@ -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);