Discussion:
How to cope with non-terminated actions (like FindFirst/Next)
(too old to reply)
R.Wieser
2005-12-09 13:01:18 UTC
Permalink
Hello All,

My subject-line may be a bit fuzzy, but I hope this clears it up : I'm
trying to create a DOS IFS (Installable File System) that connects (using a
packet-driver) to another computer (running Windows). Yep, yet another
remote drive. :-)

The problem I'm having is with the way DOS does a Find-File. It never
terminates the action, so I don't know when to close the connection, and
clean-up (for both the DOS and the Windows ends of the connection).

Is there a (standard) mechanism that I can use for cases like these ? Or
does anyone know of a trick that has allready been used in other
remote-drive IFS programs ?

I would sure like to know :-)

Regards,
Rudy Wieser
Rod Pemberton
2005-12-09 23:29:34 UTC
Permalink
2nd post attempt...
Post by R.Wieser
Hello All,
My subject-line may be a bit fuzzy, but I hope this clears it up : I'm
trying to create a DOS IFS (Installable File System) that connects (using a
packet-driver) to another computer (running Windows). Yep, yet another
remote drive. :-)
The problem I'm having is with the way DOS does a Find-File. It never
terminates the action,
What are you expecting to "terminate the action"? Or, what do you mean by
DOS "never terminates the action"?
Post by R.Wieser
so I don't know when to close the connection, and
clean-up (for both the DOS and the Windows ends of the connection).
Is there a (standard) mechanism that I can use for cases like these ? Or
does anyone know of a trick that has allready been used in other
remote-drive IFS programs ?
I would sure like to know :-)
Regards,
Rudy Wieser
Well, let's hope someone else can answer your questions: I can't.

When it comes to DOS IFS's, everyone mentions MSCDEX extensions,
INT 2Fh (Multiplex) instead of INT 21h, and
Andrew Schulman's "Undocumented DOS", but
noone ever tells on the Internet how it is done...

My probably less than enlightening hints:
1) findfirst/next don't actually open anything, so what cleanup needs to be
done?
2) In addition to findfirst(), there is _dos_findfirst().
3) The LFN API has an explicit function "FindClose" int 0x21,AX=71a1h.
4) Use Henrik Haftmann's DOSLFN driver for LFN functions. DJGPP has LFN
support,
but Watcom doesn't. You can use "LFN Create or Open File"
int0x21, ax=716Ch followed by "Close file" int 0x21,ax=3eh to force
DOSLFN to update its internal cache when using Watcom.


Rod Pemberton
R.Wieser
2005-12-10 03:00:14 UTC
Permalink
Rod Pemberton <***@bitbucket.cmm> schreef in berichtnieuws
dnd3vq$dkb$***@domitilla.aioe.org...

Hello Rod,
Post by Rod Pemberton
2nd post attempt...
It looks like your first came thru too, but maybe a bit slow (just like mine
did :-) ).
Post by Rod Pemberton
Post by R.Wieser
Hello All,
I'm trying to create a DOS IFS (Installable File System) that
connects (using a packet-driver) to another computer (running
Windows). Yep, yet another remote drive. :-)
The problem I'm having is with the way DOS does a Find-File.
It never terminates the action,
What are you expecting to "terminate the action"? Or, what do
you mean by DOS "never terminates the action"?
What I expect ? Well, that's easy : nothing. And that is exactly the
problem : I do not expect DOS to send me a signal that it terminated it's
find-first & next, so I have to generate my own. But when ?
Post by Rod Pemberton
Post by R.Wieser
so I don't know when to close the connection, and
clean-up (for both the DOS and the Windows ends of the connection).
Is there a (standard) mechanism that I can use for cases like these ?
Or does anyone know of a trick that has allready been used in other
remote-drive IFS programs ?
I would sure like to know :-)
Regards,
Rudy Wieser
Well, let's hope someone else can answer your questions: I can't.
When it comes to DOS IFS's, everyone mentions MSCDEX extensions,
INT 2Fh (Multiplex) instead of INT 21h, and
Andrew Schulman's "Undocumented DOS", but
noone ever tells on the Internet how it is done...
INT 2Fh is exactly the method I'm using. Luckily I found a source-file of a
program that described some IFS data-structures Ralf Browns interrupt-list
did not specify. :-)

And yes, I had the same problem, there is no official, and little
non-official information about DOS IFS to be found on the Web.
Post by Rod Pemberton
1) findfirst/next don't actually open anything, so what cleanup needs to be
done?
The connection to the other computer (which is a simple hand-shaking
protocol).
Post by Rod Pemberton
2) In addition to findfirst(), there is _dos_findfirst().
Not for the IFS-interface there is not.
Post by Rod Pemberton
3) The LFN API has an explicit function "FindClose" int 0x21,AX=71a1h.
Sorry, but that is Windows-DOS (only usable in a DOS-box / DOS v7.x), not
available in real DOS versions.
Post by Rod Pemberton
4) Use Henrik Haftmann's DOSLFN driver for LFN functions.
I'm sorry again, but it's the OS that does the calls, the IFS-driver (that
I'm writing) can only respond to those request, and it (the IFS-driver) only
gets INT 2Fh AX=111Bh/111Ch. There is nothing I can change about that ...

But thanks for your response.

Regards,
Rudy Wieser
J French
2005-12-10 13:13:19 UTC
Permalink
On Sat, 10 Dec 2005 04:00:14 +0100, "R.Wieser" <***@not.available>
wrote:

<snip>

I'm not entirely sure what you are up to, but the basic DOS routine
is:

FindFirst
FindNext
FindClose

If your stuff is the only thing on the machine then you could set up a
flag and do

For: FindFirst
If Flag Then FindClose
FindFirst
Then
FindNext

Probably the best bet would be to hijack the Interrupt, check for
FindFirst and do a quiet FindClose if necessary

IIRC you also need to set the DTA before FindFirst and after
FindClose, otherwise one loses the Command Tail

This is for SFNs - I guess the same applies to LFNs
R.Wieser
2005-12-10 16:45:12 UTC
Permalink
J French <***@nowhere.uk> schreef in berichtnieuws
***@news.btopenworld.com...

Hello J.
Post by J French
I'm not entirely sure what you are up to, but the basic DOS
FindFirst
INT 21h, AH=4Eh
Post by J French
FindNext
INT 21h, AH=4Fh
Post by J French
FindClose
INT ??, AH=??

:-)

Mind you, this is *real* DOS, using 8.3 filenames.
Post by J French
If your stuff is the only thing on the machine then you could set up a
flag and do
For: FindFirst
If Flag Then FindClose
FindFirst
Then
FindNext
Sorry, but the code I'm writing is an IFS (INT 2Fh, AH=11h). It receives
certain commands and should try to satisfy them. The IFS has got no
controll over the program it's called by (not aware of any looping such a
program might, or might not do).
Post by J French
This is for SFNs - I guess the same applies to LFNs
LFN's ? In a real DOS environment (read : non DOS-box) ? :-)

Regards,
Rudy Wieser
Jason Burgon
2005-12-10 17:06:20 UTC
Permalink
Post by R.Wieser
LFN's ? In a real DOS environment (read : non DOS-box) ? :-)
Sure. There is at least one MS-DOS clone that supports the DOS LFN API
natively - Datalight's ROM-DOS:

http://datalight.com/products/romdos/

And IMO, any new add-on file system that does not also support LFN's is a
waste of effort because DOSLFN is also getting pretty good..
--
Jay

Author of Graphic Vision
http://homepage.ntlworld.com/gvision/
R.Wieser
2005-12-10 17:23:39 UTC
Permalink
Jason Burgon <***@ntlworld.com> schreef in berichtnieuws
gWDmf.29120$***@newsfe6-win.ntli.net...

Hello Jason,
Post by Jason Burgon
And IMO, any new add-on file system that does not also support LFN's is a
waste of effort because DOSLFN is also getting pretty good..
Doesn't "also" mean that LFN support would be a *part* of the whole ? And
that the other part has to be supported allso ?

Or did you *really* mean that any add-on system that supports anything
*lower than* LFN's is not worth to be implemented ?....

If not, how would you get the non-LFN -part to function (the part I have a
problem with) ? :-)

Regards,
Rudy Wieser
Jason Burgon
2005-12-10 17:54:00 UTC
Permalink
Post by R.Wieser
Post by Jason Burgon
And IMO, any new add-on file system that does not also support LFN's
is a waste of effort because DOSLFN is also getting pretty good..
Doesn't "also" mean that LFN support would be a *part* of the whole ?
And that the other part has to be supported also ?
Yes, if by "the other part" you mean the SFN API.
Post by R.Wieser
Or did you *really* mean that any add-on system that supports anything
*lower than* LFN's is not worth to be implemented ?....
Yes, that ~as well~.
Post by R.Wieser
If not, how would you get the non-LFN -part to function (the part I have a
problem with) ? :-)
Your IFS driver would natively support LFN's internally and the DOS LFN API
externally, but it would also provide a legacy SFN API support just like
Windoze does. IOW, start by writing an LFN IFS driver, then write a SFN
compatibility layer.

As for your original problem, the only help I can offer is that
FindFirst/Next keep all the tracking details in the user memory, so at least
your IFS driver shouldn't need to keep track of FindFirst memory
allocations.

--
Jay

Author of Graphic Vision
http://homepage.ntlworld.com/gvision/
R.Wieser
2005-12-11 13:46:18 UTC
Permalink
Jason Burgon <***@ntlworld.com> schreef in berichtnieuws
YCEmf.26133$***@newsfe4-win.ntli.net...

Hello Jason,
[snip]
Post by Jason Burgon
Post by R.Wieser
Or did you *really* mean that any add-on system that supports anything
*lower than* LFN's is not worth to be implemented ?....
Yes, that ~as well~.
Well, that means that our conversation ends here. I want to create
something for DOS-versions that do not have native LFN ot TCP/IP support.
:-)

My idea was to enable such an OS to use, with a minimum of code-size, a
remote drive, and later on maybe be able to print to a remote printer (on
the LAN) as well.

Regards,
Rudy Wieser
billious
2005-12-11 17:54:21 UTC
Permalink
Post by R.Wieser
Hello Jason,
[snip]
Post by Jason Burgon
Post by R.Wieser
Or did you *really* mean that any add-on system that supports anything
*lower than* LFN's is not worth to be implemented ?....
Yes, that ~as well~.
Well, that means that our conversation ends here. I want to create
something for DOS-versions that do not have native LFN ot TCP/IP support.
:-)
My idea was to enable such an OS to use, with a minimum of code-size, a
remote drive, and later on maybe be able to print to a remote printer (on
the LAN) as well.
Regards,
Rudy Wieser
AIUI, your problem is how to terminate a findfirst/findnext.

Using 2F/11xx or 21/4E-4F, the search record is held in the process's DTA.

Using 21/714E-714F (the DOS7 LFN way) the initial 714E call asks Windows to
allot memory and return a handle to the searchrecord. This memory needs to
be returned via 71A1 when the searchrecord is no longer required regardless
of the number of times 714F has been called.

There is NO "terminate" required using the first method - but you must make
sure that the DTA content is not changed after the findfirst for as long as
a findnext is required.

HTH

...Bill
R.Wieser
2005-12-11 21:10:59 UTC
Permalink
billious <***@hotmail.com> schreef in berichtnieuws
439c6562$0$15356$***@reader.athenanews.com...

Hello billious,
Post by billious
AIUI, your problem is how to terminate a findfirst/findnext.
That's pretty much what my subject-line says ... :-)
Post by billious
Using 2F/11xx or 21/4E-4F, the search record is held in the process's DTA.
Affirmative.
Post by billious
Using 21/714E-714F (the DOS7 LFN way) the initial 714E call asks Windows to
allot memory and return a handle to the searchrecord. This memory needs to
be returned via 71A1 when the searchrecord is no longer required regardless
of the number of times 714F has been called.
Again, affirmative. Although I do not see how this information helps me.
Post by billious
There is NO "terminate" required using the first method - but you must make
sure that the DTA content is not changed after the findfirst for as long as
a findnext is required.
"By god, I think he's got it !" - (Free from "My fair lady")

Yes, that's exactly the problem I'm having & want to have solved. *HOW* do
I determine *WHEN* a INT 21h, AH=4Eh/4Fh is terminated, and I can do a
clean-up. :-)

Regards,
Rudy Wieser
billious
2005-12-12 05:18:02 UTC
Permalink
Post by R.Wieser
Hello billious,
Post by billious
AIUI, your problem is how to terminate a findfirst/findnext.
That's pretty much what my subject-line says ... :-)
Post by billious
Using 2F/11xx or 21/4E-4F, the search record is held in the process's DTA.
Affirmative.
Post by billious
Using 21/714E-714F (the DOS7 LFN way) the initial 714E call asks Windows
to
Post by billious
allot memory and return a handle to the searchrecord. This memory needs to
be returned via 71A1 when the searchrecord is no longer required
regardless
Post by billious
of the number of times 714F has been called.
Again, affirmative. Although I do not see how this information helps me.
Post by billious
There is NO "terminate" required using the first method - but you must
make
Post by billious
sure that the DTA content is not changed after the findfirst for as long
as
Post by billious
a findnext is required.
"By god, I think he's got it !" - (Free from "My fair lady")
Yes, that's exactly the problem I'm having & want to have solved. *HOW* do
I determine *WHEN* a INT 21h, AH=4Eh/4Fh is terminated, and I can do a
clean-up. :-)
Regards,
Rudy Wieser
21/71 calls : Just for completeness and the reasoning for a "findclose"

4E/4F returns CARRY SET when there are no [further] matches. AX should
contain 02h (file not found) 03h (path not found) or most likely 12h (no
more files)

HTH

...Bill
Rod Pemberton
2005-12-12 21:31:31 UTC
Permalink
Post by R.Wieser
At the client-side I'm writing the IFS, and use a shelling mechanism to
intercept calls from the OS to INT 2Fh, AH=11h (The IFS mechanism). So,
no
Post by R.Wieser
TSR either, but the same effect.
Pascal?
Post by R.Wieser
Yes, that's exactly the problem I'm having & want to have solved. *HOW* do
I determine *WHEN* a INT 21h, AH=4Eh/4Fh is terminated, and I can do a
clean-up. :-)
Okay, a slight review first, since this is new stuff for me. From what I
can tell, if the appropriate bit is set in the CDS (current directory
structure), then DOS recognizes it as a remote drive. If another CDS bit is
set, then the drive is marked as an 'invisible' or 'local' network drive.
This appears to be how MSCDEX works. Since I don't have a remote drive, I
believe the INT 2F chain generated when accessing the CDROM should be the
same. It appears that certain INT 21 filesystem functions will call a
corresponding INT 2F function, if DOS detemines the drive is a network
drive. Correct?

I can think of two possible "solutions."

First, since there is no direct method of determining the end of the 4E/4F
chain, this
outline may help determine it indirectly, most of the time:

1) if 2F/111B (4E) or 2F/111C (4F), CF indicates failure, end-of-chain
2) if 2F/111B (4E) is followed by 2F/111B (4E), end-of-chain, start of new
chain
3) if 2F/1122 or 2F/111D is called, end-of-chain
4) if CHDIR 2F/1105 (3B) is called, push or pop current search state

If the user is using an internal DOS function, a DOS app, or a directory
search program, it is most likely that the 2F/111B will be followed by a
complete series of 2F/111C, unless it is interrupted by 2F/1105 (CHDIR). In
which case, the next CHDIR (to the previous search directory), restores the
prior search. RB's interrupt list warns that other interrupting filesystem
functions will destroy the DTA, so it is unlikely that programs are
throwing these functions in the middle of 4E/4F chains. CHDIR is probably
the only one you need to adjust for, but you'll find out for sure when your
app gets tested. :-)

Second, since (I think) Windows is serving the files to DOS and it supports
the LFN API, you could promote 4E/4F to 714E/714F and call FindClose 71A1
whenever you want, perhaps on the conditions in the outline.


Rod Pemberton
R.Wieser
2005-12-13 18:25:33 UTC
Permalink
Rod Pemberton <***@bitbucket.cmm> schreef in berichtnieuws
dnkq84$5fg$***@domitilla.aioe.org...

Hello Rod,
Post by Rod Pemberton
Post by R.Wieser
At the client-side I'm writing the IFS, and use a shelling mechanism
to intercept calls from the OS to INT 2Fh, AH=11h (The IFS
mechanism). So, no TSR either, but the same effect.
Pascal?
Nope. The language I'm using doesn't compile. :-)

[Snip]
Post by Rod Pemberton
It appears that certain INT 21 filesystem functions will call
a corresponding INT 2F function, if DOS detemines the
drive is a network drive. Correct?
That's pretty much what happens, yes.
Post by Rod Pemberton
I can think of two possible "solutions."
First, since there is no direct method of determining the end of
the 4E/4F chain, this outline may help determine it indirectly,
1) if 2F/111B (4E) or 2F/111C (4F), CF indicates failure, end-of-chain
Correct.
Post by Rod Pemberton
2) if 2F/111B (4E) is followed by 2F/111B (4E), end-of-chain, start of
new chain
Often, but not allways.
Post by Rod Pemberton
3) if 2F/1122 or 2F/111D is called, end-of-chain
Yes,that would be handy. :-)
Post by Rod Pemberton
4) if CHDIR 2F/1105 (3B) is called, push or pop current search state
No comment (yet)
Post by Rod Pemberton
If the user is using an internal DOS function, a DOS app, or a directory
search program, it is most likely that the 2F/111B will be followed by a
complete series of 2F/111C, unless it is interrupted by 2F/1105 (CHDIR).
Not quite. A simple DIR does a find first three times : first to determine
the disk-label, than a seach for a wild-card file without an extension, and
only the third time is followed by find-nexts.

A file-copy from remote drive has got one or two non-closed find-first too.
:-\
Post by Rod Pemberton
In which case, the next CHDIR (to the previous search directory),
restores the prior search.
I think this method would interfere with a cyclic copy of files from one
remote directory to another (it than needs to maintain at least two seperate
file-find chains)
Post by Rod Pemberton
RB's interrupt list warns that other interrupting filesystem
functions will destroy the DTA, so it is unlikely that programs
are throwing these functions in the middle of 4E/4F chains.
Just move the DTA somewhere else (or save/push the first 21 bytes), and you
can even recursivily walk thru a directory-tree (entering every directory as
you encounter it) and copy files from them the FCB way. No problem at all
:-o
Post by Rod Pemberton
Second, since (I think) Windows is serving the files to DOS and it supports
the LFN API, you could promote 4E/4F to 714E/714F and call FindClose 71A1
whenever you want, perhaps on the conditions in the outline.
You're right in thinking that Windows is the remote-side of it all. And I
probably will. But only *after* I have the basics running :-)

Thanks for your suggestions. I'll have to think about them a bit.

Regards,
Rudy Wieser
Rod Pemberton
2005-12-13 22:05:51 UTC
Permalink
Post by R.Wieser
Post by Rod Pemberton
If the user is using an internal DOS function, a DOS app, or a directory
search program, it is most likely that the 2F/111B will be followed by a
complete series of 2F/111C, unless it is interrupted by 2F/1105 (CHDIR).
Not quite. A simple DIR does a find first three times : first to determine
the disk-label, than a seach for a wild-card file without an extension, and
only the third time is followed by find-nexts.
It's in the outline, 4B followed by 4B...
Post by R.Wieser
A file-copy from remote drive has got one or two non-closed find-first too.
:-\
Yuck, I'll take your word for it.
Post by R.Wieser
Post by Rod Pemberton
In which case, the next CHDIR (to the previous search directory),
restores the prior search.
I think this method would interfere with a cyclic copy of files from one
remote directory to another (it than needs to maintain at least two seperate
file-find chains)
Post by Rod Pemberton
RB's interrupt list warns that other interrupting filesystem
functions will destroy the DTA, so it is unlikely that programs
are throwing these functions in the middle of 4E/4F chains.
If not CHDIR, then there is still probably an intermediate function which
indicates that DOS is switching between file-find chains. From the simple
test I did, it seems that DOS preserves and restores DTA with CHDIR, so
probably has other functions where it does too. I would see this as a
special case to be worked out after simple things like CD, DIR, simple
COPY's, and intermediate things like DIR/S or file/directory walkers, have
been worked out.



RP
Rod Pemberton
2005-12-11 00:04:23 UTC
Permalink
Post by R.Wieser
Hello Rod,
Post by Rod Pemberton
2nd post attempt...
It looks like your first came thru too, but maybe a bit slow (just like mine
did :-) ).
Yeah, sorry, thought it got blocked due to clax86, comp.lang.asm.x86, it
never showed up there...
Post by R.Wieser
What I expect ? Well, that's easy : nothing. And that is exactly the
problem : I do not expect DOS to send me a signal that it terminated it's
find-first & next, so I have to generate my own. But when ?
Does find/first send anything back to you? Or does the IFS call return
something? Say if it succeeds, perhaps?
Post by R.Wieser
A simple "dir <remote drive>" shows at least two non-closed
find-first/next
Post by R.Wieser
actions (one for the label, and one for a file without an extension. I
can
Post by R.Wieser
show a logging of the INT 2Fh, AH=11h calls if you like).
Does this mean you can install a TSR on the DOS/remote side of the
connection? If so, you could monitor both INT 2Fh, INT 21h, INT 13h, etc
and perhaps find a nice location to terminate things. If not, you could
still perform temporary tests this way to see if you just need a time based
delay...
Post by R.Wieser
INT 2Fh is exactly the method I'm using. Luckily I found a source-file of a
program that described some IFS data-structures Ralf Browns interrupt-list
did not specify. :-)
Ooo, Ooo, Yippee! You going share the link??? I've been interested in IFS
for a while now!

Rod Pemberton
Rod Pemberton
2005-12-11 01:07:47 UTC
Permalink
If anyone is interested,
the CPHANTOM file has an IFS written in C based on Schulman's book.

http://www.pcausa.com/resources/ifsqlist.html (bottom of page)
http://mvb.saic.com/freeware/vmslt99a/nt/
http://wwwvms.mppmu.mpg.de/vmssig/archive/C/

The first link has an extra file in the zip called int2f.asm.


Rod Pemberton
Rod Pemberton
2005-12-11 02:10:56 UTC
Permalink
Jim Harper's DDJ SCSI redirector code was online for a while:

1) Google's cache message
2) CDROM.C by Jim Harper
3) ST01.C by Jim Harper

Rod Pemberton


This is Google's cache of http://www.ddj.com/ftp/1993/1993.03/cdrom.txt as
retrieved on Aug 11, 2005 04:35:36 GMT. Google's cache is the snapshot that
we took of the page as we crawled the web. The page may have changed since
that time. Click here for the current page without highlighting. This
cached page may reference images which are no longer available. Click here
for the cached text only. To link to or bookmark this page, use the
following url:
http://www.google.com/search?q=cache:HqpSYfzkDWgJ:www.ddj.com/ftp/
1993/1993.03/cdrom.txt+%22CD-ROM+redirector+for+High+Sierra+and+ISO+9660+dis
ks%22&hl=en

/***************************************************************************
***
* CDROM.C -- by Jim Harper (EXCERPTED LISTING)
* A CD-ROM redirector for High Sierra and ISO 9660 disks.

****************************************************************************
*/

/*...#include directives removed...*/
#define SetC(X) (X) |= 0x01
#define ClrC(X) (X) &= ~0x01

extern unsigned _psp, /* Runtime gives us these variables */
end;
char *IOBuf; /* I/O Buffer ptr */

/* Table of saved open SystemFileTable's (SFT's) for DoCloseAll() */
struct SFT _far *CloseTab[MAXCLOSEALL];
unsigned StkSeg, DataSeg,
DriveNo, DriveFlags,
TsrStkSeg, TsrStkPtr,
AppStkSeg, AppStkPtr,
CDType, FIDoff,
Nameoff, Dateoff,
Flagsoff, Blkoff,
Sizeoff, BlkSize,
ChainFlag,
MyStack[STACKSIZE];
unsigned _AX,_BX,_CX,_DX,_DS,_ES,_DI,_FLAGS;
struct IntRegs {
unsigned ES; unsigned DS;
unsigned DI; unsigned SI;
unsigned BP; unsigned SP;
unsigned BX; unsigned DX;
unsigned CX; unsigned AX;
unsigned IP; unsigned CS;
unsigned FLAGS;
};
int Active = 0;
struct isoVolDesc *isoVolDescp;
struct isoDirRec *isoDp;
struct hsVolDesc *hsVolDescp;
struct hsDirRec *hsDp;
struct Cmd Cmd;
struct DirEnt RootEnt,
DirCache[CACHESIZE];
/* Important pointers */
struct SDB _far *SDBp; /* Ptr to Dos Search Data Blk */
struct FDB _far *FDBp; /* Ptr to Dos Found Data Blk */
struct LOL _far *LOLp; /* Ptr to list of lists */
struct CDS _far *CDSp; /* Ptr to cur dir tab entry */
/* These pointers are set according to DOS 3.xx or 4.xx */
char _far *SWAPp, /* Ptr to Dos swap area */
_far *FN1p, /* Ptr to Dos resolved name */
_far * _far *DTApp, /* Ptr to Ptr to Current DTA */
_far * _far *SFTpp, /* Ptr to Ptr to Current SFT */
_far *DosDp, /* Ptr to dir ent for file */
_far *Sattrp, /* Ptr to search attr */
_far *OpenModep; /* Ptr to open mode */
unsigned _far *PSPp; /* Ptr to current PSP */
char *HiSierra = "HISIERRA ",
*Iso9660 = "ISO9660 ";
/*...function prototypes removed...*/
/***********************************************************************/
main(int argc, char *argv[])
{ union REGS regs;
struct SREGS sregs;
unsigned _far *EnvBlkp;
int i, Junk, CdsLen, ProgSize;
DriveNo = 999;
if (argc > 1) {
if (!strcmp(argv[1],"-u") || ! strcmp(argv[1],"-U")) {
regs.h.ah = 0x11;
regs.h.al = DEINSTALL;
int86x(INT2F,&regs,&regs,&sregs);
exit(0);
}
if (argv[1][0] >= 'A' && argv[1][0] <= 'Z' &&
argv[1][1] == ':' && argv[1][2] == '\0') {
DriveNo = argv[1][0] - 'A';
}
if (argv[1][0] >= 'a' && argv[1][0] <= 'z' &&
argv[1][1] == ':' && argv[1][2] == '\0') {
DriveNo = argv[1][0] - 'a';
}
}
if (DriveNo > 26) {
MsgOut("usage: cdrom [A-Z]:\r\n");
exit(1);
}
segread(&sregs); /* Get our stack and data segments */
StkSeg = sregs.ss;
DataSeg = sregs.ds;
regs.h.ah = FUNCID; /* Check if SCSI TSR is present */
regs.h.al = INSTALLCHK;
int86x(INT2F,&regs,&regs,&sregs);
if (regs.h.al != 0xff) {
MsgOut("Scsi tsr not found!\r\n");
exit(1);
}
/* Check if there's a High Sierra or ISO9660 disk in the drive. */
if (ScsiRead(0x10L)) {
MsgOut("IO error.\r\n");
exit(1);
}
hsVolDescp = (struct hsVolDesc *) IOBuf;
isoVolDescp = (struct isoVolDesc *) IOBuf;
CDType = UNKNOWN;
Blkoff = 2;
Sizeoff = 10;
Dateoff = 18;
FIDoff = 32;
Nameoff = 33;
strcpy(RootEnt.FName,"ROOT-CDROM ");
if (strncmp(hsVolDescp->ID,"CDROM",5) == 0) { /* it's High Sierra */
CDType = HIGHSIERRA;
Flagsoff = 24;
hsDp = (struct hsDirRec *)hsVolDescp->DirRec;
RootEnt.Fattr = _A_SUBDIR;
RootEnt.FTime = ToDosTime(hsDp->Date);
RootEnt.FDate = ToDosDate(hsDp->Date);
RootEnt.BlkNo = hsDp->ExtLocLSB;
RootEnt.FSize = hsDp->DataLenLSB;
RootEnt.ParentBlk = hsDp->ExtLocLSB;
BlkSize = hsVolDescp->BlkSizeLSB;
MsgOut("High Sierra disk...\r\n");
}
if (strncmp(isoVolDescp->ID,"CD001",5) == 0) { /* it's ISO 9660 */
CDType = ISO9660;
Flagsoff = 25;
isoDp = (struct isoDirRec *)isoVolDescp->DirRec;
RootEnt.Fattr = _A_SUBDIR;
RootEnt.FTime = ToDosTime(isoDp->Date);
RootEnt.FDate = ToDosDate(isoDp->Date);
RootEnt.BlkNo = isoDp->ExtLocLSB;
RootEnt.FSize = isoDp->DataLenLSB;
RootEnt.ParentBlk = isoDp->ExtLocLSB;
BlkSize = isoVolDescp->BlkSizeLSB;
MsgOut("ISO 9660 disk...\r\n");
}
if (CDType == UNKNOWN) {
MsgOut("Unknown disk type..\r\n");
exit(1);
}
regs.h.ah = 0x52; /* Get Address of List of Lists */
int86x(0x21,&regs,&regs,&sregs);
FP_SEG(LOLp) = sregs.es;
FP_OFF(LOLp) = regs.x.bx;
regs.x.ax = 0x5d06; /* Get address of Dos Swap area */
int86x(0x21,&regs,&regs,&sregs);
FP_SEG(SWAPp) = sregs.ds;
FP_OFF(SWAPp) = regs.x.si;
if (DriveNo > LOLp->LastDrive) {
MsgOut("Drive # to high.\r\n");
exit(1);
}
MsgOut("DOS version "); ToHex(_osmajor); MsgOut("."); ToHex(_osminor);
/* Now set the offsets within Dos according to 3.3x, 4.xx or 5.xx */
if ( _osmajor == 3 && _osminor >= 30) {
CdsLen = 0x51;
PSPp = (unsigned _far *)(SWAPp + 0x10U);
FN1p = SWAPp + 0x0092U;
Sattrp = SWAPp + 0x023aU;
DosDp = SWAPp + 0x01a7U;
SDBp = (struct SDB _far *) (SWAPp + 0x0192U);
DTApp = (char _far * _far *)(SWAPp + 0x000cU);
SFTpp = (char _far * _far *)(SWAPp + 0x0268U);
} else if (_osmajor == 4 || _osmajor == 5) {
CdsLen = 0x58;
PSPp = (unsigned _far *)(SWAPp + 0x10U);
FN1p = SWAPp + 0x009eU;
Sattrp = SWAPp + 0x024dU;
DosDp = SWAPp + 0x01b3U;
SDBp = (struct SDB _far *) (SWAPp + 0x019eU);
DTApp = (char _far * _far *)(SWAPp + 0x000cU);
SFTpp = (char _far * _far *)(SWAPp + 0x027eU);
} else {
MsgOut("Not DOS 3.3x, 4.xx or 5.xx\r\n");
exit(1);
}
/* Cast ptr to table entry pointer */
CDSp = (struct CDS _far *) (LOLp->CDS + DriveNo * CdsLen);
DriveFlags = CDSp->Flags; /* Turn on network & physical bits
*/
CDSp->Flags = 0xC000;
CDSp->RootOff = 2;

CDSp->CurDir[0] = 'A' + DriveNo; /* Set to root */
CDSp->CurDir[1] = ':';
CDSp->CurDir[2] = '\\';
CDSp->CurDir[3] = '\0';

for (i = 0; i < STACKSIZE; i++) /* Initialize our stack */
MyStack[i] = 0x4141;
TsrStkSeg = DataSeg; /* Initialize stack and bottom of program.
*/
TsrStkPtr = (unsigned)&MyStack[STACKSIZE];
if (TsrStkPtr & 0x1U) /* Make sure stack is on a word boundry */
TsrStkPtr--;
/* Program size in paragraphs w/o a heap */
ProgSize = (StkSeg + (((unsigned)&end) >> 4)) - _psp + 1;
for (i = 1; i < CACHESIZE - 1; i++) { /* Initialize cache */
DirCache[i].Forw = &DirCache[i+1];
DirCache[i].Back = &DirCache[i-1];
}
DirCache[0].Forw = &DirCache[1];
DirCache[0].Back = &RootEnt;
DirCache[CACHESIZE-1].Forw = &RootEnt;
DirCache[CACHESIZE-1].Back = &DirCache[CACHESIZE-2];

/* Root dirent provides anchor into the cache */
RootEnt.Forw = &DirCache[0];
RootEnt.Back = &DirCache[CACHESIZE-1];
/* Close files */
_dos_close(0); /* stdin */
_dos_close(1); /* stdout */
_dos_close(2); /* stderr */
Old2F = _dos_getvect(INT2F); /* Grab multiplex interrupt */
_dos_setvect(INT2F,New2F);
FP_SEG(EnvBlkp) = _psp; /* Free the environment */
FP_OFF(EnvBlkp) = 0x2c;
_dos_freemem(*EnvBlkp);
_dos_setblock(ProgSize,_psp,&Junk); /* Shrink our program size */
_dos_keep(0,ProgSize); /* TSR ourself */
}
/***** New2F(struct IntRegs IntRegs) -- our interrupt 2F handler. *****/
void _interrupt _far New2F(struct IntRegs IntRegs)
{
/* See if we handle this function */
if ((IntRegs.AX >> 8U) != 0x11 || Active)
_chain_intr(Old2F);
if ((IntRegs.AX & 0xff) == INSTALLCHK) { /* Install check?? */
IntRegs.AX = 0x00ff;
return;
}
Active++; /* Set flag saying we're active */
ChainFlag = 0; /* Don't chain out by default */
/* Save needed regs from stack */
_AX = IntRegs.AX; _BX = IntRegs.BX;
_CX = IntRegs.CX; _DX = IntRegs.DX;
_DS = IntRegs.DS; _ES = IntRegs.ES;
_DI = IntRegs.DI; _FLAGS = IntRegs.FLAGS;
_asm /* Switch to own stack */
{
cli ; Interrupts off
mov WORD PTR AppStkPtr,sp ; Save app stack
mov WORD PTR AppStkSeg,ss
mov sp,WORD PTR TsrStkPtr ; Load new stack
mov ss,WORD PTR TsrStkSeg
sti ; Interrupts on
}
switch(_AX & 0xff) /* handle the command */
{
case DEINSTALL: DeInstall(); break;
case CHDIR: DoChDir(); break;
case CLOSE: DoClose(); break;
case READ: DoRead(); break;
case GETSPACE: DoGetSpace(); break;
case GETATTR: DoGetAttr(); break;
case OPEN: DoOpen(); break;
case FINDFIRST: DoFindFirst(); break;
case FINDNEXT: DoFindNext(); break;
case SEEK: DoSeek(); break;
case CLOSEALL: DoCloseAll(); break;
case PATHNAME: Spoof(); /* hack */
case 0x25:
default: ChainFlag = 1; break;
}
_asm /* Switch back to app stack */
{
cli ; Interrupts off
mov sp,WORD PTR AppStkPtr ; Load app stack
mov ss,WORD PTR AppStkSeg
sti ; Interrupts on
}
if (ChainFlag) { /* If anyone set the chain flag, chain out */
Active = 0;
_chain_intr(Old2F);
}
/* Restore (possibly modifed) registers */
IntRegs.AX = _AX; IntRegs.BX = _BX;
IntRegs.CX = _CX; IntRegs.DX = _DX;
IntRegs.FLAGS = _FLAGS;
Active = 0; /* Clear Active Flag */
}

/***************************************************************************
***
* ST01.C -- by Jim Harper. (EXCERPTED LISTING) -- A simple SCSI transport
TSR
* that communicates with CDROM.C module via INT2F. The DoScsi() routine
below
* handles the actual work of of transferring data to/from the SCSI device.

****************************************************************************
*/
void DoScsi(void)
{
struct Cmd _far *Cmdp;
unsigned Phase,
NumBytes,
Byte = 0,
i;
FP_SEG(Cmdp) = _DS;
FP_OFF(Cmdp) = _DX;

FP_SEG(Datap) = Cmdp->DSeg;
FP_OFF(Datap) = Cmdp->DOff;

NumBytes = 512;

Endp = Datap;
Cmdp->Count = 0L;

/* Clear control reg */
*RegPort = 0x00;

/* Bus has gotta be free */
if ((*RegPort & BUSYBIT) != 0x00) {
Cmdp->Stat = 0x80;
return;
}
/* Clear control reg */
*RegPort = 0x00;
/* Assert HBA's address */
*DataPort = 0x80;
/* Set the arbitration bit */
*RegPort = (ARBITSTART | PENABLE);
/* Wait for arbitration to complete */
for (Timer1 = HZ * 3; (*RegPort & ARBITDONE) == 0x00;)
if (!Timer1) {
Cmdp->Stat = 0x81;
return;
}
/* OR the target & our ID bits into the data reg */
*DataPort = 0x80 | (0x01 << (unsigned)Cmdp->ID);

/* Assert SELect, bus enable, deassert arbitration */
*RegPort = (SEL | PENABLE | BUSENABLE);
for (Timer1 = 2; Timer1;)
;
/* Wait for BUSY */
for (Timer1 = HZ * 3; (*RegPort & BUSYBIT) == 0x00;)
if (!Timer1) {
*RegPort = 0x00;
Cmdp->Stat = 0x82;
return;
}
/* Drop Select */
*RegPort = (PENABLE | BUSENABLE);

/* Wait for command phase */
for (Timer1 = HZ * 3; ((Phase = (*RegPort & PHASEMASK)) != COMMAND);)
if (!Timer1) {
*RegPort = 0x00;
Cmdp->Stat = 0x83;
return;
}
Cmdp->Stat = 0x00;
for (Timer1 = HZ * 10;;) { /* Cmd must complete in 10s */
if (!Timer1) {
Cmdp->Stat = 0x84;
return;
}
Phase = *RegPort & PHASEMASK;
switch(Phase) {
case COMMAND:
while ((*RegPort & PHASEMASK) == COMMAND)
*DataPort = Cmdp->CDB[Byte++];
break;
case DATAIN:
_asm
{
push es
push ds
mov cx,NumBytes
les di,Datap
lds si,DataPort
cld
repeat1:
movsb
dec si
loop repeat1
pop ds
pop es
}
Datap += NumBytes;
break;
case DATAOUT:
_asm
{
push es
push ds
mov cx,NumBytes
les di,DataPort
lds si,Datap
cld
repeat2:
movsb
dec di
loop repeat2
pop ds
pop es
}
break;
case STATUS: Cmdp->Stat = *DataPort; break;
case MSGIN: Cmdp->Sense = *DataPort; break;
case BUSFREE: *RegPort = 0x00;
Cmdp->Count += Datap - Endp;
return;
}
/* Delay long enough */
for (i = 0; (*RegPort & REQ) && i < 5; i++)
;
}
}
R.Wieser
2005-12-11 13:58:47 UTC
Permalink
Rod Pemberton <***@bitbucket.cmm> schreef in berichtnieuws
dnfqd2$1gv$***@domitilla.aioe.org...

Hello Rod,
[Snip]
Post by Rod Pemberton
Does find/first send anything back to you? Or does the IFS call
returnsomething? Say if it succeeds, perhaps?
The software on the remote computer sends me, if found, the find-first/next
data back. And *I* am writing the IFS-code, so I can return anything I
like. :-)

[Snip]
Post by Rod Pemberton
Does this mean you can install a TSR on the DOS/remote
side of the connection?
I'm writing the remote-side server software (for Windows), and I let it
shows lots of debugging data. So no TSR.

At the client-side I'm writing the IFS, and use a shelling mechanism to
intercept calls from the OS to INT 2Fh, AH=11h (The IFS mechanism). So, no
TSR either, but the same effect.
Post by Rod Pemberton
If so, you could monitor both INT 2Fh, INT 21h, INT 13h,
etc and perhaps find a nice location to terminate things. If
not, you could still perform temporary tests this way to see
if you just need a time based delay...
Thats about what I was thinking of, but have no clue what combination of
commands would signal an end of Find-first/next cycle. Remember, it has to
work for the OS as well as for User-programs. :-)
Post by Rod Pemberton
Ooo, Ooo, Yippee! You going share the link??? I've been interested
in IFS for a while now!
The program (in TASM) is "iHPFS for DOS" created by Marcus Better. Hope you
can use it as I did.

Regards,
Rudy Wieser
Rod Pemberton
2005-12-09 22:57:40 UTC
Permalink
Post by R.Wieser
Hello All,
My subject-line may be a bit fuzzy, but I hope this clears it up : I'm
trying to create a DOS IFS (Installable File System) that connects (using a
packet-driver) to another computer (running Windows). Yep, yet another
remote drive. :-)
The problem I'm having is with the way DOS does a Find-File. It never
terminates the action,
What are you expecting to "terminate the action"? Or, what do you mean by
DOS "never terminates the action"?
Post by R.Wieser
so I don't know when to close the connection, and
clean-up (for both the DOS and the Windows ends of the connection).
Is there a (standard) mechanism that I can use for cases like these ? Or
does anyone know of a trick that has allready been used in other
remote-drive IFS programs ?
I would sure like to know :-)
Regards,
Rudy Wieser
Well, let's hope someone else can answer your questions: I can't.

When it comes to DOS IFS's, everyone mentions MSCDEX extensions,
INT 2Fh (Multiplex) instead of INT 21h, and
Andrew Schulman's "Undocumented DOS", but
noone ever tells on the Internet how it is done...

My probably less than enlightening hints:
1) findfirst/next don't actually open anything, so what cleanup needs to be
done?
2) In addition to findfirst(), there is _dos_findfirst().
3) The LFN API has an explicit function "FindClose" int 0x21,AX=71a1h.
4) Use Henrik Haftmann's DOSLFN driver for LFN functions. DJGPP has LFN
support,
but Watcom doesn't. You can use "LFN Create or Open File"
int0x21, ax=716Ch followed by "Close file" int 0x21,ax=3eh to force
DOSLFN to update its internal cache when using Watcom.


Rod Pemberton
Ted Davis
2005-12-10 01:41:59 UTC
Permalink
On Fri, 9 Dec 2005 17:57:40 -0500, "Rod Pemberton"
Post by Rod Pemberton
Post by R.Wieser
Hello All,
My subject-line may be a bit fuzzy, but I hope this clears it up : I'm
trying to create a DOS IFS (Installable File System) that connects (using
a
Post by R.Wieser
packet-driver) to another computer (running Windows). Yep, yet another
remote drive. :-)
The problem I'm having is with the way DOS does a Find-File. It never
terminates the action,
What are you expecting to "terminate the action"? Or, what do you mean by
DOS "never terminates the action"?
Post by R.Wieser
so I don't know when to close the connection, and
clean-up (for both the DOS and the Windows ends of the connection).
Is there a (standard) mechanism that I can use for cases like these ? Or
does anyone know of a trick that has allready been used in other
remote-drive IFS programs ?
I would sure like to know :-)
Regards,
Rudy Wieser
Well, let's hope someone else can answer your questions: I can't.
When it comes to DOS IFS's, everyone mentions MSCDEX extensions,
INT 2Fh (Multiplex) instead of INT 21h, and
Andrew Schulman's "Undocumented DOS", but
noone ever tells on the Internet how it is done...
1) findfirst/next don't actually open anything, so what cleanup needs to be
done?
2) In addition to findfirst(), there is _dos_findfirst().
3) The LFN API has an explicit function "FindClose" int 0x21,AX=71a1h.
4) Use Henrik Haftmann's DOSLFN driver for LFN functions. DJGPP has LFN
support,
but Watcom doesn't. You can use "LFN Create or Open File"
int0x21, ax=716Ch followed by "Close file" int 0x21,ax=3eh to force
DOSLFN to update its internal cache when using Watcom.
What he's referring to is that findfirst leaves DOS structures
populated and in general in a state pending some concluding action.
The proper approach, if memory serves, is to *always* call findnext as
many times as required for it return failure to find - this can be
totally unnecessary from a programmer's point of view when a single
file is sought and findnext is obviously not going to find anything,
but it is necessary from the OS's point of view because in order for
findnext to have meaning, the structures from findfirst must be
retained. findfirst doesn't have a way of knowing that the only file
has been found, but findnext can tell when there are no more to find,
and therefore has to call the findfirst/findnext cleanup function.

The two functions form a pair: findfirst begins the process and
findnext terminates it. Note that there is no findonly function and
"first" implies "next".
--
T.E.D. (***@gearbox.maem.umr.edu)
R.Wieser
2005-12-10 03:06:54 UTC
Permalink
Ted Davis <***@crayne.org> schreef in berichtnieuws
***@4ax.com...

Hello Ted,

[snip]
Post by Ted Davis
The proper approach, if memory serves, is to *always* call findnext as
many times as required for it return failure to find
I'm afraid that even the designers of the OS violate this approach.

A simple "dir <remote drive>" shows at least two non-closed find-first/next
actions (one for the label, and one for a file without an extension. I can
show a logging of the INT 2Fh, AH=11h calls if you like).

And those types of non-closed actions are exactly the ones I need to handle
... :-)

Regards,
Rudy Wieser
Ted Davis
2005-12-10 17:48:52 UTC
Permalink
Post by R.Wieser
Hello Ted,
[snip]
Post by Ted Davis
The proper approach, if memory serves, is to *always* call findnext as
many times as required for it return failure to find
I'm afraid that even the designers of the OS violate this approach.
A simple "dir <remote drive>" shows at least two non-closed find-first/next
actions (one for the label, and one for a file without an extension. I can
show a logging of the INT 2Fh, AH=11h calls if you like).
And those types of non-closed actions are exactly the ones I need to handle
... :-)
You could try calling INT 2F AX=111C with the registers set up for the
structures.

Nobody ever accused Microsoft of being consistent, and nobody but
Microsoft ever said DOS wasn't buggy.
--
T.E.D. (***@gearbox.maem.umr.edu)
R.Wieser
2005-12-11 13:39:36 UTC
Permalink
Ted Davis <***@crayne.org> schreef in berichtnieuws
***@4ax.com...

Hello Ted,

[Snip]
Post by Ted Davis
You could try calling INT 2F AX=111C with the registers set up
for the structures.
Yes, I could. I could allso just send a "terminate find action" to the
tremote computer. But when ? How can/do I decide that that
find-first/next has got enough ?
Post by Ted Davis
Nobody ever accused Microsoft of being consistent, and nobody but
Microsoft ever said DOS wasn't buggy.
It has got a better track-record than Windows has :-)

Regards,
Rudy Wieser
David J. Craig
2005-12-12 05:53:57 UTC
Permalink
Int 21h, Function 11h maintains all the necessary data for findnext at the
DTA in the FCB. Only the later protected OS versions have the OS maintain
that data.
Post by R.Wieser
Hello Ted,
[Snip]
Post by Ted Davis
You could try calling INT 2F AX=111C with the registers set up
for the structures.
Yes, I could. I could allso just send a "terminate find action" to the
tremote computer. But when ? How can/do I decide that that
find-first/next has got enough ?
Post by Ted Davis
Nobody ever accused Microsoft of being consistent, and nobody but
Microsoft ever said DOS wasn't buggy.
It has got a better track-record than Windows has :-)
Regards,
Rudy Wieser
R.Wieser
2005-12-12 11:08:19 UTC
Permalink
David J. Craig <***@crayne.org> schreef in berichtnieuws
***@comcast.com...

Hello David,
Post by David J. Craig
Int 21h, Function 11h maintains all the necessary data for findnext at the
DTA in the FCB.
So does INT 21h, AH=4Eh/4Fh

And "all the necessary data" ? For local files, yes. For remote files, no.
1) what does "cluster number" mean for a remote file ?
2) How can I recover the (local) path to the (remote) file from it :-)

Regards,
Rudy Wieser
R.Wieser
2005-12-11 13:34:49 UTC
Permalink
Guys, guys. For some reason I do not seem to get thru : I *CANNOT* add the
OS or user-program. The only thing I can do is to recieve IFS requests, and
act upon them.

To illustrate what I mean, some user could decide to loop recursivily thru
all directories on the remote drive. It means that I could have about 64
find-first/find-next calls open. All of which are not closed.

I don't know if you guys are aware, but when you type "dir drive:\*.*" the
OS (including W95 & W98, not checked on above versions) uses simple
dos-calls (find-first, find next), and not the LFN variants. And there is
*nothing* I can change about it ....

Hope that clarifies it a bit.

Regards,
Rudy Wieser
Skarmander
2005-12-11 19:54:03 UTC
Permalink
Post by R.Wieser
Guys, guys. For some reason I do not seem to get thru : I *CANNOT* add the
OS or user-program. The only thing I can do is to recieve IFS requests, and
act upon them.
To illustrate what I mean, some user could decide to loop recursivily thru
all directories on the remote drive. It means that I could have about 64
find-first/find-next calls open. All of which are not closed.
I don't know if you guys are aware, but when you type "dir drive:\*.*" the
OS (including W95 & W98, not checked on above versions) uses simple
dos-calls (find-first, find next), and not the LFN variants. And there is
*nothing* I can change about it ....
Hope that clarifies it a bit.
Then set aside a circular buffer for FindFirst requests, and discard them on
a FIFO basis as you run out. You seem to be asking for a way to implement
miracles. You cannot both have a limited number of pending requests and the
demand that all outstanding requests must remain valid even if none are
closed explicitly.

Of course this does mean you'll need synchronization if calls are to be
reentrant (I don't know if this is required). If you can't do *that* either,
you'll need a clever lock-free data structure.

If you want to be really good you can use a dynamically growing structure
and expire FindFirst requests based on time only (it's extremely unlikely a
FindFirst handle will be needed for more than a few seconds), or a hybrid
approach where you have a dynamically growing structure with an upper bound
where you do some trade-off between memory used and maximum time a request
remains valid. You could even measure "time" in the number of FindFirst
calls made overall if it's too complicated to use real time.

I'd imagine FindFirst requests do not take up much memory, if properly
implemented. You can probably afford a lot of open requests and get away
with a statically sized queue/hash table. No well-behaved application can
open a large number of FindFirsts, close none of them, and still expect for
every single one to remain valid.

S.
R.Wieser
2005-12-11 21:37:56 UTC
Permalink
Skarmander <***@crayne.org> schreef in berichtnieuws
439c83f3$0$24373$***@news.xs4all.nl...

Hello Skarmander,

[Snip]
....and discard them on a FIFO basis as you run out.
That could be a working solution. Especially when I make the number of
connectoids (handshaking UDP packets) variable (when a "cannot do anymore"
pops up the user can just re-start with a larger number of connectoids
available).
You seem to be asking for a way to implement miracles.
This miracle MUST have been solved before. I have TCP/IP software for DOS
here (closed-source MS stuff, much memory-hungry) that should have the same
problem.
You cannot both have a limited number of pending requests and the
demand that all outstanding requests must remain valid even if none are
closed explicitly.
Yep, that was my sentiment exactly. But I'm working with a
memory-constraint (just like any other method would do, even dynamically
growing of the connections), and I can't do anything about the second. :-)
... and maximum time a request remains valid. You could even
measure "time" in the number of FindFirst calls made overall
Well, timing-out is what I'm currently doing. Not the best solution. :-)
No well-behaved application can open a large number of FindFirsts,
close none of them, and still expect for every single one to remain valid.
I'm sorry for you, but that is *exactly* what an app. may expect : as long
as it does not overwrite the first 21 bytes of the DTA, it can, as far as
DOS is concerned, do another find-next whenever it wants (even hours or days
later).

And yes, I'm trying to find the "best" solution, not one that will work for
a limited number of apps most of the time. :-)

Thanks for your response, you gave me something to think about.

Regards,
Rudy Wieser
Skarmander
2005-12-12 00:26:18 UTC
Permalink
<snip>
Post by R.Wieser
You seem to be asking for a way to implement miracles.
This miracle MUST have been solved before. I have TCP/IP software for DOS
here (closed-source MS stuff, much memory-hungry) that should have the same
problem.
It probably does. It probably hasn't "solved" the problem in any definitive
way, though. Just in a way that happens to work. There should be a way of
bringing it to its knees; I'm betting it's not necessarily all that hard either.

<snip>
Post by R.Wieser
No well-behaved application can open a large number of FindFirsts,
close none of them, and still expect for every single one to remain valid.
I'm sorry for you, but that is *exactly* what an app. may expect : as long
as it does not overwrite the first 21 bytes of the DTA, it can, as far as
DOS is concerned, do another find-next whenever it wants (even hours or days
later).
No, that is not exactly what an application may expect. Not calling FindNext
until it returns "no more files" is a violation of the interface. You cannot
possibly *know* what an application may expect at this point. Anything goes.
Your specification has been rendered worthless, and you're down to trying to
guess what the other side wants from you. Not a happy position to be in, but
there you go.

You can try to be as accommodating to broken code as you like, but somewhere
the buck has to stop. You have to make *some* sort of tradeoff. If you want
closure on this, then simply *measure* what applications are doing. Do they
really do a new FindNext "hours or days later"? How many simultaneous open
requests are we talking about? 10? 100? 32,767? How many per second? What
happens if you write your own application that deliberately tries to break
the driver and set it loose on existing drivers? When does it fail? Does it
even fail, or is some unknown mechanism at work that will accommodate some
pathological cases?

To profile is to know. You could waste hours or days on a solution that is
"maximally fair" which still won't work in the particular case you're using
it for. Conversely, a "stupid" solution you hack up in a few minutes could
happen to do exactly what applications expect.
Post by R.Wieser
And yes, I'm trying to find the "best" solution, not one that will work for
a limited number of apps most of the time. :-)
Then, again, your only recourse is to try and find out how applications
expect FindFirst/Next to behave, and give them what they want. The "best"
solution does not exist in this case, since the constraints you're given
make the general problem unsolvable.
Post by R.Wieser
Thanks for your response, you gave me something to think about.
Don't think, just do it. If it doesn't work, rewrite it. Unless your code
will operate a nuclear power plant, you won't make headway here by trying to
design the ultimate unfallible driver first. It probably can't be done. Feel
your way around.

S.
R.Wieser
2005-12-12 10:55:01 UTC
Permalink
Skarmander <***@crayne.org> schreef in berichtnieuws
439cc3c1$0$11080$***@news.xs4all.nl...

Hello Skarmander,

[Snip]
Post by Skarmander
It probably does. It probably hasn't "solved" the problem in any
definitive way, though. Just in a way that happens to work.
Well, I would love to know which "just happens to work" method MS used. :-)
Post by Skarmander
There should be a way of bringing it to its knees; I'm betting it's
not necessarily all that hard either.
Harder than you might think. Currently quite a few people have read this
conversation, and none of them responded with "what are you mumbling about,
the solution is .....".

[snip]
Post by Skarmander
No, that is not exactly what an application may expect. Not calling FindNext
until it returns "no more files" is a violation of the interface.
Than complain to MS. As I mentioned before, it's own OS does not honor it.
I allso cannot remember ever having read about that constraint, although you
are one of a few people that has mentioned it. Can you give me a
reference/URL to it ?
Post by Skarmander
You cannot possibly *know* what an application may expect at this point.
Let's first try to solve the first problem, and than the next please. (FYI :
the problem you are sketching is *not* a problem for me. Trying to read
beyond the last file generates a #18 error - "no more files")
Post by Skarmander
You can try to be as accommodating to broken code as you like, but somewhere
the buck has to stop.
[snip]

Yes, it's a trade-off. But please allso acknowledge that my IFS-driver
should *at least* be able to accomodate THE OS. Currently it cannot even
do that, because of non-closed find-first's BY THE OS.

[snip]
Post by Skarmander
Don't think, just do it. If it doesn't work, rewrite it.
"just rewrite it" :-) Gladly, my dear Sir. But should I not need to have
an idea to what to rewrite the code to ? Or am I expected to just press
buttons & see if it will compile later ?
Post by Skarmander
Feel your way around.
...

Regards,
Rudy Wieser
Waldek Hebisch
2005-12-13 22:22:09 UTC
Permalink
Post by R.Wieser
You seem to be asking for a way to implement miracles.
This miracle MUST have been solved before. I have TCP/IP software for DOS
here (closed-source MS stuff, much memory-hungry) that should have the same
problem.
You cannot both have a limited number of pending requests and the
demand that all outstanding requests must remain valid even if none are
closed explicitly.
Yep, that was my sentiment exactly. But I'm working with a
memory-constraint (just like any other method would do, even dynamically
growing of the connections), and I can't do anything about the second. :-)
Looking at Ralf Brown description it seems that DOS uses 10 bytes of FCB
to retain state between searches. If needed you can probably use a few
more bytes.

So, you probably can store in the FCB enough info to identify remote
directory. It is not enough to store full pathname, but you can get the
patchname searching directory tree for a given directory (as long as you
can identify it). Of course searching is slow but if you cache locally
mappings from id-s to pathnames remote you will need to search only in
cases which would otherwise fail.
--
Waldek Hebisch
***@math.uni.wroc.pl
R.Wieser
2005-12-14 09:43:47 UTC
Permalink
Waldek Hebisch <***@crayne.org> schreef in berichtnieuws
dnnhih$q12$***@panorama.wcss.wroc.pl...

Hello Waldek,
[Snip]
Post by Waldek Hebisch
Looking at Ralf Brown description it seems that DOS uses 10 bytes
of FCB to retain state between searches. If needed you can probably
use a few more bytes.
I'm aware of that area, but I'm not sure if I can "just use" it : it isn't
specifically mentioned as being "free" for when the target-drive is
non-local ... Nor does Ralf have a description of the last 4 bytes, or what
the cluster & index do for non-local drives.

Wait a minute : 10 bytes ? You don't mean 8 starting at offset 13 (just
behind the search-for attribute), but the 10 starting at offset 33 (just
behind the found attribute) ? If that's so, that would be no good. A
program could erase the returned search-results (everything beyond the 21
byte, and still be able to find the next file.

Some programmers have been known to do a recursive directory-tree traversal,
only saving & restoring the DTA's first 21 bytes on the stack.

I'm currently allready utilizing that 8-byte area, as I store the ID of the
connectoid to the server in there. That should make sure that even if the
(contents of the) DTA is(are) moved I do still know wich search-service
thread on the remote computer I have to send it to. :-)
Post by Waldek Hebisch
So, you probably can store in the FCB enough info to identify remote
directory. It is not enough to store full pathname, but you can get the
patchname searching directory tree for a given directory (as long as you
can identify it). Of course searching is slow but if you cache locally
mappings from id-s to pathnames remote you will need to search only in
cases which would otherwise fail.
That's not a bad idea. I was thinking about much the same, but was thought
I should be able to locally resolve the DTA-contents to a directory-path
(drive & search-mask are allready available in the DTA itself). You gave
my brain a nudge, and made me aware that I only need to have an ID of the pa
th. And for some reason I think that the clusternumber could be used for
just such a purpose (if DOS will allow it) :-)

Thanks for the suggestion.

Regards,
Rudy Wieser

Rod Pemberton
2005-12-11 10:02:28 UTC
Permalink
Post by R.Wieser
Hello All,
Is there a (standard) mechanism that I can use for cases like these ? Or
does anyone know of a trick that has allready been used in other
remote-drive IFS programs ?
I think I found the answer to your question of findfirst/next may have been
solved in CMU's Mach DOS emulator. The
network redirector code in CMU's Mach DOS emulator is in dos.h and dos_fs.c.
These files made it into DOSEMU and PCEMU as mfs.c, mfs.h, emufs.S.

David Hedley's PCEMU http://pcemu.sourceforge.net/
Robert Sanders' DOSEMU http://dosemu.sourceforge.net/

CMU's Mach DOS emulator i386.mdos.src.tar.Z from here:
http://www.cs.cmu.edu/afs/cs.cmu.edu/project/mach/public/src/


Rod Pemberton
R.Wieser
2005-12-11 14:04:11 UTC
Permalink
Rod Pemberton <***@bitbucket.cmm> schreef in berichtnieuws
dngteh$8sr$***@domitilla.aioe.org...

Hello Rod,

[Snip]
Post by Rod Pemberton
I think I found the answer to your question of findfirst/next may have been
solved in CMU's Mach DOS emulator. The
network redirector code in CMU's Mach DOS emulator is in dos.h and dos_fs.c.
These files made it into DOSEMU and PCEMU as mfs.c, mfs.h, emufs.S.
Thanks for the links. I'll take a look :-)

Regards,
Rudy Wieser
Loading...