delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/12/26/19:45:56

From: "Tim Van Holder" <tim DOT van DOT holder AT pandora DOT be>
To: <djgpp-workers AT delorie DOT com>
Subject: Re: Draft patch for opendir() extension
Date: Wed, 27 Dec 2000 01:25:11 +0100
Message-ID: <NEBBIOJNGMKPNOBKHCGHGEBECAAA.tim.van.holder@pandora.be>
MIME-Version: 1.0
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0)
In-reply-to: <2593-Tue26Dec2000190505+0200-eliz@is.elta.co.il>
Importance: Normal
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400
X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id TAA10172
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

> 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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019