[net.bugs.4bsd] Bug in 4.1C seekdir

ra@rlgvax.UUCP (Rick Adams) (10/06/83)

If you have a directory with 1 entry in it and you do the following
sequence:

	dirp = opendir("whatever");
	dp = readdir(dirp);
	rewinddir(dirp);
	dp2 = readdir(dirp);

The second readdir will NOT find the file. This is because of an
optimization in seekdir (rewinddir is a macro defined as
seekdir(dirp,0L)) The optimization fails in the special case of a seek
to location 0 while you are in the first block.

The optimization is an attempt to avoid re-reading the directory block
when the block is already in the buffer. Unfortunately, readdir uses a
pointer to location 0 as a flag to read in the next block, so a true
seek must be done.

The following diff shows a fix:

*** seekdir.c.old	Wed Oct  5 19:53:08 1983
--- seekdir.c	Wed Oct  5 19:03:22 1983
***************
*** 22,28
  		return;
  	base = loc & ~(DIRBLKSIZ - 1);
  	offset = loc & (DIRBLKSIZ - 1);
! 	if (dirp->dd_loc != 0 && (curloc & ~(DIRBLKSIZ - 1)) == base) {
  		dirp->dd_loc = offset;
  		return;
  	}

--- 23,29 -----
  		return;
  	base = loc & ~(DIRBLKSIZ - 1);
  	offset = loc & (DIRBLKSIZ - 1);
! 	if (dirp->dd_loc != 0 && offset != 0 && (curloc & ~(DIRBLKSIZ - 1)) == base) {
  		dirp->dd_loc = offset;
  		return;
  	}

Some versions of uucp use rewinddir() to re-read the work directory
instead of closing and re-opening the directory.
This bug will cause entries to be missed unless it is corrected.


Rick Adams
{seismo|ihnp4|allegra|mcnc}!rlgvax!ra