diff options
| author | jdolecek <jdolecek@NetBSD.org> | 2002-03-24 00:32:34 +0000 |
|---|---|---|
| committer | jdolecek <jdolecek@NetBSD.org> | 2002-03-24 00:32:34 +0000 |
| commit | 0b5e2aba9af1003d22f4c5704091cbda2f1fa2d7 (patch) | |
| tree | 31825e730d1218d3ac7a132ca84d5d6d42663eb3 /sys/compat/linux | |
| parent | 2a593e4ce5dda0fa1b7d073ae9e690a768a1f34e (diff) | |
Fix problem with assumption non-socket == vnode in F_{G,S}ETOWN different way
(revisions 1.47 & 1.48 effectively backed off):
* for all but vnodes, just fallback to sys_fcntl(); assumming
state of support for F_SETOWN/F_GETOWN and even hardcoding it here is
not right (e.g. rev. 1.47 had this incorrect for DTYPE_PIPE)
* fallback to sys_fcntl() also for vnodes which don't represent tty
* don't need to use FILE_{,UN}USE() here, the code won't block while
using the pointer
* add/fix some comments
Diffstat (limited to 'sys/compat/linux')
| -rw-r--r-- | sys/compat/linux/common/linux_file.c | 99 |
1 files changed, 38 insertions, 61 deletions
diff --git a/sys/compat/linux/common/linux_file.c b/sys/compat/linux/common/linux_file.c index 7eecc4ad1b3..6c11cfa6dc9 100644 --- a/sys/compat/linux/common/linux_file.c +++ b/sys/compat/linux/common/linux_file.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_file.c,v 1.48 2002/03/23 15:36:15 christos Exp $ */ +/* $NetBSD: linux_file.c,v 1.49 2002/03/24 00:32:34 jdolecek Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_file.c,v 1.48 2002/03/23 15:36:15 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_file.c,v 1.49 2002/03/24 00:32:34 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -413,77 +413,54 @@ linux_sys_fcntl(p, v, retval) case LINUX_F_SETOWN: case LINUX_F_GETOWN: /* - * We need to route around the normal fcntl() for these calls, - * since it uses TIOC{G,S}PGRP, which is too restrictive for - * Linux F_{G,S}ETOWN semantics. For sockets, this problem - * does not exist. + * We need to route fcntl() for tty descriptors around normal + * fcntl(), since NetBSD tty TIOC{G,S}PGRP semantics is too + * restrictive for Linux F_{G,S}ETOWN. For non-tty descriptors, + * this is not a problem. */ fdp = p->p_fd; if ((fp = fd_getfile(fdp, fd)) == NULL) return EBADF; - - FILE_USE(fp); - switch (fp->f_type) { - case DTYPE_SOCKET: + if (fp->f_type != DTYPE_VNODE) { + notty: + /* Not a tty, proceed with common fcntl() */ cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; - FILE_UNUSE(fp, p); - goto doit; - - case DTYPE_VNODE: - vp = (struct vnode *)fp->f_data; - if (vp->v_type != VCHR) { - error = EINVAL; - goto done; - } - if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) - goto done; - - d_tty = cdevsw[major(va.va_rdev)].d_tty; - if (!d_tty || (tp = (*d_tty)(va.va_rdev)) == NULL) { - error = EINVAL; - goto done; - } - if (cmd == LINUX_F_GETOWN) { - retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id - : NO_PID; - error = 0; - goto done; - } - if ((long)arg <= 0) { - pgid = -(long)arg; - } else { - struct proc *p1 = pfind((long)arg); - if (p1 == NULL) { - error = ESRCH; - goto done; - } - pgid = (long)p1->p_pgrp->pg_id; - } - pgrp = pgfind(pgid); - if (pgrp == NULL || pgrp->pg_session != p->p_session) { - error = EPERM; - goto done; - } - tp->t_pgrp = pgrp; - error = 0; - goto done; - - case DTYPE_PIPE: - error = EINVAL; - goto done; + break; + } - default: - panic("linux_fcntl: Bad file %d\n", fp->f_type); + /* check that the vnode is a tty */ + vp = (struct vnode *)fp->f_data; + if (vp->v_type != VCHR) + goto notty; + if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) + return error; + d_tty = cdevsw[major(va.va_rdev)].d_tty; + if (!d_tty || (!(tp = (*d_tty)(va.va_rdev)))) + goto notty; + + /* set tty pg_id appropriately */ + if (cmd == LINUX_F_GETOWN) { + retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; + return 0; } + if ((long)arg <= 0) { + pgid = -(long)arg; + } else { + struct proc *p1 = pfind((long)arg); + if (p1 == NULL) + return (ESRCH); + pgid = (long)p1->p_pgrp->pg_id; + } + pgrp = pgfind(pgid); + if (pgrp == NULL || pgrp->pg_session != p->p_session) + return EPERM; + tp->t_pgrp = pgrp; + return 0; -done: - FILE_UNUSE(fp, p); - return error; default: return EOPNOTSUPP; } -doit: SCARG(&fca, fd) = fd; SCARG(&fca, cmd) = cmd; SCARG(&fca, arg) = arg; |
