362 lines
14 KiB
Plaintext
362 lines
14 KiB
Plaintext
|
DEFINITION MODULE FileSystem;
|
|||
|
(*
|
|||
|
file manipulation routines
|
|||
|
|
|||
|
Derived from the Modula-2 system developed by the
|
|||
|
group of Prof. N. Wirth, ETH Zurich, Switzerland.
|
|||
|
*)
|
|||
|
|
|||
|
|
|||
|
FROM SYSTEM IMPORT ADDRESS, WORD;
|
|||
|
|
|||
|
EXPORT QUALIFIED
|
|||
|
(* file operations: *)
|
|||
|
File, Response, Command,
|
|||
|
Create, Close, Lookup, Rename, Delete,
|
|||
|
SetRead, SetWrite, SetModify, SetOpen,
|
|||
|
Doio, SetPos, GetPos, Length,
|
|||
|
|
|||
|
(* Streamlike I/O: *)
|
|||
|
Flag, FlagSet,
|
|||
|
Reset, Again,
|
|||
|
ReadWord, ReadChar, ReadByte, ReadNBytes,
|
|||
|
WriteWord, WriteChar, WriteByte, WriteNBytes,
|
|||
|
|
|||
|
(* Medium Handling: *)
|
|||
|
FileProc, DirectoryProc,
|
|||
|
MediumType, CreateMedium, RemoveMedium,
|
|||
|
|
|||
|
FileNameChar;
|
|||
|
|
|||
|
|
|||
|
TYPE MediumHint = CARDINAL;
|
|||
|
(*- medium index used in DiskFiles *)
|
|||
|
|
|||
|
MediumType = ARRAY [0..2] OF CHAR;
|
|||
|
(*- medium name (A, B...) *)
|
|||
|
|
|||
|
Flag = (er, ef, rd, wr, ag, txt);
|
|||
|
(*- status flag for file operations
|
|||
|
|
|||
|
er = error occured, ef = end-of-file reached, rd = in read mode, wr = in
|
|||
|
write mode, ag = "Again" has been called after last read, txt = text-file
|
|||
|
(the last access to the file was a 'WriteChar' or 'ReadChar').
|
|||
|
*)
|
|||
|
|
|||
|
FlagSet = SET OF Flag;
|
|||
|
(*- status flag set *)
|
|||
|
|
|||
|
Response = (done, notdone, notsupported, callerror, unknownmedium,
|
|||
|
unknownfile, paramerror, toomanyfiles, eom, userdeverror);
|
|||
|
(*- result of a file operation *)
|
|||
|
|
|||
|
Command = (create, close, lookup, rename, delete, setread, setwrite,
|
|||
|
setmodify, setopen, doio, setpos, getpos, length);
|
|||
|
(*- commands passed to DiskFiles *)
|
|||
|
|
|||
|
BuffAdd = POINTER TO ARRAY [0..0FFFEH] OF CHAR;
|
|||
|
(*- file buffer pointer type *)
|
|||
|
|
|||
|
File = RECORD
|
|||
|
bufa: BuffAdd; (* Buffer Address *)
|
|||
|
buflength: CARDINAL;
|
|||
|
(* size of buffer in bytes. In the current release
|
|||
|
it is always a multiple of 128 *)
|
|||
|
validlength: CARDINAL;
|
|||
|
(* Number of valid bytes in the buffer. *)
|
|||
|
bufind: CARDINAL;
|
|||
|
(* Byte-Index of current position in the buffer *)
|
|||
|
flags: FlagSet; (* status of the file *)
|
|||
|
eof: BOOLEAN;
|
|||
|
(* TRUE, if last access was past end of file *)
|
|||
|
res: Response; (* result of last operation *)
|
|||
|
lastRead:CARDINAL;(* the last read word or byte (char) *)
|
|||
|
mt: MediumType;
|
|||
|
(* selects the driver that supports that file *)
|
|||
|
fHint: CARDINAL; (* internally used by the device-driver *)
|
|||
|
mHint: MediumHint; (* internally used by medium-handler *)
|
|||
|
CASE com: Command OF
|
|||
|
lookup: new: BOOLEAN;
|
|||
|
| setpos, getpos, length: highpos, lowpos: CARDINAL;
|
|||
|
END;
|
|||
|
END;
|
|||
|
(*- file structure used for bookkeeping by DiskFiles *)
|
|||
|
|
|||
|
PROCEDURE Create (VAR f: File; mediumName: ARRAY OF CHAR);
|
|||
|
(*- create a temporary file
|
|||
|
in: mediumName name of medium to create file on, in char format
|
|||
|
out: f initialized file structure
|
|||
|
|
|||
|
A temporary file is characterised by an empty name. To make the file
|
|||
|
permanent, it has to be renamed with a non-empty name before closing it.
|
|||
|
For subsequent operations on this file, it is referenced by "f".
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Close (VAR f: File);
|
|||
|
(*- Close a file
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f the field f.res will be set appropriately.
|
|||
|
|
|||
|
Terminates the operations on file "f". If "f" is a temporary file, it will
|
|||
|
be destroyed, whereas a file with a non-empty name remains on its medium
|
|||
|
and is accessible through "Lookup". When closing a text-file after writing,
|
|||
|
the end-of-file code 32C is written on the file (MS-DOS and CP/M convention).
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Lookup (VAR f: File; filename: ARRAY OF CHAR; newFile: BOOLEAN);
|
|||
|
(*- look for a file
|
|||
|
in: filename drive and name of file to search for
|
|||
|
newFile TRUE if file should be created if not found
|
|||
|
out: f initialized file structure; f.res will be set
|
|||
|
appropriately.
|
|||
|
|
|||
|
Searches the medium specified in "filename" for a file that matches the
|
|||
|
name and type given in "filename". If the file is not found and "newFile"
|
|||
|
is TRUE, a new (permanent) file with the given name and type is created.
|
|||
|
If it is not found and "newFile" is FALSE, no action takes place and
|
|||
|
"notdone" is returned in the result field of "f".
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Rename (VAR f: File; newname: ARRAY OF CHAR);
|
|||
|
(*- rename a file
|
|||
|
in: f structure referencing an open file
|
|||
|
newname filename to rename to, with device:name.type specified
|
|||
|
out: f file name in f will be changed and the f.res field will
|
|||
|
be set appropriately.
|
|||
|
|
|||
|
The medium, on which the files reside can not be changed with this command.
|
|||
|
The medium name inside "newname" has to be the old one.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Delete (name: ARRAY OF CHAR; VAR f: File);
|
|||
|
(*- delete a file
|
|||
|
in: name name of file to delete, with dev:name.type specified
|
|||
|
out: f the result field f.res will be set appropriately.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE ReadWord (VAR f: File; VAR w: WORD);
|
|||
|
(*- Returns the word at the current position in f
|
|||
|
in: f structure referencing an open file
|
|||
|
out: w word read from file
|
|||
|
f the result field f.res will be set appropriately.
|
|||
|
|
|||
|
the file will be positioned at the next word when the read is done.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE WriteWord (VAR f: File; w: WORD);
|
|||
|
(*- Write one word to a file
|
|||
|
in: f structure referencing an open file
|
|||
|
w word to write
|
|||
|
out: f the field f.res will be set appropriately.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE ReadChar (VAR f: File; VAR ch: CHAR);
|
|||
|
(*- Read one character from a file
|
|||
|
in: f structure referencing an open file
|
|||
|
out: ch charatcter read from file
|
|||
|
f the result field f.res will be set appropriately.
|
|||
|
|
|||
|
the file will be positioned at the next character when the read is done.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE WriteChar (VAR f: File; ch: CHAR);
|
|||
|
(*- Write one character to a file
|
|||
|
in: f structure referencing an open file
|
|||
|
ch character to write
|
|||
|
out: f the result field f.res will be set apporopriately.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE ReadByte (VAR f: File; VAR b: CHAR);
|
|||
|
(*- Read one byte from a file
|
|||
|
in: f structure referencing an open file
|
|||
|
out: b byte read from file
|
|||
|
f the result field f.res will be set appropriately.
|
|||
|
|
|||
|
the file will be positioned at the next byte when the read is completed.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE WriteByte (VAR f: File; b: CHAR);
|
|||
|
(*- Write one byte to a file
|
|||
|
in: f structure referencing an open file
|
|||
|
b byte to write
|
|||
|
out: f the result field f.res will be set appropriately.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE ReadNBytes (VAR f: File; bufPtr: ADDRESS;
|
|||
|
requestedBytes: CARDINAL; VAR read: CARDINAL);
|
|||
|
(*- Read a specified number of bytes from a file
|
|||
|
in: f structure referencing an open file
|
|||
|
bufPtr pointer to buffer area to read bytes into
|
|||
|
requestedBytes number of bytes to read
|
|||
|
out: bufPtr^ bytes read from file
|
|||
|
f the result field f.res will be set appropriately.
|
|||
|
read the number of bytes actually read.
|
|||
|
|
|||
|
the file will be positioned at the next byte after the requested string.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE WriteNBytes (VAR f: File; bufPtr: ADDRESS;
|
|||
|
requestedBytes: CARDINAL; VAR written: CARDINAL);
|
|||
|
(*- Write a specified number of bytes to a file
|
|||
|
in: f structure referencing an open file
|
|||
|
bufPtr pointer to string of bytes to write
|
|||
|
requestedBytes number of bytes to write
|
|||
|
out: f the result field f.res will be set appropriately.
|
|||
|
written the number of bytes actually written
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Again (VAR f: File);
|
|||
|
(*- returns a character to the buffer to be read again
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f the f.res field will be set appropriately.
|
|||
|
|
|||
|
This should be called after a read operation only (it has no effect
|
|||
|
otherwise). It prevents the subsequent read from reading the next element;
|
|||
|
the element just read before will be returned a second time. Multiple calls
|
|||
|
to Again without a read in between have the same effect as one call to
|
|||
|
Again. The position in the file is undefined after a call to Again (it is
|
|||
|
defined again after the next read operation).
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE SetRead (VAR f: File);
|
|||
|
(*- Set the file in reading-state, without changing the current position.
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f f.res will be set appropriately.
|
|||
|
|
|||
|
Upon calling SetRead, the current position must be before the eof.
|
|||
|
In reading-state, no writing is allowed.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE SetWrite (VAR f: File);
|
|||
|
(*- Sets the file in writing-state, without changing the current position.
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f f.res will be set appropriately.
|
|||
|
|
|||
|
Upon calling SetWrite, the current position must be a legal position in
|
|||
|
the file (including eof). In writing-state, no reading is allowed, and
|
|||
|
a write always takes place at the eof. The current implementation does
|
|||
|
not truncate the file.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE SetModify (VAR f: File);
|
|||
|
(*- Sets the file in modifying-state, without changing the current position.
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f f.res will be set appropriately.
|
|||
|
Upon calling SetModify, the current position must be before the eof.
|
|||
|
In modifying-state, reading and writing are allowed. Writing is done
|
|||
|
at the current position, overwriting whatever element is already there.
|
|||
|
The file is not truncated.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE SetOpen (VAR f: File);
|
|||
|
(*- Set the file to opened-state, without changing the current position.
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f f.res will be set appropriately.
|
|||
|
|
|||
|
The buffer content is written back on the file, if the file has been in
|
|||
|
writing or modifying status. The new buffer content is undefined.
|
|||
|
In opened-state, neither reading nor writing is allowed.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Reset (VAR f: File);
|
|||
|
(*- Set the file to opened state and position it to the top of file.
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f f.res will be set appropriately.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE SetPos (VAR f: File; high, low: CARDINAL);
|
|||
|
(*- Set the current position in file
|
|||
|
in: f structure referencing an open file
|
|||
|
high high part of the byte offset
|
|||
|
low low part of the byte offset
|
|||
|
out: f f.res will be set appropriately.
|
|||
|
|
|||
|
The file will be positioned (high*2^16 +low) bytes from top of file.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE GetPos (VAR f: File; VAR high, low: CARDINAL);
|
|||
|
(*- Return the current byte position in file
|
|||
|
in: f structure referencing an open file
|
|||
|
out: high high part of byte offset
|
|||
|
low low part of byte offset
|
|||
|
|
|||
|
The actual position is (high*2^16 +low) bytes from the top of file.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Length (VAR f: File; VAR high, low: CARDINAL);
|
|||
|
(*- Return the length of the file in bytes.
|
|||
|
in: f structure referencing an open file.
|
|||
|
out: high high part of byte offset
|
|||
|
low ;pw part of byte offset
|
|||
|
|
|||
|
The actual length is (high*2^16 +low) bytes.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE Doio (VAR f: File);
|
|||
|
(*- Do various read/write operations on a file
|
|||
|
in: f structure referencing an open file
|
|||
|
out: f f.res will be set appropriately.
|
|||
|
|
|||
|
The exact effect of this command depends on the state of the file (flags):
|
|||
|
opened = NOOP.
|
|||
|
reading = reads the record that contains the current byte from the
|
|||
|
file. The old content of the buffer is not written back.
|
|||
|
writing = the buffer is written back. It is then assigned to the
|
|||
|
record, that contains the current position. Its content
|
|||
|
is not changed.
|
|||
|
modifying = the buffer is written back and the record containing
|
|||
|
the current position is read.
|
|||
|
Note that 'Doio' does not need to be used when reading through the
|
|||
|
'stream-like' I/O routines. Its use is limited to special applications.
|
|||
|
*)
|
|||
|
|
|||
|
|
|||
|
PROCEDURE FileNameChar (c: CHAR): CHAR;
|
|||
|
(*- Check the character c for legality in an MS-DOS filename.
|
|||
|
in: c charater to check
|
|||
|
out: 0C for illegal characters and c otherwise; lowercase
|
|||
|
letters are transformed into uppercase letters.
|
|||
|
*)
|
|||
|
|
|||
|
TYPE FileProc = PROCEDURE (VAR File);
|
|||
|
(*- Procedure type to be used for internal file operations
|
|||
|
|
|||
|
A procedure of this type will be called for the functions:
|
|||
|
setread, setwrite, setmodify, setopen, doio,
|
|||
|
setpos, getpos, length, setprotect, getprotect,
|
|||
|
setpermanent, getpermanent.
|
|||
|
*)
|
|||
|
|
|||
|
DirectoryProc = PROCEDURE (VAR File, ARRAY OF CHAR);
|
|||
|
(*- Procedure type to be used for operations on an entire file
|
|||
|
|
|||
|
A procedure of this type will be called for the functions:
|
|||
|
create, close, lookup, rename, delete.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE CreateMedium (mt: MediumType;
|
|||
|
fproc: FileProc; dproc: DirectoryProc;
|
|||
|
VAR done: BOOLEAN);
|
|||
|
(*- Install the medium "mt" in the file system
|
|||
|
in: mt medium type to install
|
|||
|
fproc procedure to handle internal file operations
|
|||
|
dproc procedure to handle operations on an entire file
|
|||
|
out done TRUE if medium was successfully installed.
|
|||
|
|
|||
|
Before accessing or creating a file on a medium, this medium has to be
|
|||
|
announced to the file system by means of the routine CreateMedium.
|
|||
|
FileSystem calls "fproc" and "dproc" to perform operations on a file of
|
|||
|
this medium. Up to 24 mediums can be announced.
|
|||
|
*)
|
|||
|
|
|||
|
PROCEDURE RemoveMedium (mt: MediumType; VAR done: BOOLEAN);
|
|||
|
(*- Remove the medium "mt" from the file system
|
|||
|
in: mt medium type to remove
|
|||
|
out: done true if medium was successfully removed
|
|||
|
|
|||
|
Attempts to access a file on this medium result in an error (unknownmedium).
|
|||
|
*)
|
|||
|
|
|||
|
|
|||
|
END FileSystem.
|
|||
|
|