home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
-
-
- Methods for Dealing with Shared Files
- in TURBO Pascal Version 5.0
- by
- John W. Wulff
- Wulff Enterprises, Inc.
- 260 Terranova Drive
- Warrenton, VA 22186-9227
- (703) 349-8805
-
- Revised May 15, 1989
-
- This paper was first written January 19, 1987 as a means of
- demonstrating how to modify Turbo Pascal 3.x to handle the
- opening of READ-ONLY files and to make it able to deal with files
- in a Shared, network environment. It provided a means of finding
- an undocumented byte known as the "Open Mode Byte". Since then,
- Turbo Pascal 5.0 has been released and this byte has been
- globally declared as the FILEMODE variable. Even so, Turbo
- Pascal 5.0 ignores the variable when opening TEXT files. While
- there is a small explanation in the Turbo Pascal Reference Guide
- as to its use, the information in this paper is still valid today
- and has been updated to reflect its relevance to Turbo Pascal
- 5.0. For those wishing to continue to work in Turbo Pascal 3.0,
- I have included the locations for this byte in appendix A.
-
- There have been many innovations in the development of PCBoard
- software for BBS's. One of which is the network environment that
- the authors have included in the code. While this is wonderful
- for the multi-node system, it does pose certain problems and
- restrictions on application programs and utilities that are being
- written for it, especially those written in Borland's Turbo
- Pascal.
-
- One problem that plagues most authors writing application
- programs that eventually become used in network environments is
- coping with the Share utility that DOS uses to protect files.
- Any file opened for reading under Turbo Pascal will cause a
- Sharing violation if running under a DOS 3.x and 4.x networking
- mode. This is because Turbo Pascal opens all files in what is
- known as "Inherited by Child Processes, Compatibility Mode,
- Read/Write access".
-
- I have written a utility for PCBoard systems, PCBFile, and since
- it is extremely file intensive, I've had to do some research on
- the technical aspects of DOS in the network mode. Because of
- this research, I've been able to get Turbo Pascal to cooperate
- and have written this paper to help other authors who are
- struggling with the same problems.
-
- As documented in the Turbo Pascal instructions, the FILEMODE
- variable has a value of 2 when opening files for RESET or REWRITE
- which allows both reading and writing. The instructions suggest
- that you should assign a value of 0 to the variable to RESET or
- REWRITE read-only files. While this works for READ-ONLY files,
-
-
-
-
-
-
-
-
-
-
-
-
- it is not the only value to consider when running an application
- in a network environment, especially one with PCBoard software
- upon which I will focus my attention for the remainder of the
- document.
-
- One thing to consider, if using other languages, especially
- assembly language, is that this FILEMODE variable, corresponds to
- the AL register. All references to that byte and its decimal
- number can be applied to assembly in this way:
-
- AH contains 3DH - the function call
- DS:DX points to an ASCIIZ path name
- AL will be loaded with the 8 bit number that the
- FILEMODE variable contains.
-
- When the function returns, AX will contain error codes or a 16
- bit file handle if successful. (See DOS manual for details.) I
- don't profess to be anywhere close to fluent in assembly so I
- will leave this information with those who are best suited to
- take advantage of it.
-
- This variable is GLOBALLY pre-declared in Turbo Pascal, so all
- you have to do is refer to it as FILEMODE. Then a simple check
- is necessary to see if the variable contains a 2 and if so, load
- it with a 0:
-
- begin
- if FILEMODE = 2 then
- FILEMODE := 0;
- end;
-
- The completed routine would look like this:
-
- Procedure OpenMode(Var OpenFile : text;
- InFileName : string
- Var GoAhead : boolean);
-
- {Remember, FILEMODE is a GLOBALLY declared variable of type
- byte. No other declaration is necessary on your part}
-
- begin
- if FILEMODE = 2 then
- FILEMODE := 0; (* allows reading of READ-ONLY files *)
- assign(OpenFile,InFileName);
- {$I-} reset(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if GoAhead then
- writeln(InFileName,' opened!')
- else
- writeln(InFileName,' failed to open!');
- end; { of Procedure OpenMode }
-
-
- Shared Files in Turbo Pascal 5.0 2
-
-
-
-
-
-
-
-
-
-
-
-
- Now we need to determine just what is going on with PCBoard and
- how it opens files using DOS's SHARE. The DIR files, or the
- files that contain the filenames of the available files for the
- user to download, are opened in READ SHARED mode which in
- QuickBASIC would be:
-
- OPEN "<filename>" FOR INPUT ACCESS READ SHARED AS #1.
-
- Upload DIR files are opened for APPEND in a LOCKED WRITE mode.
- This keeps other nodes from writing at that particular moment but
- allows other nodes to read this file.
-
- In order to accomplish these same modes in Turbo Pascal we must
- look into the DOS Technical Reference Manual (groan!). The
- following is reprinted from that manual with some additions by
- me.
-
- The OPEN mode consists of 4 bit-oriented fields:
- * INHERITANCE FLAG
- * SHARING MODE FIELD
- * RESERVED FIELD
- * ACCESS FIELD
- The INHERITANCE FLAG determines if the file will ever be
- inherited by another process, which in the case of a network is
- usually the desired effect. The SHARING FIELD defines what
- operations may be performed on the file by other nodes. The
- ACCESS FIELD defines what operations THIS node may perform on the
- file.
-
- 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 like this:
- if S = 000; Compatibility mode - The default open mode - it
- denies ALL OTHER processes access to the file.
- Since this is the mode that Turbo Pascal uses to
- open a file, what do you think will happen on the
- BBS side if you have a file open on your end and
- the BBS tries to open it?
- if S = 001; Deny Read/Write mode (Exclusive). This would
- actually be the same as setting the I flag to 1.
- if S = 010; Deny Write mode - you should open a file in this
- mode if you wish to protect it. It will allow
- other processes to read it but not write.
- if S = 011; Deny Read mode
- if S = 100; Deny None mode - Who cares what happens!
-
-
- Shared Files in Turbo Pascal 5.0 3
-
-
-
-
-
-
-
-
-
-
-
-
- It is important to specify what operations you want to perform
- (access mode). The default access mode is Read/Write and causes
- the open request to fail if another process has the file opened
- with any sharing mode other than Deny None. File sharing
- requires cooperation of both sharing processes. This is
- communicated through the sharing and access modes.
-
- R RESERVED (set third bit field to 0)
-
- A ACCESS - The file access is assigned as follows:
-
- If A = 000; Read Access
- if A = 001; Write Access
- if A = 010; Read/Write access
-
- If all this seems a bit involved, I'm sorry. I don't know of any
- way to give you the background for all this hocus-pocus except
- with the above info. I also recommend picking up a Tech Ref
- manual for more detailed study of the 3DH function call.
-
- OK! With all these numbers in hand, let's see how to get Turbo
- Pascal to duplicate these modes. Earlier I said that other gurus
- had stated that Turbo Pascal opens files in COMPATIBILITY MODE
- with READ/WRITE ACCESS and INHERITANCE BY CHILD PROCESSES and the
- magic value for the FILEMODE variable is 2. Let's look at how
- that was done:
-
- Compatibility mode: 000 {S}
- Read/Write ACCESS : 010 {A}
- Inherited by child: 0 {I}
- Reserved as ALWAYS: 0 {R}
-
- Remember the bit fields are:
- <I> < S > <R> < A >
- Open Mode bits 7 6 5 4 3 2 1 0 Let's plug in
- 0 0 0 0 0 0 1 0 the numbers.
- Using binary arithmetic:
- <I> < S > <R> < A >
- 128 64 32 16 8 4 2 1
- 0 0 0 0 0 0 1 0 = 00000010 = 2
-
- By using a FILEMODE value of 0 we change the ACCESS field to 000,
- READ ACCESS, which allows us to read a READ-ONLY file.
-
- PCBoard is opening its DIR files as READ ACCESS SHARED and
- actually opening the file with a SHARING MODE of Deny/Write which
- would be a SHARE <S> field of 010. The value for the FILEMODE
- variable then becomes:
- <I> < S > <R> < A >
- 128 64 32 16 8 4 2 1
- 0 0 1 0 0 0 0 0 = 00100000 = 32
-
-
- Shared Files in Turbo Pascal 5.0 4
-
-
-
-
-
-
-
-
-
-
-
-
- This is how I open ALL my files for reading or for general
- ASSIGNING for RESET in Turbo Pascal for my program PCBFile. I
- have some procedures written for TEXT files, and files of type
- BYTE. I have reproduced the code below:
- (* This procedure, KeepOn, is used to determine if the file has
- been locked out. I try a file for 10 times as determined by
- OpenAtt variable before I give up *)
-
- Procedure KeepOn(OpenAtt : byte; var GA : boolean);
- begin
- if OpenAtt <= 10 then
- GA := TRUE (* GoAhead Flag - if within 10 go for it *)
- else GA := FALSE; (* forget it! *)
- end; {of Procedure KeepOn}
-
- Procedure SetResetMode(Var OpenFile : text; (* OPEN MODE FOR
- InFileName : string; TEXT FILES *)
- Var GoAhead : boolean);
- var
- OpenAttempts : byte;
-
- begin
- OpenAttempts := 1;
- FILEMODE := 32; (* this is Deny Write
- Mode/Read Access *)
- assign(OpenFile,InFileName);
- repeat
- {$I-} reset(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if not GoAhead then
- OpenAttempts := OpenAttempts + 1;
- until (GoAhead) OR (OpenAttempts > 10); (* keep trying *)
- KeepOn(OpenAttempts,GoAhead);
- end; {of Procedure SetResetMode}
-
- Procedure SetResetModeFile(Var OpenFile : file of byte
- InFileName : string;
- var GoAhead : boolean);
- var
- OpenAttempts : byte;
- begin
- OpenAttempts := 1;
- if FILEMODE := 32; (* this is Deny Write
- Mode/Read Access *)
- assign(OpenFile,InFileName);
- repeat
- {$I-} reset(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if not GoAhead then OpenAttempts := OpenAttempts + 1;
- until GoAhead OR (OpenAttempts > 10);
- KeepOn(OpenAttempts,GoAhead);
- end; {of Procedure SetResetModeFile}
-
- Shared Files in Turbo Pascal 5.0 5
-
-
-
-
-
-
-
-
-
-
-
-
-
- Now here comes a little zinger to change things up. I want to
- create a file that I don't want the other nodes to damage. I
- elect to open the file for READ/WRITE ACCESS for myself and give
- the other nodes READ capability and deny them the ability to
- write to my file. This would be Deny/Write Mode under the <S> or
- SHARING FIELD and would be coded 010. For READ/WRITE ACCESS the
- <A> or ACCESS FIELD is coded 010 also. This is the same mode
- that PCBoard uses for writing to the Upload directory. Using our
- binary formulae, the FILEMODE value then becomes:
- <I> < S > <R> < A >
- 128 64 32 16 8 4 2 1
- 0 0 1 0 0 0 1 0 = 00100010 = 34
-
- With the magic number of 34 the SetFileLock procedure was born.
-
- Procedure SetFileLock(Var OpenFile : text;
- InFileName : string;
- var GoAhead : boolean);
- var
- OpenAttempts : byte;
-
- begin
- OpenAttempts := 1;
- FILEMODE := 34; (* Deny Write Mode/Read-Write Access *)
- assign(OpenFile,InFileName);
- repeat
- {$I-} rewrite(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if not GoAhead then
- OpenAttempts := OpenAttempts + 1;
- until GoAhead or (OpenAttempts > 10);
- KeepOn(OpenAttempts,GoAhead);
- end; {of Procedure SetFileLock}
-
- Finally, a little walk around the park to insure that the
- FILEMODE variable is returned to Borland's normal mode.
-
- Procedure ReleaseOpenMode;
-
- begin
- FILEMODE := 2;
- end;
-
- So it's really simple to change the Turbo Pascal Open mode to
- exactly what you want, you just have to know what results you
- desire from the program. Just remember these definitions of the
- fields that make up the magic number for DOS Function call 3DH.
-
- * INHERITANCE FLAG I = 0; Inherited (usually the case)
- I = 1; Private
-
-
- Shared Files in Turbo Pascal 5.0 6
-
-
-
-
-
-
-
-
-
-
-
-
- * SHARING MODE FIELD (Other node or process)
- S = 000; Compatibility mode
- S = 001; Deny Read/Write mode
- (Exclusive)
- S = 010; Deny Write mode
- S = 011; Deny Read mode
- S = 100; Deny None mode
-
- * RESERVED FIELD R = 0; Always
-
- * ACCESS FIELD (Your node or process)
- A = 000; Read Access
- A = 001; Write Access
- A = 010; Read/Write Access
- The bit fields:
- <I> < S > <R> < A >
- Open Mode bits 7 6 5 4 3 2 1 0
-
- Even though a DOS Technical Reference Manual gives a more
- thorough discussion of Function Call 3DH, I will attempt to
- create a matrix with the number for the FILEMODE variable based
- on the SHARE and ACCESS fields.
-
- ACCESS |SHARE-> Compat Deny/RW Deny/W Deny/R Deny/N
- | 000 001 010 011 100
- v -------------------------------------------
- Read 000 | 0 | 16 | 32 | 48 | 64 |
- |--------|-------|-------|-------|--------|
- Write 001 | 1 | 17 | 33 | 49 | 65 |
- |--------|-------|-------|-------|--------|
- Read/ 010 | 2 | 18 | 34 | 50 | 66 |
- Write -------------------------------------------
-
- I know that this is probably more than a human can bear to
- assimilate at any one time but I hope that you will be able to
- see the logic behind my system and be able to use Turbo Pascal to
- its full potential.
-
- PCBoard (c) Clark Development Company, Inc., Murray, UT
- Turbo Pascal (c) Borland International, Scotts Valley, CA
- PCBFile (c) John W. Wulff
- Compuserve (c) Compuserve, Inc., Columbus, OH
-
-
-
-
-
-
-
-
-
-
-
- Shared Files in Turbo Pascal 5.0 7
-
-
-
-
-
-
-
-
-
-
-
-
-
- Appendix
-
- For Turbo Pascal 3.x Die-Hards:
-
- Bela Lubkin published a text article, ACMODE.DOC, which is on
- Compuserve in the Borland Sig that gives the locations of a
- little gem known as the "Open Mode Byte". This byte is at an
- absolute address for the various editions of Turbo Pascal and
- communicates to DOS, via Function call 3DH, how the file is to be
- accessed and what access to give other processes. It also
- becomes very handy for us in trying to use Turbo Pascal in a
- network environment. These locations are:
- Open mode byte for Reset & Rewrite for Turbo 3.00x (PC-DOS)
- TURBO.COM CSEG:$248D
- TURBO-87.COM CSEG:$1F3C
- TURBOBCD.COM CSEG:$2393
- Open mode byte for Reset & Rewrite for Turbo 3.00x (MS-DOS)
- TURBO.COM CSEG:$2182
- TURBO-87.COM CSEG:$1C31
- TURBOBCD.COM CSEG:$2088
- Open mode byte for Reset & Rewrite for Turbo 3.01x (PC-DOS)
- TURBO.COM CSEG:$24FC
- TURBO-87.COM CSEG:$1FAB
- TURBOBCD.COM CSEG:$2402
- Open mode byte for Reset & Rewrite for Turbo 3.01x (MS-DOS)
- TURBO.COM CSEG:$21D4
- TURBO-87.COM CSEG:$1C83
- TURBOBCD.COM CSEG:$20DA
- Open mode byte for Reset & Rewrite for Turbo 3.02x (PC-DOS)
- TURBO.COM CSEG:$24C6
- TURBO-87.COM CSEG:$1F75
- TURBOBCD.COM CSEG:$23CE
-
- Another valuable document is Robert K. Blaine's RES_MODE.INC,
- also available on CSERV. It details the procedure for finding
- out the location of this byte, using DEBUG.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Shared Files in Turbo Pascal 5.0 8
-
-
-
-
-
-
-