[Back to FILES SWAG index] [Back to Main SWAG index] [Original]
UNIT FILEIO; { Low Level File handling routines. Jan 18/94 }
{ Copyright (C) 1993,1994 Greg Estabrooks }
{ NOTE: Requires TP 6.0+ to compile. }
INTERFACE
{***********************************************************************}
USES DOS; { IMPORT FSearch. }
CONST { Handles PreDefined by DOS. }
fStdIn = $00; { STD Input Device, (Keyboard). }
fStdOut = $01; { STD Output Device,(CRT). }
fStdErr = $02; { STD Error Device, (CRT). }
fStdCom = $03; { STD Comm. }
fStdPrn = $04; { STD Printer. }
oRead = $00; { Opens a file for read only. }
oWrite = $01; { Opens a file for writing only. }
oReadWrite = $02; { Opens a file for reading and writing. }
oDenyAll = $10; { Deny access to other processes. }
oDenyWrite = $20; { Deny write access to other processes. }
oDenyRead = $30; { Deny read access to other processes. }
oDenyNone = $40; { Allow free access to other processes. }
{ Possible file attribs,can be combined.}
aNormal = $00; aSystem = $04; aArchive = $20;
aReadOnly = $01; aVolume = $08;
aHidden = $02; aDir = $10;
TYPE
LockType = (Lock,UnLock); { Ordinal Type for use with 'fLock'. }
VAR
fError :WORD; { Holds any error codes from routines. }
PROCEDURE ASCIIZ( VAR fName :STRING );
{ Routine to add a NULL to a string to make it }
{ ASCIIZ compatible. }
{ File routines automatically call this routine}
{ usage : }
{ ASCIIZ(fName); }
FUNCTION fCreate( fName :STRING; Attr :BYTE ) :WORD;
{ Routine to Create 'fName' with an attribute }
{ of 'Attr'. If the file already exists then it}
{ will be truncated to a zero length file. }
{ Returns a WORD value containing the handle. }
{ Uses Int 21h/AH=3Ch. }
{ usage : }
{ handle := fCreate('Temp.Dat',aNormal); }
FUNCTION fOpen( fName :STRING; Mode :BYTE ) :WORD;
{ Routine to open already existing file defined}
{ in 'fName' with an opening mode of 'Mode'. }
{ Returns a WORD value containing the handle. }
{ Uses Int 21h/AH=3Dh. }
{ usage : }
{ handle := fOpen('Temp.Dat',oRead); }
PROCEDURE fRead( fHandle :WORD; VAR Buff; NTRead:WORD; VAR ARead :WORD );
{ Reads 'NTRead' bytes of data from 'fHandle' }
{ and puts it in 'Buff'. The actually amount }
{ of bytes read is returned in 'ARead'. }
{ Uses Int 21h/AH=3Fh. }
{ usage : }
{ fRead(handle,Buffer,SizeOf(Buffer),ARead); }
PROCEDURE fWrite( fHandle :WORD; VAR Buff; NTWrite:WORD; VAR AWrite :WORD );
{ Writes 'NTWrite' bytes of info from 'Buff' }
{ to 'fHandle'. The actually amount written is }
{ returned in 'AWrite'. }
{ Uses Int 21h/AH=40h. }
{ usage : }
{ fWrite(handle,Buffer,SizeOf(Buffer),AWrite);}
PROCEDURE fClose( fHandle :WORD );
{ Routine to close file 'fHandle'. This updates}
{ the directory time and size enteries. }
{ Uses Int 21h/AH=3Eh. }
{ usage : }
{ fClose(handle); }
PROCEDURE fReset( fHandle :WORD );
{ Routine to reset file position pointer to the}
{ beginning of 'fHandle'. }
{ Uses Int 21h/AH=42h. }
{ usage : }
{ fReset(handle); }
PROCEDURE fAppend( fHandle :WORD );
{ Routine to move the File position pointer of }
{ 'fHandle' to the end of the file. Any further}
{ writing is added to the end of the file. }
{ Uses Int 21h/AH=42h. }
{ usage : }
{ fAppend(handle); }
PROCEDURE fSeek( fHandle :WORD; fOfs :LONGINT );
{ Routine to move the file position pointer for}
{ 'fHandle' to 'fOfs'. 'fOfs' is the actual }
{ byte position in the file to move to. }
{ Uses Int 21h/AH=42h. }
{ usage : }
{ fSeek(handle,1023); }
PROCEDURE fErase( fName :STRING );
{ Routine to erase 'fName'. }
{ Uses Int 21h/AH=41h. }
{ usage : }
{ fErase('Temp.Dat'); }
FUNCTION fPos( fHandle :WORD ) :LONGINT;
{ Routine to return the current position within}
{ 'fHandle'. }
{ Uses Int 21h/AH=42. }
{ usage : }
{ CurPos := fPos(handle); }
FUNCTION fEof( fHandle :WORD ) :BOOLEAN;
{ Routine to determine whether or not we're }
{ currently at the end of file 'fHandle'. }
{ usage : }
{ IsEnd := fEof(handle); }
FUNCTION fExist( fName :STRING ) :BOOLEAN;
{ Routine to determine whether or not 'fName' }
{ exists. }
{ usage : }
{ Exist := fExist('Temp.Dat'); }
FUNCTION fGetAttr( fName :STRING ) :BYTE;
{ Routine to return the current file attribute }
{ of 'fName'. }
{ Uses Int 21h/AH=43h,AL=00h. }
{ usage : }
{ CurAttr := fGetAttr('Temp.Dat'); }
PROCEDURE fSetAttr( fName :STRING; NAttr :BYTE );
{ Routine to set file attribute of 'fName' to }
{ 'NAttr'. }
{ Uses Int 21h/AH=43h,AL=01h. }
{ usage : }
{ fSetAttr('Temp.Dat',aArchive OR aReadOnly); }
PROCEDURE fSetVerify( On_Off :BOOLEAN );
{ Routine to set the DOS verify flag ON or OFF.}
{ depending on 'On_Off'. }
{ TRUE = ON, FALSE = OFF. }
{ Uses Int 21h/AH=2Eh. }
{ usage : }
{ fSetVerify( TRUE ); }
FUNCTION fGetVerify :BOOLEAN;
{ Routine to return the current state of the }
{ DOS verify flag. }
{ Uses Int 21h/AH=54h. }
{ usage : }
{ IsVerify := fGetVerify; }
FUNCTION fSize( fHandle :WORD ) :LONGINT;
{ Routine to determine the size in bytes of }
{ 'fHandle'. }
{ usage : }
{ CurSize := fSize(handle); }
PROCEDURE fFlush( fHandle :WORD );
{ Flushes any File buffers for 'fHandle' }
{ immediately and updates the directory entry. }
{ Uses Int 21h/AH=68h. }
{ usage : }
{ fFlush(handle); }
PROCEDURE fLock( fHandle :WORD; LockInf :LockType; StartOfs,Len :LONGINT );
{ Routine to lock/unlock parts of a open file. }
{ Locking or unlock is determined by 'LockInf'. }
{ Uses Int 21h/AH=5Ch. }
{ usage : }
{ fLock(handle,Lock,1000,500); }
{***********************************************************************}
IMPLEMENTATION
PROCEDURE ASCIIZ( VAR fName :STRING ); ASSEMBLER;
{ Routine to add a NULL to a string to make it }
{ ASCIIZ compatible. }
{ File routines automatically call this routine}
ASM
Push DS { Push DS onto the stack. }
LDS DI,fname { Point DS:DI ---> fName. }
Xor BX,BX { Clear BX. }
Mov BL,BYTE PTR DS:[DI] { Load length of string into BL. }
Inc BL { Point to char after last one in name. }
Mov BYTE PTR DS:[DI+BX],0 { Now make it a ASCIIZ string. }
Pop DS { Pop DS off the stack. }
END;{ASCIIZ}
FUNCTION fCreate( fName :STRING; Attr :BYTE ) :WORD;
{ Routine to Create 'fName' with an attribute }
{ of 'Attr'. If the file already exists then it}
{ will be truncated to a zero length file. }
{ Returns a WORD value containing the handle. }
{ Uses Int 21h/AH=3Ch. }
BEGIN
ASCIIZ(fName); { Convert fName to an ASCIIZ string. }
ASM
Push DS { Push DS Onto stack. }
Mov fError,0 { Clear Error Flag. }
Mov AX,SS { Load AX with SS. }
Mov DS,AX { Now load that value into DS. }
Lea DX,fName { Now load DX with the offset of DX. }
Inc DX { Move past length byte. }
Xor CH,CH { Clear High byte of CX. }
Mov CL,Attr { Load attribute to give new file. }
Mov AH,$3C { Function to create a file. }
Int $21 { Call dos to create file. }
Jnc @Exit { If no error exit. }
Mov fError,AX { If there was an error save it. }
@Exit:
Mov @Result,AX { Return proper result to user. }
Pop DS { Pop DS Off the Stack. }
END;
END;{fCreate}
FUNCTION fOpen( fName :STRING; Mode :BYTE ) :WORD;
{ Routine to open already existing file defined}
{ in 'fName' with an opening mode of 'Mode'. }
{ Returns a WORD value containing the handle. }
{ Uses Int 21h/AH=3Dh. }
BEGIN
ASCIIZ(fName); { Convert fName to an ASCIIZ string. }
ASM
Push DS { Push DS onto stack. }
Mov fError,0 { Clear Error Flag. }
Mov AX,SS { Load AX with SS. }
Mov DS,AX { Now load that value into DS. }
Lea DX,fName { Now load DX with the offset of DX. }
Inc DX { Move past length byte. }
Mov AL,Mode { File Opening mode. }
Mov AH,$3D { Function to open a file. }
Int $21 { Call dos to open file. }
Jnc @Exit { If no error exit. }
Mov fError,AX { If there was an error save it. }
@Exit:
Mov @Result,AX { Return proper result to user. }
Pop DS { Restore DS from stack. }
END;
END;{fOpen}
PROCEDURE fRead( fHandle :WORD; VAR Buff; NTRead:WORD; VAR ARead :WORD );
ASSEMBLER; { Reads 'NTRead' bytes of data from 'fHandle' }
{ and puts it in 'Buff'. The actually amount }
{ of bytes read is returned in 'ARead'. }
{ Uses Int 21h/AH=3Fh. }
ASM
Push DS { Push DS onto the stack. }
Mov fError,0 { Clear Error flag. }
Mov AH,$3F { Function to read from a file. }
Mov BX,fHandle { load handle of file to read. }
Mov CX,NTRead { # of bytes to read. }
LDS DX,Buff { Point DS:DX to buffer. }
Int $21 { Call Dos to read file. }
LDS DI,ARead { Point to amount read. }
Mov WORD PTR DS:[DI],AX { Save amount actually read. }
Jnc @Exit { if there was no error exit. }
Mov fError,AX { If there was Save error code. }
@Exit:
Pop DS { Pop DS off the stack. }
END;{fRead}
PROCEDURE fWrite( fHandle :WORD; VAR Buff; NTWrite:WORD; VAR AWrite :WORD );
ASSEMBLER; { Writes 'NTWrite' bytes of info from 'Buff' }
{ to 'fHandle'. The actually amount written is }
{ returned in 'AWrite'. }
{ Uses Int 21h/AH=40h. }
ASM
Push DS { Push DS onto the stack. }
Mov fError,0 { Clear Error flag. }
Mov AH,$40 { Function to write to file. }
Mov BX,fHandle { Handle of file to write to. }
Mov CX,NTWrite { # of bytes to read. }
LDS DX,Buff { Point DS:DX -> Buffer. }
Int $21 { Call Dos to write to file. }
LDS DI,AWrite { Point to amount write. }
Mov WORD PTR DS:[DI],AX { Save amount actually written. }
Jnc @Exit { If there was no error exit. }
Mov fError,AX { if there was save error code. }
@Exit:
Pop DS { Pop DS off the stack. }
END;{fWrite}
PROCEDURE fClose( fHandle :WORD ); ASSEMBLER;
{ Routine to close file 'fHandle'. This updates}
{ the directory time and size enteries. }
{ Uses Int 21h/AH=3Eh. }
ASM
Mov fError,0 { Clear Error flag }
Mov AH,$3E { Function to close file }
Mov BX,fHandle { load handle of file to close }
Int $21 { call Dos to close file }
Jnc @Exit { If there was no error exit }
Mov fError,AX { if there was save error code }
@Exit:
END;{fClose}
PROCEDURE fReset( fHandle :WORD ); ASSEMBLER;
{ Routine to reset file position pointer to the}
{ beginning of 'fHandle'. }
{ Uses Int 21h/AH=42h. }
ASM
Mov fError,0 { Clear error flag. }
Mov AH,$42 { Function to move file pointer. }
Mov BX,fHandle { Handle of file. }
Mov AL,0 { Offset relative to begining. }
Mov CX,0 { CX:DX = offset from begining of file }
Mov DX,0 { to move to. }
Int $21 { Call dos to change file pointer. }
Jnc @Exit { If there was no error exit. }
Mov fError,AX { If there was save error code. }
@Exit:
END;{fReset}
PROCEDURE fAppend( fHandle :WORD); ASSEMBLER;
{ Routine to move the File position pointer of }
{ 'fHandle' to the end of the file. Any further}
{ writing is added to the end of the file. }
{ Uses Int 21h/AH=42h. }
ASM
Mov fError,0 { Clear error flag. }
Mov AH,$42 { Function to change file ptr position. }
Mov BX,fHandle { handle of file to change. }
Mov AL,$02 { Change relative to end of file. }
Mov CX,0 { CX:DX = offset from end of file }
Mov DX,0 { to move to. }
Int $21 { Call dos to move file ptr. }
Jnc @Exit { If there was no error exit. }
Mov fError,AX { If there was save error code. }
@Exit:
END;{fAppend}
PROCEDURE fSeek( fHandle :WORD; fOfs :LONGINT ); ASSEMBLER;
{ Routine to move the file position pointer for}
{ 'fHandle' to 'fOfs'. 'fOfs' is the actual }
{ byte position in the file to move to. }
{ Uses Int 21h/AH=42h. }
ASM
Mov fError,0 { Clear error flag. }
Mov AH,$42 { Function to change file ptr position. }
Mov BX,fHandle { handle of file to change. }
Mov AL,$00 { Change relative to start of file. }
Mov CX,fOfs[2].WORD { CX:DX = offset from start of file }
Mov DX,fOfs.WORD { to move to. }
Int $21 { Call dos to move file ptr. }
Jnc @Exit { If there was no error exit. }
Mov fError,AX { If there was save error code. }
@Exit:
END;{fSeek}
PROCEDURE fErase( fName :STRING );
{ Routine to erase 'fName'. }
{ Uses Int 21h/AH=41h. }
BEGIN
ASCIIZ(fName); { Convert fName to an ASCIIZ string. }
ASM
Push DS { Push DS onto the stack. }
Mov fError,0 { Clear error flag. }
Mov AX,SS { Load AX with SS. }
Mov DS,AX { Now load that value into DS. }
Lea DX,fName { Now load DX with the offset of DX. }
Inc DX
Mov AH,$41 { Function to erase a file. }
Int $21 { Call dos to erase file. }
Jnc @Exit { If no error exit. }
Mov fError,AX { if there was error save error code. }
@Exit:
Pop DS { Pop DS off the stack. }
END;
END;{fErase}
FUNCTION fPos( fHandle :WORD ) :LONGINT; ASSEMBLER;
{ Routine to return the current position within}
{ 'fHandle'. }
{ Uses Int 21h/AH=42. }
ASM
Mov fError,0 { Clear error flag. }
Mov AH,$42 { Function to move file pointer. }
Mov BX,fHandle { Handle of file. }
Mov AL,1 { Offset relative to current pos. }
Mov CX,0 { CX:DX = offset from current position }
Mov DX,0 { to move to. }
Int $21 { Call dos to change file pointer. }
Jnc @Exit { If there was no error return result. }
Mov fError,AX { If there was save error code. }
@Exit: { Int already returns DX:AX as file pos.}
END;{fPos}
FUNCTION fEof( fHandle :WORD ) :BOOLEAN;
{ Routine to determine whether or not we're }
{ currently at the end of file 'fHandle'. }
VAR
CurOfs :LONGINT; { current file offset. }
BEGIN
CurOfs := fPos(fHandle); { Save Current Pos. }
fAppend(fHandle); { Move to the end of the file. }
fEof := (CurOfs = fPos(fHandle)); { was current pos = end pos?. }
fSeek(fHandle,CurOfs); { Restore to original file position. }
END;{fEof}
FUNCTION fExist( fName :STRING ) :BOOLEAN;
{ Routine to determine whether or not 'fName' }
{ exists. }
BEGIN
fExist := ( FSearch(fName,'') <> '');
END;{fExist}
FUNCTION fGetAttr( fName :STRING ) :BYTE;
{ Routine to return the current file attribute }
{ of 'fName'. }
{ Uses Int 21h/AH=43h,AL=00h. }
BEGIN
ASCIIZ(fName); { Convert fName to an ASCIIZ string. }
ASM
Push DS { Push DS onto the stack. }
Mov fError,0 { Clear error flag. }
Mov AX,SS { Load AX with SS. }
Mov DS,AX { Now load that value into DS. }
Lea DX,fName { Now load DX with the offset of DX. }
Inc DX
Mov AX,$4300 { Function to Get file Attrib. }
Int $21 { Call dos to get attr. }
Jnc @Success { If no error return proper info. }
Mov fError,AX { if there was error save error code. }
@Success:
Mov AX,CX
Mov @Result,AL { Return proper result to user. }
Pop DS { Pop DS off the stack. }
END;
END;{fGetAttr}
PROCEDURE fSetAttr( fName :STRING; NAttr :BYTE );
{ Routine to set file attribute of 'fName' to }
{ 'NAttr'. }
{ Uses Int 21h/AH=43h,AL=01h. }
BEGIN
ASCIIZ(fName); { Convert fName to an ASCIIZ string. }
ASM
Push DS { Push DS onto the stack. }
Mov fError,0 { Clear error flag. }
Mov AX,SS { Load AX with SS. }
Mov DS,AX { Now load that value into DS. }
Lea DX,fName { Now load DX with the offset of DX. }
Inc DX { Point to first char after length byte.}
Xor CX,CX { Clear CX. }
Mov CL,NAttr { Load New attribute byte. }
Mov AX,$4301 { Function to Set file Attrib. }
Int $21 { Call dos to set attrib. }
Jnc @Exit { If no error exit. }
Mov fError,AX { if there was error save error code. }
@Exit:
Pop DS { Pop DS off the stack. }
END;
END;{fSetAttr}
PROCEDURE fSetVerify( On_Off :BOOLEAN ); ASSEMBLER;
{ Routine to set the DOS verify flag ON or OFF.}
{ depending on 'On_Off'. }
{ TRUE = ON, FALSE = OFF. }
{ Uses Int 21h/AH=2Eh. }
ASM
Mov AH,$2E { Interrupt Subfunction. }
Mov DL,0 { Clear DL. }
Mov AL,On_Off { 0(FALSE) = off, 1(TRUE) = on. }
Int $21 { Call Dos. }
END;{fSetVerify}
FUNCTION fGetVerify :BOOLEAN; ASSEMBLER;
{ Routine to return the current state of the }
{ DOS verify flag. }
{ Uses Int 21h/AH=54h. }
ASM
Mov AH,$54 { Interrupt Subfunction }
Int $21 { Call Dos }
END;{fGetVerify}
FUNCTION fSize( fHandle :WORD ) :LONGINT;
{ Routine to determine the size in bytes of }
{ 'fHandle'. }
VAR
CurOfs :LONGINT; { Holds original file pointer. }
BEGIN
CurOfs := fPos(fHandle); { Save current file pointer. }
fAppend(fHandle); { Move to end of file. }
fSize := fPos(fHandle); { Save current pos which equals size. }
fSeek(fHandle,CurOfs); { Restore original file pos. }
END;{fSize}
PROCEDURE fFlush( fHandle :WORD ); ASSEMBLER;
{ Flushes any File buffers for 'fHandle' }
{ immediately and updates the directory entry. }
{ Uses Int 21h/AH=68h. }
ASM
Mov fError,0 { Clear error flag. }
Mov AH,$68 { Function to Commit file to disk. }
Mov BX,fHandle { Load handle of file to Commit. }
Int $21 { Call dos to flush file. }
Jnc @Exit { If no error exit. }
Mov fError,AX { if there was error save error code. }
@Exit:
END;{fSetAttr}
PROCEDURE fLock( fHandle :WORD; LockInf :LockType; StartOfs,Len :LONGINT );
{ Routine to lock/unlock parts of a open file. }
ASSEMBLER; { Locking or unlock is determined by 'LockInf'. }
{ Uses Int 21h/AH=5Ch. }
ASM
Mov fError,0 { Clear Error Flag. }
Mov AH,$5C { Function to lock/unlock part of a file.}
Mov AL,LockInf { Load whether to lock/unlock file area.}
Mov BX,fHandle { Handle of file to lock. }
Mov CX,StartOfs.WORD[0] { Load StartOfs Into CX:DX. }
Mov DX,StartOfs.WORD[2]
Mov SI,Len.WORD[0] { Load Len Into SI:DI. }
Mov DI,Len.WORD[2]
Int $21 { Call dos to lock area. }
Jnc @Exit { If no error exit. }
Mov fError,AX { If there was an error save it. }
@Exit:
END;{fLock}
BEGIN
END.{FileIO}
[Back to FILES SWAG index] [Back to Main SWAG index] [Original]