easy way to determine if a stream or fd is seekable

Brandon Gooch jamesbrandongooch at gmail.com
Wed Nov 16 03:01:42 UTC 2011


On Nov 15, 2011 2:25 PM, "Alexander Best" <arundel at freebsd.org> wrote:
>
> hi there,
>
> one of the things i'm missing is an easy way to determine, whether a
stream or
> fd is seekable. i checked the dd(1) and hd(1) sources and those tools are
> performing so much stuff just to find out if this is the case, and they
still
> are doing a very poor job.
>
> dd(1) e.g. identifies /dev/zero as non-seekable, even though it is. the
result:
>
> `dd if=/dev/zero bs=1m count=1 skip=100000`:
>
> on freebsd:
> 57,41 real         0,05 user        43,21 sys
>
> on openbsd:
> 0,88 real         0,00 user         0,07 sys
>
> on freebsd dd(1) is very easy fixable (1 line diff). the point however is:
>
> there doesn't seem to exist a unified way of checking seekable == TRUE. so
> every userspace application seems to do it differently and most of them
(dd(1)
> and hd(1) e.g) aren't doing it right. hd(1) e.g. believes that only
regular
> files are seekable. this means that hd(1) fired at /dev/ada* with a high
skip
> value takes ages! dd(1) is a bit smarter in this case, but still not
correct.
>
> idealy there would be something like stat.st_mode (see stat(2)) where one
> could simply do a S_ISSEEK(m). so far the best and easiest solution i've
seen
> is:
>
> fd = open(argv[1], O_RDONLY);
> if (fd == -1)
>   exit(1);
> if (lseek(fd, 0, SEEK_CUR) != -1)
>    printf ("%d is seekable.\n", fd);
> else
>    printf ("%d is not seekable.\n", fd);
>
> seeing an application iterate through a stream or fd via getchar(),
although
> a simple seek() would work is very frustrating. i think what would be
needed
> is a simple function or macro that userspace applications can make use of.
> maybe such a thing already exists in linux, openbsd, netbsd, dragonflybsd,
> solaris or plan9?
>
> cheers.
> alex
>
> references:
> [1]
http://www.mavetju.org/mail/view_thread.php?list=freebsd-hackers&id=3290708&thread=yes
> [2] http://www.freebsd.org/cgi/query-pr.cgi?pr=152485
> [3] http://www.freebsd.org/cgi/query-pr.cgi?pr=86485

So, according to APUE 2nd Edition, seek should be supported on anything
that's not a pipe, FIFO, or socket.  In fact, the "test for seekability"
you've provided above closely resembles the example given in that text.

Need to think about this more before commenting further...

-Brandon


More information about the freebsd-hackers mailing list