Mail Archives: djgpp-workers/2000/12/26/19:45:56
> The above just passes the name of the file, not the directory where it
> ``lives''.
Hmm. I thought that an fsext_open hook got the name as passed to open().
If not, how would the /dev/zero support know it's being asked for
/dev/zero and not d:/my/favorite/numbers/zero?
And for the non-fsext entries you mention below, they can just pass
the full filename. The only difficulty would be to decide which names
to run fixpath on; after all, we'd generally want this, but not for
files in /dev (oherwise, we'd only list them for the current drive).
> Also, all /dev/* devices supported now don't have an associated
> fsext. So not only an fsext will need this.
Right - so a register call would be needed at startup, and a deregister
at shutdozn.
> > > - Can fake entries be registered before an opendir call for their
> > > parent directory? Can they be deregistered before closedir is
> > > called?
> > Yes, but that would not have an effect - the list of fake entries is
> > added to the DIR structure during opendir and is not changed.
> Again, this doesn't go along with the current ``emulation'' of
> /dev/null and other devices: they are always present.
I don't see your point - given that they always exist, there should be no
need to register/deregister them after an opendir(). If need be, you could
rebuild the list of fake entries in rewinddir().
> What about the /dev/ directory itself? It doesn't really exist, so
> some means are required to make opendir think it does.
I already handled this - as I said, that's why I added the exists field to
DIR. If a directory is opened that doesn't exist, but does have fake entries,
opendir() will succeed (with DIR->exists = 0). This is checked by readdir to
determine whether or not it should do a findfirst/findnext after returning
all fake entries.
> > > Anyway, I'm not sure what is the bug you are trying to solve. Can you
> > > give an example of a series of calls to opendir, readdir, telldir, and
> > > seekdir where the current implementation fails?
> > D = opendir ("/"); // has entries: foo, bar, hello, world and xyzzy
> > readdir (D); // '.'
> > readdir (D); // '..'
> > readdir (D); // 'foo'
> > readdir (D); // 'bar'
> > readdir (D); // 'hello'
> > readdir (D); // 'world'
> > pos = telldir(D); // pos gets 4, as that's the number of real entries read
> > seekdir (D, pos); // rewinds, calles readdir pos times
>
> This could be solved by replacing this code:
>
> rewinddir(dir);
> for (i=0; i<loc; i++)
> readdir(dir);
>
> with this:
>
> rewinddir(dir);
> while (dir->num_read <= loc)
> readdir(dir);
>
Not quite. If both . and .. are being emulated, a telldir() after the first
or second readdir() would still return 0, causing a seekdir() to simply call
rewinddir(). The current CVS code doesn't increment num_read until it starts
to read real entries using findfirst/findnext.
The patch I sent handles all these cases.
> > > I also don't understand why do you need both fsext_entries and
> > > fsext_entry, since they both are used to index into the same array.
> > > Isn't num_read enough for that?
> > Actually, fsext_entries is an array of strings, fsext_entry is used
> > to index into it. Using num_read only would require also keeping the
> > number of strings in the fsext_entries array and then computing where
> > we were in the list.
> Isn't the list in fsext_entries[] NULL-terminated? If so, you don't
> need to know how many entries are there, you just go on until you hit
> NULL.
My point remains.
Now I distinguish states this way:
num_read < need_fake_dot_dotdot ?
=> return fake . or ..
fsext_entry != NULL ?
=> return *fsext_entry,
and if *(++fsext_entry) == NULL, fsext_entry = NULL
exists == 0 ?
=> return 0
exists == 1 ?
=> return findfirst(), set exists to 2
otherwise (exists == 2) ?
=> return findnext()
Without fsext_entry, I'd need to rely solely on num_read, leading to:
num_read < need_fake_dot_dotdot ?
=> return fake . or ..
otherwise ?
=> idx = num_read - need_fake_dot_dotdot
for (i = 0; i < idx; ++i)
if (fsext_entries[i] == NULL)
break;
}
i == idx ?
=> fsext_entries[i] != NULL ?
=> return fsext_entries[i]
otherwise ?
=> return findfirst
otherwise (i != idx) ?
=> return findnext()
The second method saves 4 bytes in the DIR structure, but has a greater
overhead in readdir() (unless I'm seeing this wrong, and there is a more
elegant way of doing it). I decided the size increase for DIR was preferable
over the readdir() overhead.
- Raw text -