Mail Archives: djgpp-workers/1996/11/05/01:02:35
On Mon, 4 Nov 1996, DJ Delorie wrote:
> > subst drive, findfirst for "s:/" (if s is substed) does not
> > report "." but findfirst for "s:/*.*" reports ".". The result of
> > this is, when you do
>
> Why would findfirst("s:/") return *anything*? It's a directory, not a
> wildcard.
Robert have chosen an unclear wording IMHO. The real problem as far as I
can see it is that `opendir' called findfirst("s:/") instead of
findfirst("s:/*.*") where it tried to see if "." is returned from the
directory. It just happens that *real* root directories always fail
`findfirst', so this code worked. But on a SUBSTed drive, `findfirst'
succeeds for the root directory, and that's where the bug became obvious.
What Robert *meant* to say (I think) was that a call like findfirst("s:/")
succeeds but doesn't return a ".", and so `opendir' thinks it must fake
"." and "..", but then `readdir' also finds "." and ".." on its own, so
you get them twice.
Btw: is it safe to assume that if a "." is found, then ".." will also be
found, and that "." is always the first entry returned by `findfirst'?
The original code did that, and I didn't change this in the patch below,
but I wonder whether some network redirector could pull a trick on us.
Here's the fix (tested with `ls' on a SUBSTed drive):
*** src/libc/posix/dirent/opendir.c~0 Mon Nov 4 18:25:18 1996
--- src/libc/posix/dirent/opendir.c Mon Nov 4 18:33:58 1996
***************
*** 34,51 ****
/* Make absolute path */
_fixpath(name, dir->name);
- /* If we're doing opendir of the root directory, we need to
- fake out the . and .. entries, as some unix programs (like
- mkisofs) expect them and fail if they don't exist */
- dir->need_fake_dot_dotdot = 0;
- if (dir->name[1] == ':' && dir->name[2] == '/' && dir->name[3] == 0)
- {
- /* see if findfirst finds "." anyway */
- int done = findfirst(dir->name, &dir->ff, FA_ARCH|FA_RDONLY|FA_DIREC|FA_SYSTEM);
- if (done || strcmp(dir->ff.ff_name, "."))
- dir->need_fake_dot_dotdot = 2;
- }
-
/* Ensure that directory to be accessed exists */
if (access(dir->name, D_OK))
{
--- 34,39 ----
***************
*** 69,79 ****
break;
}
}
-
dir->name[length++] = '/';
dir->name[length++] = '*';
dir->name[length++] = '.';
dir->name[length++] = '*';
dir->name[length++] = 0;
return dir;
}
--- 57,79 ----
break;
}
}
dir->name[length++] = '/';
dir->name[length++] = '*';
dir->name[length++] = '.';
dir->name[length++] = '*';
dir->name[length++] = 0;
+
+ /* If we're doing opendir of the root directory, we need to
+ fake out the . and .. entries, as some unix programs (like
+ mkisofs) expect them and fail if they don't exist */
+ dir->need_fake_dot_dotdot = 0;
+ if (dir->name[1] == ':' && dir->name[2] == '/' && length == 7)
+ {
+ /* see if findfirst finds "." anyway */
+ if (findfirst(dir->name, &dir->ff, FA_ARCH|FA_RDONLY|FA_DIREC)
+ || strcmp(dir->ff.ff_name, "."))
+ dir->need_fake_dot_dotdot = 2;
+ }
+
return dir;
}
- Raw text -