From: "Tim Van Holder" To: Subject: Re: Draft patch for opendir() extension Date: Wed, 27 Dec 2000 01:25:11 +0100 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" 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 Content-Transfer-Encoding: 8bit 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 Precedence: bulk > 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 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.