easy way to determine if a stream or fd is seekable
Alexander Best
arundel at freebsd.org
Wed Nov 16 10:14:23 UTC 2011
On Tue Nov 15 11, Brandon Gooch wrote:
> 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.
if this really is the case, things could even be easier in a freebsd specific
manor than the code above:
!S_ISFIFO(m) && !S_ISSOCK(m)
this means it would be trivial to write a new macro S_ISSEEK which would test
stat.st_mode against the according bits.
cheers.
alex
>
> Need to think about this more before commenting further...
>
> -Brandon
More information about the freebsd-hackers
mailing list