From owner-freebsd-bugs@FreeBSD.ORG Mon Apr 19 23:30:22 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BB7DF16A4CE for ; Mon, 19 Apr 2004 23:30:22 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9D6C043D4C for ; Mon, 19 Apr 2004 23:30:22 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i3K6UMbv044832 for ; Mon, 19 Apr 2004 23:30:22 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i3K6UM0p044824; Mon, 19 Apr 2004 23:30:22 -0700 (PDT) (envelope-from gnats) Date: Mon, 19 Apr 2004 23:30:22 -0700 (PDT) Message-Id: <200404200630.i3K6UM0p044824@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Bruce Evans Subject: Re: kern/65786: Incorrect fifo semantics X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Bruce Evans List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Apr 2004 06:30:23 -0000 The following reply was made to PR kern/65786; it has been noted by GNATS. From: Bruce Evans To: Guido Laubner Cc: freebsd-gnats-submit@freebsd.org, freebsd-bugs@freebsd.org Subject: Re: kern/65786: Incorrect fifo semantics Date: Tue, 20 Apr 2004 16:26:47 +1000 (EST) On Mon, 19 Apr 2004, Guido Laubner wrote: > >Description: > I found a strange behaviour of dd. Digging into it I believe it's a > problem of the fifo created by mkfifo(2). > It looks like the fifo allows (and reports correct return codes) for > lseek(2), but when reading form the fifo after the lseek advancing the "read cursor", reading starts from position 0. > Comparing this with a pipe, the pipe behaves correctly : > It allows for lseek and reading starts at the position given in the lseek(2) syscall. > Assuming the pipe is correct, the fifo is not implemented correctly in that is does not position the read "cursor" for the next read properly. > If my assumption is wrong (so the pipe semantics would not hold for > a fifo) the lseek syscall to a fifo should return an error. lseek() on fifos shall return an error. From POSIX.1-2001-draft7: % 23980 The lseek( ) function shall fail if: % ... % 23986 [ESPIPE] The fildes argument is associated with a pipe, FIFO, or socket. This was fixed in 1996 in rev.1.52 of vfs_syscalls.c and associated changes, but was broken in 2003 in rev.1.319 of vfs_syscalls.c and associated changes. % Index: vfs_syscalls.c % =================================================================== % RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v % retrieving revision 1.318 % retrieving revision 1.319 % diff -u -2 -r1.318 -r1.319 % --- vfs_syscalls.c 11 Jun 2003 00:56:59 -0000 1.318 % +++ vfs_syscalls.c 18 Jun 2003 19:53:59 -0000 1.319 % ... % @@ -1342,5 +1342,5 @@ % if ((error = fget(td, uap->fd, &fp)) != 0) % return (error); % - if (fp->f_type != DTYPE_VNODE) { % + if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) { % fdrop(fp, td); % return (ESPIPE); The bug in rev.1.319 is that fifos use the same f_ops as regular files, so they cannot be distinguished from regular files using f_ops. Rev.1.52 worked by putting their classification in f_type and using it here and in a couple of other places. Fifos are still classified by f_type, but the correct fix is not as simple as changing the above to: if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE) || fp->f_type != DTYPE_VNODE) { ... since several places would need to be changed similarly and then the changes in rev.1.352 would increase the number of special cases a lot instead of reducing it a little. lseek() is also broken for device files (seeking on ttys and /dev/null bogusly succeeds), but this is an old bug. Some devices are seekable, so lseek() must work for them, but there is no way for indivual devices to indicate if they support seeking so lseek() must works for all devices. Breaking lseek() of course confuses any program that expects lseek() to actually work if it returns successfully, and are used on files where it is broken. Such program/usage combinations are apparently surprisingly rare. The problem only showed up here in a fifo test program. dd knows not to trust lseek() on devices only. Bruce