From owner-freebsd-hackers@FreeBSD.ORG Fri Nov 18 21:06:16 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 1233) id 18DED106567A; Fri, 18 Nov 2011 21:06:16 +0000 (UTC) Date: Fri, 18 Nov 2011 21:06:16 +0000 From: Alexander Best To: Tim Kientzle Message-ID: <20111118210616.GA15763@freebsd.org> References: <20111117175514.274040@gmx.com> <20111117214805.GA96937@freebsd.org> <34A2877A-977A-4668-8E37-642C6062AAC1@kientzle.com> <20111118205325.GA12245@freebsd.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20111118205325.GA12245@freebsd.org> Cc: freebsd-hackers@freebsd.org Subject: Re: easy way to determine if a stream or fd is seekable X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Nov 2011 21:06:16 -0000 On Fri Nov 18 11, Alexander Best wrote: > On Fri Nov 18 11, Tim Kientzle wrote: > > On Nov 17, 2011, at 1:48 PM, Alexander Best wrote: > > > > > On Thu Nov 17 11, Dieter BSD wrote: > > >>> lseek() on a tape drive does not return an error, nor does it > > >>> actually do anything. > > >> > > >> IIRC some tape drives can seek, while others cannot. > > >> Vague memories that it is supposed to be possible to put a > > >> filesystem on a DECtape and mount the filesystem. > > > > > > or how about the following: > > > > > > 1) if the file argument we're seeking on is a tape drive, just do a regular > > > seek operation. > > > 2) afterwards use ftell() to verify that the seek REALLY happend. if it didn't, > > > return -1 and set errno = EBADF. > > > > ftell() can't tell whether the seek really happened or not. > > All it can do is ask the kernel, and the kernel doesn't know. > > > > Here is my current understanding: > > > > When you call lseek(), the kernel just stores the requested > > offset in the file descriptor. lseek() always succeeds because > > storing the requested offset in the file descriptor always succeeds. > > (Except that the kernel specially checks if the file descriptor > > is a pipe.) > > > > ftell() just obtains the data from the file descriptor. > > So it always succeeds and always returns the data from > > the previous seek request, regardless of whether that seek > > actually did anything. > > > > With the next read or write request, the device driver may inspect the > > offset information in the file descriptor. Or it can ignore > > it. Almost all tape device drivers ignore it. Filesystems > > uniformly support it. Disk drivers uniformly support it. > > Other drivers vary considerably. > > > > In short: No, there is no "easy way" to determine if an > > arbitrary stream or fd is seekable. If you try to create > > a function that determines this, be certain to include > > "Don't Know" as a possible return value. > > well it really depends what the goal is. it appears fixing fseek() for all > cases is impossible then. however from a pragmatic point of view: > > why does a user have to wait for a command such as hd(1) or dd(1) working on > files such as /dev/zero, /dev/null, /dev/(u)random or even /dev/ada* (only > hd(1) -- dd(1) supports seeking here) for ages, although it could suceed in > less than a second? > > the fact is: users care for speed and freebsd is slower than linux and openbsd > in these cases. users aren't interested in the fact that lseek() won't work > with tapes. most of them have probably never seen one (me included). > > if we return an error from within lseek() whenever lseek() was fired at a tape > drive, wouldn't that cover 99% of all the possible cases? something like the following inside lseek() would take care of tape drives: if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) { if (ioctl(io->fd, FIODTYPE, &type) == -1) err(1, "%s", io->name); if (type & D_TAPE) return(EBADF) } cheers. alex > > cheers. > alex > > > > > Tim