Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/compat/linux/common/linux_file.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/compat/linux/common/linux_file.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.105 retrieving revision 1.106 diff -u -p -r1.105 -r1.106 --- src/sys/compat/linux/common/linux_file.c 2013/09/24 13:27:50 1.105 +++ src/sys/compat/linux/common/linux_file.c 2013/11/18 01:32:52 1.106 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_file.c,v 1.105 2013/09/24 13:27:50 njoly Exp $ */ +/* $NetBSD: linux_file.c,v 1.106 2013/11/18 01:32:52 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: linux_file.c,v 1.105 2013/09/24 13:27:50 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_file.c,v 1.106 2013/11/18 01:32:52 chs Exp $"); #include #include @@ -155,6 +155,32 @@ linux_sys_creat(struct lwp *l, const str return sys_open(l, &oa, retval); } +static void +linux_open_ctty(struct lwp *l, int flags, int fd) +{ + struct proc *p = l->l_proc; + + /* + * this bit from sunos_misc.c (and svr4_fcntl.c). + * If we are a session leader, and we don't have a controlling + * terminal yet, and the O_NOCTTY flag is not set, try to make + * this the controlling terminal. + */ + if (!(flags & O_NOCTTY) && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) { + file_t *fp; + + fp = fd_getfile(fd); + + /* ignore any error, just give it a try */ + if (fp != NULL) { + if (fp->f_type == DTYPE_VNODE) { + (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, NULL); + } + fd_putfile(fd); + } + } +} + /* * open(2). Take care of the different flag values, and let the * NetBSD syscall do the real work. See if this operation @@ -169,7 +195,6 @@ linux_sys_open(struct lwp *l, const stru syscallarg(int) flags; syscallarg(int) mode; } */ - struct proc *p = l->l_proc; int error, fl; struct sys_open_args boa; @@ -182,25 +207,32 @@ linux_sys_open(struct lwp *l, const stru if ((error = sys_open(l, &boa, retval))) return error; - /* - * this bit from sunos_misc.c (and svr4_fcntl.c). - * If we are a session leader, and we don't have a controlling - * terminal yet, and the O_NOCTTY flag is not set, try to make - * this the controlling terminal. - */ - if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) { - file_t *fp; + linux_open_ctty(l, fl, *retval); + return 0; +} - fp = fd_getfile(*retval); +int +linux_sys_openat(struct lwp *l, const struct linux_sys_openat_args *uap, register_t *retval) +{ + /* { + syscallarg(const char *) path; + syscallarg(int) flags; + syscallarg(int) mode; + } */ + int error, fl; + struct sys_openat_args boa; - /* ignore any error, just give it a try */ - if (fp != NULL) { - if (fp->f_type == DTYPE_VNODE) { - (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, NULL); - } - fd_putfile(*retval); - } - } + fl = linux_to_bsd_ioflags(SCARG(uap, flags)); + + SCARG(&boa, fd) = SCARG(uap, fd); + SCARG(&boa, path) = SCARG(uap, path); + SCARG(&boa, oflags) = fl; + SCARG(&boa, mode) = SCARG(uap, mode); + + if ((error = sys_openat(l, &boa, retval))) + return error; + + linux_open_ctty(l, fl, *retval); return 0; } @@ -492,19 +524,34 @@ linux_sys_lstat(struct lwp *l, const str /* * The following syscalls are mostly here because of the alternate path check. */ + int -linux_sys_unlink(struct lwp *l, const struct linux_sys_unlink_args *uap, register_t *retval) +linux_sys_linkat(struct lwp *l, const struct linux_sys_linkat_args *uap, register_t *retval) { /* { - syscallarg(const char *) path; + syscallarg(int) fd1; + syscallarg(const char *) name1; + syscallarg(int) fd2; + syscallarg(const char *) name2; + syscallarg(int) flags; } */ - int error, error2; - struct pathbuf *pb; - struct nameidata nd; + int fd1 = SCARG(uap, fd1); + const char *name1 = SCARG(uap, name1); + int fd2 = SCARG(uap, fd2); + const char *name2 = SCARG(uap, name2); + int follow; - error = sys_unlink(l, (const void *)uap, retval); - if (error != EPERM) - return (error); + follow = SCARG(uap, flags) & LINUX_AT_SYMLINK_FOLLOW; + + return do_sys_linkat(l, fd1, name1, fd2, name2, follow, retval); +} + +static int +linux_unlink_dircheck(const char *path) +{ + struct nameidata nd; + struct pathbuf *pb; + int error; /* * Linux returns EISDIR if unlink(2) is called on a directory. @@ -514,9 +561,9 @@ linux_sys_unlink(struct lwp *l, const st * * XXX this should really not copy in the path buffer twice... */ - error2 = pathbuf_copyin(SCARG(uap, path), &pb); - if (error2) { - return error2; + error = pathbuf_copyin(path, &pb); + if (error) { + return error; } NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); if (namei(&nd) == 0) { @@ -529,8 +576,44 @@ linux_sys_unlink(struct lwp *l, const st vput(nd.ni_vp); } pathbuf_destroy(pb); + return error ? error : EPERM; +} - return (error); +int +linux_sys_unlink(struct lwp *l, const struct linux_sys_unlink_args *uap, register_t *retval) +{ + /* { + syscallarg(const char *) path; + } */ + int error; + + error = sys_unlink(l, (const void *)uap, retval); + if (error == EPERM) + error = linux_unlink_dircheck(SCARG(uap, path)); + + return error; +} + +int +linux_sys_unlinkat(struct lwp *l, const struct linux_sys_unlinkat_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(int) flag; + } */ + struct sys_unlinkat_args ua; + int error; + + SCARG(&ua, fd) = SCARG(uap, fd); + SCARG(&ua, path) = SCARG(uap, path); + SCARG(&ua, flag) = linux_to_bsd_atflags(SCARG(uap, flag)); + + error = sys_unlinkat(l, &ua, retval); + if (error == EPERM) + error = linux_unlink_dircheck(SCARG(uap, path)); + + return error; } int @@ -538,19 +621,39 @@ linux_sys_mknod(struct lwp *l, const str { /* { syscallarg(const char *) path; - syscallarg(int) mode; - syscallarg(int) dev; + syscallarg(linux_umode_t) mode; + syscallarg(unsigned) dev; + } */ + struct linux_sys_mknodat_args ua; + + SCARG(&ua, fd) = LINUX_AT_FDCWD; + SCARG(&ua, path) = SCARG(uap, path); + SCARG(&ua, mode) = SCARG(uap, mode); + SCARG(&ua, dev) = SCARG(uap, dev); + + return linux_sys_mknodat(l, &ua, retval); +} + +int +linux_sys_mknodat(struct lwp *l, const struct linux_sys_mknodat_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(linux_umode_t) mode; + syscallarg(unsigned) dev; } */ /* * BSD handles FIFOs separately */ if (S_ISFIFO(SCARG(uap, mode))) { - struct sys_mkfifo_args bma; + struct sys_mkfifoat_args bma; + SCARG(&bma, fd) = SCARG(uap, fd); SCARG(&bma, path) = SCARG(uap, path); SCARG(&bma, mode) = SCARG(uap, mode); - return sys_mkfifo(l, &bma, retval); + return sys_mkfifoat(l, &bma, retval); } else { /* @@ -559,11 +662,56 @@ linux_sys_mknod(struct lwp *l, const str * this just fits into our dev_t. Just mask off the * upper 16bit to remove any random junk. */ - return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode), - SCARG(uap, dev) & 0xffff, retval, UIO_USERSPACE); + + return do_sys_mknodat(l, SCARG(uap, fd), SCARG(uap, path), + SCARG(uap, mode), SCARG(uap, dev) & 0xffff, retval, + UIO_USERSPACE); } } +int +linux_sys_fchmodat(struct lwp *l, const struct linux_sys_fchmodat_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(linux_umode_t) mode; + } */ + + return do_sys_chmodat(l, SCARG(uap, fd), SCARG(uap, path), + SCARG(uap, mode), AT_SYMLINK_FOLLOW); +} + +int +linux_sys_fchownat(struct lwp *l, const struct linux_sys_fchownat_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(uid_t) owner; + syscallarg(gid_t) group; + syscallarg(int) flag; + } */ + int flag; + + flag = linux_to_bsd_atflags(SCARG(uap, flag)); + return do_sys_chownat(l, SCARG(uap, fd), SCARG(uap, path), + SCARG(uap, owner), SCARG(uap, group), flag); +} + +int +linux_sys_faccessat(struct lwp *l, const struct linux_sys_faccessat_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(const char *) path; + syscallarg(int) amode; + } */ + + return do_sys_accessat(l, SCARG(uap, fd), SCARG(uap, path), + SCARG(uap, amode), AT_SYMLINK_FOLLOW); +} + /* * This is just fsync() for now (just as it is in the Linux kernel) * Note: this is not implemented under Linux on Alpha and Arm