Thread View: micro.ibm
1 messages
1 total messages
Started by ugogan
Fri, 10 Apr 1987 22:24
Followup on "Opening files for Shared Read in Turbo Pascal"
Author: ugogan
Date: Fri, 10 Apr 1987 22:24
Date: Fri, 10 Apr 1987 22:24
265 lines
12164 bytes
12164 bytes
About a month ago, we posted the following request for information:
> Has anyone found a way to get Turbo Pascal to open random
> access files in read only mode to allow shared concurrent
> access over an MS-DOS 3.1/NETBIOS-based network?
> Normally, Turbo opens files in read/write mode only, producing
> "sharing violation ... abort, retry, ignore" error messages.
> (At least the version of Turbo we have does.) We could
> trap those errors & have users wait till file is free, but
> would obviously prefer shared access.
> Thoughts, anyone??
Basically, the responses that we got back from this request were of two
varieties. The first group said that unless we wanted to write all our own
I/O routines, we were out of luck; the second group said that if we found out
anything to let them know.
Although the idea of writing all of our own I/O routines was not appealing,
we did decide to take a look at a compiled Turbo program and see how it
opened files. Not surprisingly, Turbo's run-time library uses DOS function
call 3DH ("open file") with a mode byte of 02 (for read/write). If you try
to use the DOS ATTRIB command (or equivalent) to mark a file as "read only",
when your Turbo program tries to open the file, you'll get an error message.
In the meantime, a letter to the editor in the April 1987 issue of PC Tech
Journal suggested the possibility of changing this mode byte that Turbo
Pascal passes to the DOS function call 3DH to a zero (for read-only access).
Although this would provide one alternative to our problem, we decided to
take this solution one step further and take advantage of the increased power
of the 3DH function call under DOS 3.xx, as well as provide a means to avoid
having to use DEBUG on every network application program that we develop
under Turbo Pascal.
The following description of the solution we developed, as well as a Turbo
Pascal procedure that can be used to set the desired sharing and access modes
for any files that you want to open in your program, is detailed below by
Todd Lewis. If you have any specific questions about this method, please
send your replies directly to Todd at UTODDL@UNC.BITNET. If you do not have
access to BITNET mail, feel free to reply to me and I will forward them to
Todd.
Thanks to those who replied to our original request.
-- Jim Gogan (ugogan@ecsvax)
University of North Carolina at Chapel Hill
Microcomputing Support Center
--------- cut here for Todd's solution ----------
An instruction at 24FB in TURBO.COM (Ver. 3.01a) controls the
options for opening random access files with RESET. (You will have
to snoop around with DEBUG to find the offset for other versions of
Turbo. It should still be in the same general area.) It looks
like "xxxx:24FB B8023D MOV AX,3D02". AX=3Dxx is the DOS function
to open a file; AL=00, 01, and 02 requests read access rights,
write access rights, and read/write acces rights, respectively, in
DOS 2.10. In DOS 3.xx, things get a little more sophisticated. In
3.xx, AL consists of four bit-oriented fields. They are:
* Inheritance flag
* Sharing mode field
* Reserved field
* Access field
The bit fields are mapped as follows:
<I> < S > <R> < A >
Open Mode bits 7 6 5 4 3 2 1 0
I Inheritance flag
If I = 0, file is inherited by child processes
If I = 1, file is private to the current process
S Sharing Mode
The file is opened as follows:
If S = 000, compatability with DOS 2.xx
If S = 001, Deny Read/Write mode (exclusive rights)
If S = 010, Deny Write mode
If S = 011, Deny Read mode
If S = 100, Deny None mode
Any other combinations are invalid.
R Reserved (always 0).
A Access (just like in DOS 2.xx)
The file access is assigned as follows:
If A = 000, Read access
If A = 001, Write access
If A = 010, Read/Write access
Any other combinations are invalid.
The upshot is this: if you use the function below with the
parameters Share_Compatability, Access_Read, which zaps your
memory-image (not the .COM file on the disk), you can do random
access reads through a typed file RESET on a Read-Only file. For my
purposes (I'm trying to have several programs reading from the same
pre-existing data file over a network), I will probably use
Share_DenyNone and Access_Read (any number of programs can read the
file simultaniously). BUT if any of the programs tries to do a
WRITE, that program is gonna die! If you really wanted to live
dangerously, you could have several programs open with
Share_DenyNone, Access_ReadWrite, and they could all read AND
CHANGE the file at the same time. This wouldn't provide for any
record locking. You would have to do that through explicit DOS
calls.
You should examine your TURBO.COM file with debug to make sure the
zapping function will work with your version. I'm using 3.01a and
the code a la debug I'm zapping is:
xxxx:24FB B8023D MOV AX,3D02
It's the 02 part that sets the access mode. (You could zap a copy
of the compiler itself, but I don't recommend it.)
Note Well: I have not tested this with REWRITE of typed files and
don't intend to. There is at least one other place in the run-time
memory image where B8023D shows up and it could well be used for
REWRITE. Trying to trace through Turbo's code is beyond me, and if
I need to REWRITE a file I'll set everything back to the load-time
defaults first.
Below is a program which shows how to do this in ver. 3.01a. Note
that the address constants given in the function will have to be
changed if you are using another version of Turbo. It tries to do
a little checking, but it isn't really adequate.
PROGRAM ModifiedTypedFileReset;
(**************************************************
By: Todd M. Lewis,
Microcomputer Support Center
UNC Chapel Hill
(UTODDL@UNC.BITNET)
**************************************************)
TYPE
SharingMode = (Share_Compatability,
Share_DenyReadWrite,
Share_DenyWrite,
Share_DenyRead,
Share_DenyNone);
AccessMode = (Access_Read,
Access_Write,
Access_ReadWrite);
TypedFileModeRetCode = ( TypedFileModeSetOK,
NotDOS3orAbove,
NotTurboVer301a);
FUNCTION SetTypedFileMode( s: SharingMode; a: AccessMode ): TypedFileModeRetCode;
{ N.B.: If this function returns anything other than TypedFileModeSetOK then
the Sharing and Access modes are going to be whatever they were the last
time the funtion returned TypedFileModeSetOK. If the funtion has not been
called and returned TypedFileModeSetOK, then you still have the load-time
defaults (Share_Compatability, Access_ReadWrite). }
TYPE
RegsIType = RECORD
AX, BX, CX, DX, BP,SI,DI,DS,ES,FLAGS: INTEGER;
END;
RegsBType = RECORD
AL,AH,BL,BH,CL,CH,DL,DH : BYTE;
END;
VAR
RegsI : RegsIType; { This gives better control when setting}
RegsB : RegsBType ABSOLUTE RegsI; { regs -- Turbo sometimes screws up when}
{ using CASE INTEGER 1:(..); 2:(..) ! }
BEGIN
RegsB.AH := $30; { Set for DOS function to get DOS version number }
Intr($21,RegsI);
IF ( RegsB.AL >= $03 ) OR { We are either using DOS 3.00 or }
( s = Share_Compatability ) { above, or we are 2.x compatabile.}
THEN IF ( Mem[CSeg:$24FB] = $B8 ) AND { The bytes before and after the patch}
( Mem[CSeg:$24FD] = $3D ) { in Turbo 3.01a are $B8 and $3D... }
THEN BEGIN
Mem[Cseg:$24FC] := BYTE( (ORD(s)*16) + ORD(a) );
SetTypedFileMode := TypedFileModeSetOK;
END
ELSE SetTypedFileMode := NotTurboVer301a
ELSE SetTypedFileMode := NotDOS3orAbove;
{ N.B.: We only get this if we are asking for some sharing}
{ that isn't provided for in earlier versions of DOS. }
END; (* SetTypedFileMode *)
PROCEDURE ShowResult(r:TypedFileModeRetCode);
BEGIN
CASE r OF
TypedFileModeSetOK : Writeln('Typed File Mode Set OK.');
NotDOS3orAbove : Writeln('Not DOS 3.00 or Above.');
NotTurboVer301a : Writeln('Not Turbo Ver. 3.01a');
END; (* CASE *)
END; (* ShowResult *)
(****** Main Block Setup******)
CONST
flName = '_TEST_.TMP';
VAR
f1,f2: File of INTEGER;
i,j : INTEGER;
r : TypedFileModeRetCode;
BEGIN
(* Note: For the Sharing stuff to make any difference, you must have
run the DOS program 'SHARE'. Note also that the PC-NetWork startup
procedure runs 'SHARE'.
First, we need a file to play with, so.... *)
Assign(f1,flName);
Rewrite(f1);
FOR i := 1 TO 100 DO Write(f1,i);
Close(f1);
(* Now we have a file with some data to play with.
Let's try a few things. *)
Write('Share_Compatability, Access_ReadWrite (Turbo default). ');
ShowResult(SetTypedFileMode(Share_Compatability,Access_ReadWrite));
Assign(f1,flName); Reset(f1);
Assign(f2,flName); Reset(f2);
Seek(f1,5); Read(f1,i);
Seek(f2,7); Read(f2,j); Writeln(i,', ',j);
close(f1); close(f2);
Writeln('Press <Enter>...'); Readln;
Write('Share_DenyWrite, Access_Read. ');
ShowResult(SetTypedFileMode(Share_DenyWrite,Access_Read));
Assign(f1,flName); Reset(f1);
Assign(f2,flName); Reset(f2);
Seek(f1,5); Read(f1,i);
Seek(f2,7); Read(f2,j); Writeln(i,', ',j);
close(f1); close(f2);
Writeln('Press <Enter>...'); Readln;
Writeln('Let''s try some read-only file. Assume we are on a system disk.');
Writeln('We''ll use \IBMBIO.COM. If this isn''t a system disk, we''ll die here.')
;
Write('Share_DenyNone, Access_Read. ');
ShowResult(SetTypedFileMode(Share_DenyNone,Access_Read));
Assign(f1,'\IBMBIO.COM'); Reset(f1);
Assign(f2,'\IBMBIO.COM'); Reset(f2);
Seek(f1,5); Read(f1,i);
Seek(f2,7); Read(f2,j); Writeln(i,', ',j);
close(f1); close(f2);
Writeln('Press <Enter>...'); Readln;
Writeln('Now we''ll blow ourselves out of the water. F1''s Share');
Writeln('attributes will keep f2 from working. We''ll abort with');
Writeln('an I/O error 01 -- File Not Found -- when we Reset(f2).');
Write('F1: Share_DenyRead, Access_Read. ');
ShowResult(SetTypedFileMode(Share_DenyRead,Access_Read));
Assign(f1,flName); Reset(f1);
Write('F2: Share_DenyNone, Access_Read. ');
ShowResult(SetTypedFileMode(Share_DenyNone,Access_Read));
Assign(f2,flName); Reset(f2);
Seek(f1,5); Read(f1,i);
Seek(f2,7); Read(f2,j); Writeln(i,', ',j);
close(f1); close(f2);
Writeln('If you got this far and your return codes from calls to ');
Writeln('''SetTypedFileMode'' are ''FileModeSetOK'', then you must');
Writeln('not have run SHARE.');
END.
(**************************************************
By: Todd M. Lewis,
Microcomputer Support Center
UNC Chapel Hill
(UTODDL@UNC.BITNET)
**************************************************)
==============================
--
Jim Gogan mail:ugogan@ecsvax (UUCP/BITNET)
Microcomputing Support Center
University of North Carolina at Chapel Hill
Chapel Hill, NC 27514
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads