summaryrefslogtreecommitdiff
path: root/sys/compat/linux
diff options
context:
space:
mode:
authorjdolecek <jdolecek@NetBSD.org>2002-03-24 00:32:34 +0000
committerjdolecek <jdolecek@NetBSD.org>2002-03-24 00:32:34 +0000
commit0b5e2aba9af1003d22f4c5704091cbda2f1fa2d7 (patch)
tree31825e730d1218d3ac7a132ca84d5d6d42663eb3 /sys/compat/linux
parent2a593e4ce5dda0fa1b7d073ae9e690a768a1f34e (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.c99
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;