[comp.unix.wizards] telldir usage

fnf@estinc.UUCP (Fred Fish) (03/31/89)

Is it legal to do a telldir on an open directory, close the directory,
and then come back later to open the directory and use the telldir
value in a seekdir call to pick up where you left off?  I've seen
this topic discussed previously on the net, and had thought that the
consensus was that this was a special case supported by the directory
reading routines.  The manual for telldir states:

	  seekdir sets the position of the next	readdir	operation on
	  the directory	stream.	 The new position reverts to the one
	  associated with the directory	stream when the	telldir
	  operation was	performed.  Values returned by telldir are
	  good only for	the lifetime of	the DIR	pointer	from which
	  they are derived.  If	the directory is closed	and then
	  reopened, the	telldir	value may be invalidated due to
	  undetected directory compaction.

which seems to state that such operation is not legal.  However, it
then goes on to say:

	  It is safe to use a previous telldir value immediately after
	  a call to opendir and before any calls to readdir.

The sample program below works on Ultrix, the only BSD based system
I have immediate access to, but fails on a pyramid in the att universe.
The failure mode on the pyramid is that dirpos remains stuck at zero
and the program loops printing "0 ."

Similar code works fine on all of the System V machines I have access
to that have been retrofitted with the directory reading routines.

Is the pyramid broken?  Does this work on most machines simply by
luck and thus breaks on the pyramid since it is "officially illegal"?
What sayeth the wizards...

=================================  cut here =========================
#include <stdio.h>
#include <sys/types.h>

#ifdef SYSV
#  include <sys/ndir.h>
#  define DSTRUCT direct
#else
#  include <dirent.h>
#  define DSTRUCT dirent
#endif

main ()
{
    register int needseek = 0;
    register DIR *dirp = NULL;
    register long dirpos = 0L;
    register struct DSTRUCT *dbuf;

    for (;;) {
	if ((dirp = opendir (".")) == NULL) {
	    perror ("can't open '.'");
	    break;
	}
	if (needseek) {
	    seekdir (dirp, dirpos);
	}
	if ((dbuf = readdir (dirp)) == NULL) {
	    break;
	} else {
	    dirpos = telldir (dirp);
	    printf ("%8ld %s\n", dirpos, dbuf -> d_name);
	    closedir (dirp);
	    needseek = 1;
	}
    }
    if (dirp != NULL) {
	closedir (dirp);
    }
}
=================================  cut here =========================

-Fred
-- 
# Fred Fish, 1835 E. Belmont Drive, Tempe, AZ 85284,  USA
# 1-602-491-0048           asuvax!{nud,mcdphx}!estinc!fnf

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/04/89)

In article <76@estinc.UUCP> fnf@estinc.UUCP (Fred Fish) writes:
>Is it legal to do a telldir on an open directory, close the directory,
>and then come back later to open the directory and use the telldir
>value in a seekdir call to pick up where you left off?

From the manual entry I provide with my public-domain implementation
of the directory access routines:

DESCRIPTION
...
Telldir returns the current position associated with the named directory
stream for later use as an argument to seekdir.

Seekdir sets the position of the next readdir operation on the named
directory stream.  The new position reverts to the one associated with
the directory stream when the telldir operation from which loc was
obtained was performed.
...
WARNINGS
...
The value returned by telldir need not have any simple interpretation
and should only be used as an argument to seekdir.  Similarly, the loc
argument to seekdir must be obtained from a previous telldir operation
on the same directory stream.

Telldir and seekdir are unreliable when used in conjunction with file
systems that perform directory compaction or expansion or when the
directory stream has been closed and reopened.  It is best to avoid
using telldir and seekdir altogether.