|
|
DataMuseum.dkPresents historical artifacts from the history of: Bogika Butler |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Bogika Butler Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 52736 (0xce00)
Types: TextFile
Names: »VERSAFS.SA«
└─⟦311ba069f⟧ Bits:30009789/_.ft.Ibm2.50006625.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »VERSAFS.SA«
└─⟦49237ce80⟧ Bits:30009789/_.ft.Ibm2.50006627.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »VERSAFS.SA«
└─⟦714bbb381⟧ Bits:30009789/_.ft.Ibm2.50006595.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »VERSAFS.SA«
æ*****************************************************************
Copyright 1984 by
NCR Corporation
Dayton, Ohio U.S.A.
All Rights Reserved
******************************************************************
EOS Software produced by:
NCR Systems Engineering - Copenhagen
Copenhagen
DENMARK
*****************************************************************å
æ$h=0åæ No heap space å
OBJECT PROGRAM VersaFs;
æ
VV VV EEEEEE RRRRR SSSS AA FFFFFF SSSS
VV VV EE RR RR SS SS AAAA FF SS SS
VV VV EE RR RR SS AA AA FF SS
VV VV EEEE RRRRR SSSS AAAAAA == FFFFF SSSS
VVVV EE RR R SS AA AA FF SS
VVVV EE RR RR SS SS AA AA FF SS SS
VV EEEEEE RR RR SSSS AA AA FF SSSS
V E R S A F S
Change history: 83-06-20, EAR, first version
83-07-10, VIR, read/write less than one page
83-09-28, EAR, allow null-char for end of file name
vers.01.01 83-11-09, EAR, re-entrant fao
vers.01.02 83-11-15, EAR, check ioRights in DataSize
vers.01.03 83-12-01, EAR, changed iosys.id
exclude: moveMan in terminate loop
å CONST procId = 'versafs vers.01.03 83-12-01 '; æ
The VersaFs Module is a low level file system for Motorola's
VersaDos file format.
In the present implementation only contiguous files are allowed, and
creation/deletion of files is not implemented.
The VersaFs contains the following entries:
OBJECT FileSystem;
ENTRY Assign (ownedFao; fileName, ioRights Æ, createMode Æ, volumeÅÅ );
Creates a File Access Object (FAO) to the file named
by 'fileName'. The disc must have been included previously.
The file is reserved according to 'ioRights':
Write reservation demands that no other FAO have any
access to the same file; read reservation demands only
that no other FAO have write access to the file.
The present implementation handles only contiguous files,
which must exist on disc when assign is called. The
optional parameter 'createMode' has a special meaning in
this implementation: When the parameter is specified with
the value 'NewFile', the logical end-of-file is reset to -1
denoting an empty file.
The logical end-of-file may contain the following values
(which are not in accordance with Versados):
-1: empty file
0: end-of-file = allocation limit
(standard when a contiguous file is created
by Versados)
>0: LSN (logical sector no) of end-of-file pos
ENTRY Include (; devName Æ, readOnlyÅ );
This procedure includes the disc specified by 'deviceName'.
The proper driver system is found, and a Disc Access Object
(DAO) is created by the object call "driver.assign".
If the optional parameter 'readOnly' is specified as <> 0, all
files on the disc can only be read, i.e all calls of WriteSeq
and WriteRandom will be rejected. Default value is false.
ENTRY Exclude (; devName Æ, abortAllowedÅ );
This procedure removes the disc specified by 'deviceName' from
the system.
The value of the optional parameter 'abortAllowed' determines the
reaction on any open FAO on the disc: If 'abortAllowed' <> 0
all open FAOs on the disc are aborted, and the termination
procedure is called. Otherwise Exclude is rejected if any
open FAO is found. Default value is false.
The Disc Access Object (DAO) corresponding to 'deviceName' is
deallocated. If this fails, the deallocation must be performed
when the device is included again.
OBJECT Fao;
ENTRY ReadSeq (segment ; byteCount );
This procedure reads a physical block from the file, starting
in the logical file position defined by current position.
The block is read into the buffer specified by 'segment',
and the block consists of as many whole pages as the buffer
may contain. The parameter 'byteCount' returns the number
of bytes actually read, and current position is advanced
corresponding to the end of the block read.
When reaching the logical end-of-file a shorter block may
be read, and a correspondingly smaller value of byteCount
is returned. Reading beyond end-of-file but within the
allocation limit returns a 'byteCount' of zero.
An attempt to read beyond the allocation limit is rejected.
This situation can only occur after a seek operation.
The FAO must have read or readWrite reservation, otherwise
the call is rejected.
ENTRY WriteSeq (segment ; byteCount );
This procedure writes a physical block from the buffer specified
by 'segment', into the file from current position and on.
The size of the block is always as many whole pages as the
buffer may contain.
Current position is advanced corresponding to the end of the block
written. 'ByteCount' returns the number of bytes actually written.
If the new current position is beyond the logical end-of-file
position (but within the allocation limit) the end-of-file
position is advanced.
A file of contiguous type cannot be extended, i.e. if the
block would exceed the allocation limit, the call is rejected.
(When writing into a non-contiguous file the file is extended
if needed. P.t. not implemented).
The FAO must have write or readWrite reservation, otherwise
the call is rejected.
ENTRY ReadRandom (segment ; byteCount, pos, actualPos );
Reads a physical block into the buffer in the same manner as ReadSeq,
but the logical position within the file is determined by 'pos',
which is a relative byte address. In case 'pos' does not
correspond to a page boundary, the nearest lower page boundary
is used. 'ActualPos' returns the position actually used.
If 'pos' is beyond end-of-file but within the allocation limit
a 'byteCount' of zero is returned. If pos is beyond the allocation
limit the call is rejected.
Current position is updated corresponding to the end of the
block read.
ENTRY WriteRandom (segment ; byteCount, pos, actualPos );
Writes a physical block from the buffer into the file, to a position
determined by 'pos' in the same manner as ReadRandom. Otherwise
similar to WriteSeq.
ENTRY Seek (; baseMode, offset, pos );
Changes current position according to 'baseMode' and 'offset'. The
return parameter 'pos' is computed as 'baseMode' + 'offset', and
current position of the file will be this position, or the nearest
lower page boundary.
If the resulting position is < 0 the call is rejected. If the
resulting position is beyond the allocation limit, a later
read or write call may be rejected.
END Fao
END FileSystem
å
æ$L-å
æ$Eå
æ$F=FAMILY.UNIV.IDå
æ$F=FAMILY.KNEL.IDå
æ$L+å
æ$Eå
æ****** E X P O R T D E S C R I P T I O N *.****å
æ*************************************************å
æ$F=FAMILY.IOSYS.IDå
æ$L-å
æ$Eå
æ****** I M P O R T D E S C R I P T I O N ******å
æ*************************************************å
æ$F=FAMILY.ALLOC.IDå
æ$F=FAMILY.SCHED.IDå
æ$F=FAMILY.OBJDIR.IDå
æ$L+å
æ$Eå
æ***** E X T E R N A L P R O C E D U R E S *****å
æ*****************************************************å
PROCEDURE PrintText (text : fullId); FORWARD;
PROCEDURE PrintVar (text : fullId; UNIV v : blockPtr); FORWARD;
æ$Eå
æ***** C O N S T A N T S A N D T Y P E S *****å
æ*************************************************å
CONST
maxDisc = 5;
maxIdLength = 48;
noControl = 0;
orgNo = 34;
orgSys = 4003;
Reject = -1;
space = ' ';
versaPageSize = 256;
æVersaDos File Typeså
contiguous = 0;
sequential = 1;
isamKey = 2;
isamDup = 3;
æargument numberså
objectArg = 1;
entryA = 2;
faoArg = 4;
bufArg = 4;
fNameArg = -1;
dNameArg = -1;
baseArg = -1;
ioArg = -2;
posArg = -2;
offsetArg = -2;
createArg = -3;
seekPosArg = -3;
æaux causeså
volIdError = 11;
userOrCatalog = 12;
fileOrExt = 13;
nonContiguous = 14;
volNotIncluded = 15;
volAlreadyInclud = 16;
devTabLimit = 17;
driverObjectkind = 18;
deviceClass = 19;
devicePageSize = 20;
nameFormatIllegal= 21;
posNegative = 22;
illBaseMode = 23;
illIoRights = 24;
illCreateMode = 25;
filesOpen = 26;
noReadRight = 27;
noWriteRight = 28;
æ$Eå
æ***** VERSADOS DESCRIPTIONS *****å
æ*********************************å
TYPE
fullName = PACKED ARRAY Æ1..maxIdLengthÅ OF char;
name2 = PACKED ARRAY Æ1..2Å OF char;
name4 = PACKED ARRAY Æ1..4Å OF char;
name8 = PACKED ARRAY Æ1..8Å OF char;
sdbEntry = RECORD
userNo : word; æUser Noå
catName : name8; æCatalog Nameå
fPdp : long; æ^ first Pdbå
sDummy : word; æreservedå
END;
catStructure = (vid, sdb);
catV = RECORD
CASE catStructure OF
vid: æVolume Identification Blockå
(vidVol : name4; æVolume Idå
vidUser : word; æVolume Ownerå
vidSat : long; æ^ Sector Alloc Tableå
vidSal : word; ælength - - - å
vidSds : long æ^ first Sdbå
);
sdb: æSecond Directory Blockå
(sdbFpt : long; æ^ next Sdbå
sdbDummy : packed array Æ1..12Å of byte; æreservedå
sde : ARRAY Æ1..15Å OF sdbEntry
);
END; æcatVå
pdbEntry = RECORD
fileName : name8; æFile Nameå
ext : name2; æExtension Nameå
pDummy1 : word; æreservedå
dirFS : long; æPSN first sectorå
dirFE : long; æLSN last sector (alloc size)å
dirEOF : long; æ eos eos LSN end of file as byte# (used size)å
dirEOR : long; ælast recno (non-contiguous)å
dirWCD : byte; æWrite Access Codeå
dirRCD : byte; æRead Access Codeå
dirAtt : byte; æFile Typeå
dirLBZ : byte; ælast data block size (non-contig)å
dirRecSize : word; æRecord Size (non-contiguous)å
pDummy2 : byte; æreservedå
dirKey : byte; ænon-contiguous: key sizeå
dirFab : byte; æ - - : FAB sizeå
dirDat : byte; æ - - : Data Block sizeå
writeDate : word; ælast update dateå
assignDate : word; ælast assign dateå
pDummy3 : packed array Æ1..8Å of byte; æreservedå
END;
catP = RECORD æPrimary Directory Blockå
pdbFpt : long; æ^ next pdbå
pdbUser : word; æUser Noå
pdbCatName : name8; æCatalog Nameå
pDummyA : word; æreservedå
pde : ARRAY Æ1..20Å OF pdbEntry;
pDummyB : ARRAY Æ1..8Å OF byte;
END; æcatPå
æ$Eå
æ***** G L O B A L P R O C E D U R E S *****å
æ*********************************************å
FUNCTION MakeRes (main, family, argNo, auxCause : integer)
: resultType;
VAR
r : resultType;
BEGIN
r.main := main;
r.family := family;
r.argNo := argNo;
r.auxCause := auxCause;
r.orgNo := orgNo;
r.orgSys := orgSys;
MakeRes := r;
END; æ MakeRes å
PROCEDURE CheckOk (res : resultType);
BEGIN
æ IF res.main <> Ok THEN printVar ('**** Versa Check **** res=', res); å
IF res.main <> Ok THEN Exception (res);
END;
PROCEDURE sCheck (res : resultType);
BEGIN æresult can only be okå
IF res.main <> ok THEN printVar ('*** versafs sCheck ***, res= ', res);
END;
PROCEDURE rCheck (res : resultType);
BEGIN æobjReturn if result <> okå
IF res.main <> ok THEN printVar ('*** versafs rCheck ***, res= ', res);
IF res.main <> ok THEN ObjReturn (res);
END;
TYPE
stringeling = ^ÆÅ charstring;
FUNCTION Equal (s1, s2 : stringeling) : boolean;
VAR
i : integer;
b : boolean;
BEGIN
b := elements(s1) = elements(s2);
i := 1;
WHILE b AND (i<=elements(s1)) DO
BEGIN
b := s1ÆiÅ = s2ÆiÅ;
i := i+1;
END;
Equal := b;
END; æ Equal å
æ$Eå
PROCEDURE GetName (fileName : fullId;
partName : shortId;
sep : char;
VAR index : integer;
max : integer );
æ This procedure fetches a part of fileName, from the character after
index to the next occurrence of the separator sep (or end of fileName).
At return index points to the separator last read.
å
FUNCTION nextChar (VAR i : integer) : char;
VAR c : char; x : integer;
BEGIN
i := i+1;
c := fileNameÆiÅ;
IF c = CHR(0) THEN
BEGIN
c := sep;
i := i-1;
END
ELSE
IF (c>='a') AND (c<='z') THEN
c := CHR (ORD(c) - 32);
nextChar := c;
END;
VAR
i, j, k : integer;
c : char;
BEGIN
j := 0;
i := index;
k := Elements (fileName);
IF i>=k THEN æfileName exhaustedå
c := sep
ELSE
REPEAT æskip leading spaces and/or slash å
c := nextChar(i);
UNTIL (c<>'/') AND (c<>space) OR (i>k);
WHILE (c<>sep) AND (j<max) AND (i<=k) DO
BEGIN
j := j+1;
partNameÆjÅ := c;
IF i<k THEN
c := nextChar(i)
ELSE
c := sep; æsimulate separator at end of nameå
END; æ while å
IF c<>sep THEN æskip possible ending spaceså
WHILE c=space DO
IF i<k THEN c := nextChar(i) ELSE c := sep;
IF ( (j=0) AND (index=0) ) OR (c<>sep) THEN
Exception (MakeRes (Reject * FileNotFound, IoFamily,
fNameArg, nameFormatIllegal));
æfill partName with ending spaceså
IF j<max THEN
FOR j := j+1 TO max DO
partNameÆjÅ := space;
index := i;
END; æ GetName å
æ$Eå
æ****** F A O L O C A L P O I N T E R S ******å
æ*************************************************å
TYPE
refFao = ^^faoLocals;
pGateType = ^^Gate;
faoLocals = RECORD
code : ^^;
faoData : ^^vFaoData;
faoGate : ^^Gate;
faoChain : refFao;
vsRef : ^^versaLocals;
daoRef : faoRefType;
END;
vFaoData = RECORD
fileAddr, æabs. byteAddr of fileStartå
curPos, ærel. - - current positionå
eofPos, ærel. - - eof positionå
fileSize, ærel. - - allocation limitå
pdbPos, æabs. - - current PDBå
firstFab, æsector noå
curFab, æ - å
lastFab : integer; æ - å
rwRights : ioType;
fileType : byte;
readOnly : boolean;
terminated : boolean;
pageSize : integer;
localId : integer;
pdbEntry : 1..20;
END;
æ$Eå
æ****** I O S Y S L O C A L P O I N T E R S ******å
æ*****************************************************å
TYPE
versLocRef = ^^ versaLocals;
versaLocals = RECORD
code : ^^;
vsGate : ^^Gate;
dao : ARRAY Æ1..maxDiscÅ OF faoRefType;
faoMan : ARRAY Æ1..maxDiscÅ OF refFao;
vsData : ^^versaData;
objDirRef : ^^ObjDir;
allocRef : ^^Allocate;
schedRef : ^^Scheduler;
END;
discData = RECORD
deviceName : fullName;
volName : name4;
pageSize : word;
readOnly : boolean;
deviceState : (free, included, exNotOk);
END;
versaData = RECORD
lastLocalId : integer;
devTable : ARRAY Æ1..maxDiscÅ OF discData;
END;
æ$Eå
æ****** I M P L E M E N T V E R S A F A O ******å
æ***************************************************å
PROGRAM VersaFaoImplement OBJECT Fao WITH FaoLocals;
PROCEDURE ReadBlock (VAR buf : bufRef;
VAR fd : vFaoData;
VAR byteCount : integer;
VAR actualPos : integer;
argNo : integer æin case of errorå );
VAR
bs, eof, pos : integer;
BEGIN
WITH b = buf^^ DO
BEGIN
æ#b# printVar ('readBlock: fd= ', fd); #e#å
æ Check read reservation å
IF (fd.rwRights = NoRights) OR
(fd.rwRights = WriteRights) THEN
Exception (MakeRes (Reject * EntryIllegal, Universal,
0, noReadRight ));
æ Check current position against eof position å
IF fd.eofPos = 0
THEN eof := fd.fileSize æallocation limitå
ELSE eof := fd.eofPos; æeofå
æ#b# printVar ('eof=',eof); #e#å
IF fd.curPos > fd.fileSize THEN
Exception (makeRes (Reject * PosOutsideRange, IoFamily,
argNo, ReadRights));
IF fd.curPos >= eof THEN
byteCount := 0 æfile exhaustedå
ELSE
BEGIN
pos:=fd.curPos;
bs := elements(b);
æ#b# printVar ('elements(b) = ', bs ); #e#å
IF pos + bs > eof THEN
bs := eof - fd.curPos; ænot data enough for full bufferå
æ Read data block and update current position å
pos := fd.fileAddr + pos;
æ#b#
printVar ('absPos=',pos);
printVar ('bs = ', bs );
#e#å
CheckOk( daoRef.ReadRandom (VAR IN OUT buf^^Æ1..bsÅ ;
OUT byteCount, IN pos, OUT pos));
æ#b# printVar ('pos after dao.Read=',pos); #e#å
actualPos := pos - fd.fileAddr;
fd.curPos := actualPos + byteCount;
æ#b# printVar ('new curPos=', fd.curPos); #e#å
END; ænot eofå
END; æwithå
END; æReadBlockå
æ$Eå
PROCEDURE WriteBlock (VAR buf : bufRef;
VAR fd : vFaoData;
VAR byteCount : integer;
VAR actualPos : integer;
argNo : integer æin case of eof errorå);
VAR
bs, eof, pos : integer;
BEGIN
WITH b = buf^^ DO
BEGIN
æ Check write reservation å
æ#b# printVar ('writeBlock: fd= ',fd); #e#å
IF (fd.rwRights < WriteRights) OR fd.readOnly THEN
Exception (MakeRes (Reject * EntryIllegal, Universal,
0, noWriteRight));
pos:= fd.curPos;
æ Check position against eof position å
IF fd.eofPos= 0
THEN eof := fd.fileSize æallocation limitå
ELSE eof := fd.eofPos; æeofå
bs := elements (b);
IF pos + bs > fd.fileSize THEN
Exception (MakeRes (Reject * PosOutsideRange, IoFamily,
argNo, WriteRights));
æ Write data block and update current position å
pos := fd.fileAddr + pos;
æ#b# printVar ('absPos = ',pos); #e#å
CheckOk( daoRef.WriteRandom (buf ; OUT byteCount, IN pos, OUT pos));
actualPos := pos - fd.fileAddr;
fd.curPos := actualPos + byteCount;
æ Update eof position å
IF fd.curPos > eof THEN
fd.eofPos := fd.curPos;
END;
END; æ writeBlock å
æ$Eå
æ***** ReadSeq / WriteSeq *****å
æ**********************************å
ENTRY ReadSeq
æ segment ; OUT byteCount å
WITH RECORD
t : ^^;
END;
VAR
actualPos : integer;
res : resultType;
BEGIN
æ#b# printText ('-----vs.ReadSeq-----'); #e#å
sCheck ( faoGate.Lock );
IN
WITH fd = faoData^^ DO
ReadBlock (segment, fd, byteCount, actualPos, bufArg);
res := MakeRes(Ok, Ok, Ok, Ok);
DO
res := GetException;
sCheck ( faoGate.Open );
æ#b# printVar ('--end vs.ReadSeq-- res=', res); #e#å
ObjReturn (res);
END; æReadSeqå
ENTRY WriteSeq
æ segment ; OUT byteCount å
WITH RECORD
t : ^^;
END;
VAR
actualPos : integer;
res : resultType;
BEGIN
æ#b# printText ('-----vs.WriteSeq-----'); #e#å
sCheck ( faoGate.Lock );
IN
WITH fd = faoData^^ DO
WriteBlock (segment, fd, byteCount, actualPos, bufArg);
res := MakeRes (Ok, Ok, Ok, Ok);
DO
res := GetException;
sCheck ( faoGate.Open );
æ#b# printVar ('--end vs.WriteSeq-- res=', res); #e#å
ObjReturn (res);
END; æWriteSeqå
æ$Eå
æ***** ReadRandom *****å
æ**************************å
ENTRY ReadRandom
æ segment ; OUT byteCount, IN pos, OUT actualPos å
WITH RECORD
t : ^^;
END;
VAR
res : resultType;
BEGIN
æ#b# printText ('-----vs.ReadRandom-----'); #e#å
sCheck ( faoGate.Lock );
IN
WITH fd = faoData^^ DO
BEGIN
æ Check position and assign current position å
IF (pos < 0) OR
(pos > fd.fileSize) THEN
Exception (makeRes (Reject * PosOutsideRange, IoFamily,
posArg, ReadRights ));
fd.curPos:=pos;
æ Read data block å
ReadBlock (segment, fd, byteCount, actualPos, bufArg);
res := MakeRes (Ok, Ok, Ok, Ok);
END; æwith fdå
DO
res := GetException;
sCheck (faoGate.Open );
æ#b# printVar ('--end vs.ReadRandom-- res=',res); #e#å
ObjReturn (res);
END; æReadRandomå
æ$Eå
ENTRY WriteRandom
æ segment ; OUT byteCount, IN pos, OUT actualPos å
WITH RECORD
t : ^^;
END;
VAR
res : resultType;
BEGIN
æ#b# printText ('-----vs.WriteRandom-----'); #e#å
sCheck ( faoGate.Lock );
IN
WITH fd = faoData^^ DO
BEGIN
æ#b# printVar ('pos= ',pos); #e#å
æ Check position and assign current position å
IF (Pos < 0) OR
(Pos > fd.fileSize) THEN
Exception (MakeRes (Reject * PosOutsideRange, IoFamily,
posArg, WriteRights ));
fd.curPos := Pos;
æ Write data block å
WriteBlock (segment, fd, byteCount, actualPos, posArg);
res := MakeRes (Ok, Ok, Ok, Ok);
END; æwithå
DO
res := GetException;
sCheck ( faoGate.Open );
æ#b# printVar ('--end vs.WriteRandom-- res=', res); #e#å
ObjReturn (res);
END; æWriteRandomå
æ$Eå
ENTRY Seek
æ ; IN baseMode, IN offset, OUT pos å
WITH RECORD t : ^^; END;
VAR
res : resultType;
tPos, eof : integer;
BEGIN
æ#b# printText ('---------vs.seek-----------'); #e#å
sCheck ( faoGate.Lock );
IN
WITH fd = faoData^^ DO
BEGIN
IF fd.fileType <> contiguous THEN
Exception (makeRes (Reject * VolumeFormatError, IoFamily,
entryA, nonContiguous ));
æseek cannot be implemented without disc access for a
non-contiguous fileå
CASE baseMode OF
FromStart:
tPos := offset;
FromCurrentPos:
tPos := fd.curPos + offset;
FromEnd:
BEGIN
eof := fd.eofPos;
IF eof = 0 THEN eof := fd.fileSize ELSE
IF eof =-1 THEN eof := 0;
tPos := eof + offset;
END; æfromEndå
OTHERWISE
Exception (makeRes (Reject * DataValueIllegal, IoFamily,
baseArg, illBaseMode));
END; æcaseå
æ#b# printVar ('pos= ',tPos); #e#å
IF tPos < 0 THEN
Exception (makeRes (Reject * PosOutsideRange, IoFamily,
offsetArg, posNegative));
fd.curPos := tPos;
pos := tPos;
END; æwithå
res := makeRes (Ok, Ok, Ok, Ok);
DO
res := GetException;
sCheck ( faoGate.Open);
æ#b# printVar ('---------end vs.seek--------, res= ',res); #e#å
ObjReturn (res);
END;
æ$Eå
ENTRY SetMode
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
ENTRY GetFileInf
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
ENTRY SetRights
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
ENTRY CheckRights
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
ENTRY MoveRights
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
ENTRY NewLink
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
ENTRY AllocSize
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
æ$Eå
ENTRY DataSize
æ ; IN dataBytes å
WITH RECORD t : ^^; END;
VAR
res : resultType;
BEGIN
æ#b# printText ('-----vs.DataSize----- '); #e#å
sCheck ( faoGate.Lock);
IN
WITH fd = faoData^^ DO
BEGIN
æ Check write reservation å
IF (fd.rwRights < WriteRights) OR fd.readOnly THEN
Exception (MakeRes (Reject * EntryIllegal, Universal,
0, noWriteRight));
IF dataBytes = 0 THEN fd.eofPos := -1
ELSE fd.eofPos := dataBytes;
æ#b# printVar ('fd.eofPos = ',fd.eofPos); #e#å
res := okResult;
END; æwithå
DO
res := GetException;
sCheck ( faoGate.Open);
ObjReturn (res);
END;
ENTRY WaitBreak
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
ENTRY WaitReady
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
end;
OTHERWISE FaoOther
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
END; æotherwisweå
END; æVersaFaoImplementå
æ$Eå
æ****** I M P L E M E N T V E R S A F I L E S Y S T E M ******å
æ*****************************************************************å
PROGRAM VersFilImplement OBJECT IoSys WITH versaLocals;
PRIVATE Close
(IN fao : ownSet;
IN faoEnv : refFao);
PROCEDURE InitFilSys;
VAR
d, i : integer;
BEGIN
printText (procId);
CheckOk( schedRef.NewGate (OUT vsGate));
CheckOk( vsGate.Lock);
æ Initialize versaData å
WITH vsData^^ DO
BEGIN
lastLocalId := 0;
FOR d := 1 TO maxDisc DO
WITH devTableÆdÅ DO
BEGIN
deviceState := free;
FOR i := 1 TO maxIdLength DO
deviceNameÆiÅ := space;
FOR i := 1 TO 4 DO
volNameÆiÅ := space;
END; æ for d å
END; æ with å
CheckOk ( MakeReentrant (Void));
END; æ InitFilSys å
æ$Eå
æ***** Assign *****å
æ**********************å
ENTRY Assign
æOUT ownedFao; IN fileName, IN ioRights, optional IN createMode, volumeå
WITH RECORD
t : ^^;
faoEnv : ^^ faoLocals;
tmpFaoMan : ^^;
nextFao : refFao;
saveFaoPtr : refFao;
END;
VAR
nullSize, voidSize, size : sizeType;
dummyRes, res : resultType;
found : boolean;
cmPtr : ^createType;
createMode : createType;
auxCause, charNo, count, daoIndex, e, i, j, locId,
nextPdb, nextSdb, pageSize, pos, savedAddr, userNo : integer;
extension : name2;
vol, user : name4;
catalog, fileN : name8;
buf : catV;
pbuf : catP;
BEGIN
æ*b* printText ('-----vs.Assign-----'); *e*å
IN
CheckOk( vsGate.Lock );
DO
BEGIN
æ not ok means file system not initialized å
InitFilSys;
END;
res := vsGate.Open;
æ Check IoRights parameter å
IF (ioRights < NoRights) OR (ioRights > ReadWrite) THEN
Exception (MakeRes (Reject * DataValueIllegal, Universal,
ioArg, illIoRights));
æ Take optional createMode parameter å
IF NextValArg (cmPtr)
THEN createMode := cmPtr^
ELSE createMode := oldFile;
æ*b* printVar ('createMode=', createMode); *e*å
IF (createMode < NewOrOld) OR (createMode > NewFile) THEN
Exception (makeRes (Reject * DataValueIllegal, Universal,
createArg, illCreateMode));
æ Allocate Fao Object å
sCheck ( ClearSize (size));
sCheck ( AddGen (size, refs(faoLocals)));
sCheck ( AddEmbSeg (size, bytes(vFaoData)));
rCheck ( allocRef.NewObj (OUT ownedFao; IN size, OUT i));
æ Make Fao a general object with temporary manager å
nullSize.user := 0; nullSize.kernel := 0;
voidSize.user := -1; voidSize.kernel := -1;
rCheck ( DeclGen (ownedFao, tmpFaoMan, faoEnv, refs(faoLocals), Close,
nullSize, voidSize, refs(VersaFaoImplement),
bytes(VersaFaoImplement), noControl,
addr(VersaFaoImplement), nullSize, true));
æ Create Fao data segment å
rCheck ( NewSeg (faoEnv^^.faoData, bytes(vFaoData)));
æ Create fao gate å
rCheck ( schedRef.NewGate (OUT faoEnv^^.faoGate));
æ enter critical region before search devTab å
sCheck ( vsGate.Lock );
IN
WITH vd = vsData^^ DO
BEGIN
æ Find disc volume name in device table å
charNo := 0;
GetName (fileName, vol, ':', charNo, 4);
æ*b* printVar ('fileName=',fileName); *e*å
æ*b* printVar ('vol =',vol); *e*å
daoIndex := 1;
found := false;
REPEAT
IF Equal (vd.devTableÆdaoIndexÅ.volName, vol) THEN
BEGIN
found := true;
pageSize := vd.devTableÆdaoIndexÅ.pageSize;
END
ELSE
daoIndex := daoIndex + 1;
UNTIL found OR
(daoIndex > maxDisc);
æ*b* printVar ('daoIndex=',daoIndex); *e*å
IF NOT found THEN
Exception (makeRes (Reject * FileNotFound, IoFamily,
fNameArg, volNotIncluded));
æwhen volName not found in deviceTable, an automatic search for volName
on all included devices could be made. If found on a device this device
should be implicit excluded and included
å
æ Now the proper Dao is found (daoIndex), search fileName
in disc directory å
æFirst split fileNameå
GetName (fileName, user, '.', charNo, 4);
æ*b* printVar ('user =',user); *e*å
GetName (fileName, catalog, '.', charNo, 8);
æ*b* printVar ('catalog=',catalog); *e*å
GetName (fileName, fileN, '.', charNo, 8);
æ*b* printVar ('fileN =',fileN); *e*å
GetName (fileName, extension,'(', charNo, 2);
æ*b* printVar ('ext =',extension); *e*å
æ Convert user into binary userNo å
userNo := 0;
FOR i := 1 TO 4 DO
BEGIN
j := ORD(userÆiÅ) - ORD('0');
IF (j>=0) AND (j<=9) THEN
userNo := userNo*10 + j
ELSE
IF userÆiÅ <> space THEN
Exception (MakeRes (Reject * FileNotFound, IoFamily,
fNameArg, nameFormatIllegal));
END;
æ*b* printVar ('userN0 =',userNo); *e*å
æ Read Volume Identification Block, VID å
pos := 0;
CheckOk( daoÆdaoIndexÅ.ReadRandom (VAR IN OUT buf;
OUT count, IN pos, OUT pos));
æ Check Volume Name å
IF NOT Equal (vol, buf.vidVol) THEN
Exception (makeRes (Reject * VolumeFormatError, IoFamily,
fNameArg, volIdError ));
æwhen volName on device not ok, this device should be implicit excluded
and included again. All devices should be searched for the wanted volName,
and if found on some other device, this should also be excluded and
included again.
å
æ Search Secondary Directory Block, SDB å
æ*b* printText ('search Secondary Directory Block'); *e*å
auxCause := userOrCatalog;
found := false;
nextSdb := buf.vidSds;
REPEAT
æ*b* printVar ('nextSdb=',nextSdb); *e*å
pos := nextSdb * pageSize;
CheckOk( daoÆdaoIndexÅ.ReadRandom (VAR IN OUT buf;
OUT count, IN pos, OUT pos));
nextSdb := buf.sdbFpt;
e := 1;
REPEAT
IF (buf.sdeÆeÅ.userNo = userNo) AND
Equal (buf.sdeÆeÅ.catName, catalog)
THEN found := true
ELSE e := e + 1;
UNTIL found OR (e>15);
UNTIL found OR (nextSdb=0);
æ*b* printVar ('sdb-e =',e); *e*å
IF found THEN
BEGIN
æ Search Primary Directory Block, PDB å
æ*b* printText ('search Primary Directory Block'); *e*å
auxCause := fileOrExt;
found := false;
nextPdb := buf.sdeÆeÅ.fPdp;
REPEAT
æ*b* printVar ('nextPdb=',nextPdb); *e*å
pos := nextPdb * pageSize;
CheckOk( daoÆdaoIndexÅ.ReadRandom (VAR IN OUT pBuf;
OUT count, IN pos, OUT pos));
nextPdb := pbuf.pdbFpt;
e := 1;
REPEAT
IF Equal (pbuf.pdeÆeÅ.fileName, fileN) AND
Equal (pbuf.pdeÆeÅ.ext, extension)
THEN found := true
ELSE e := e + 1;
UNTIL found OR (e > 20);
UNTIL found OR (nextPdb = 0);
END; æsearch PDBå
æ*b* printVar ('pdb-e =',e); *e*å
IF NOT found THEN
Exception (MakeRes (Reject * FileNotFound, IoFamily,
fNameArg, auxCause));
æ FileName has been found in directory, check file type
(must be contiguous), and initialize faoData å
WITH fd = faoEnv^^.faoData^^, pbuf.pdeÆeÅ DO
BEGIN
IF dirAtt = contiguous THEN
BEGIN
savedAddr := dirFS * pageSize;
fd.fileAddr := savedAddr;
fd.curPos := 0;
IF createMode = newFile
THEN fd.eofPos := -1
ELSE fd.eofPos := dirEOF;
fd.fileSize := (dirFE+1) * pageSize;
fd.pdbPos := pos;
fd.pdbEntry := e;
fd.firstFab := 0;
fd.curFab := 0;
fd.lastFab := 0; ænot used by contig.fileå
fd.fileType := dirAtt;
fd.rwRights := ioRights;
fd.readOnly := vd.devTableÆdaoIndexÅ.readOnly;
fd.terminated := false;
fd.pageSize := pageSize;
æ*b* printVar ('file description = ',fd); *e*å
END æ contiguous å
ELSE
Exception (MakeRes (reject * VolumeFormatError, ioFamily,
fNameArg, nonContiguous));
ænon-contiguous files not implementedå
END; æwith fdå
æ Search all other faos connected to same disc. If same file
then check reservation å
æ*b* printVar ('search other faos, own file addr=', savedAddr); *e*å
found := false;
res := FirstInSet (faoManÆdaoIndexÅ, nextFao);
IF res.main = ok THEN
BEGIN
REPEAT
WITH fd = nextFao^^.faoData^^ DO
BEGIN
æ*b* printVar ('fd.fileAddr=',fd.fileAddr); *e*å
IF fd.fileAddr = savedAddr THEN
BEGIN æ same file å
IF (ioRights > readRights) OR
(fd.rwRights > readRights) THEN
Exception (MakeRes (Reject * RightsOccupied, IoFamily,
fNameArg, ioRights));
IF NOT found THEN
BEGIN æ first same, save fao pointer for later connectå
sCheck ( Copy (nextFao^^.faoChain, faoEnv^^.faoChain));
sCheck ( Copy (nextFao, saveFaoPtr));
found := true;
locId := fd.localId;
END; æfirst foundå
END; æsame fileå
END; æwith fdå
res := NextInSet (faoManÆdaoIndexÅ, nextFao);
æ*b* printVar ('NextInSet, res= ',res); *e*å
UNTIL res.main <> Ok;
END; æfaoMan set not emptyå
æ Reservation ok, move new fao manager and initialize fao pointerså
sCheck ( MoveMan (tmpFaoMan, faoManÆdaoIndexÅ));
sCheck ( Copy (code, faoEnv^^.code));
sCheck ( Copy (daoÆdaoIndexÅ, faoEnv^^.daoRef));
sCheck ( MakeReentrant (faoEnv));
æ*b* printText ('after copy fao pointers '); *e*å
æ Insert this fao in file chain, and assign localId å
WITH fd = faoEnv^^.faoData^^ DO
BEGIN
IF found THEN
BEGIN
fd.localId := locId;
CheckOk( Copy (faoEnv, saveFaoPtr^^.faoChain));
END æfoundå
ELSE
BEGIN æfile not used before,
create new localId and new fileChain å
vd.lastLocalId := vd.lastLocalId + 1;
fd.localId := vd.lastLocalId;
CheckOk( Copy (faoEnv, faoEnv^^.faoChain));
END; ænot foundå
æ*b* printVar ('localId=',fd.localId); *e*å
END; æ with fd å
res := MakeRes (Ok, Ok, Ok, Ok);
END; æwith vdå
DO
BEGIN
æsome error during assign, undo everythingå
IF daoIndex > 0 THEN
BEGIN
dummyRes := DelEnv (ownedFao, faoManÆdaoIndexÅ);
dummyRes := Dealloc (ownedFao, faoManÆdaoIndexÅ);
END;
res := GetException;
END;
æ Leave critical region å
dummyRes := vsGate.Open;
æ*b* printVar ('--end vs.Assign-- res=',res); *e*å
ObjReturn (res);
END; æAssignå
æ$Eå
ENTRY InitFileScan æp.t. not implementedå
æOUT scanObj; IN partialFileNameå
WITH RECORD t : ^^; END;
BEGIN ObjReturn (MakeRes (Reject*EntryIllegal, Universal, entryA, 0)); END;
ENTRY RenameFile æp.t. not implementedå
æ ; IN fileName, IN newFileNameå
WITH RECORD t : ^^; END;
BEGIN ObjReturn (MakeRes (Reject*EntryIllegal, Universal, entryA, 0)); END;
ENTRY CreateLink æp.t. not implementedå
æ ; IN fileName, IN newFileNameå
WITH RECORD t : ^^; END;
BEGIN ObjReturn (MakeRes (Reject*EntryIllegal, Universal, entryA, 0)); END;
ENTRY DeleteLink æp.t. not impelmentedå
æ ; IN fileNameå
WITH RECORD T : ^^; END;
BEGIN ObjReturn (MakeRes (Reject*EntryIllegal, Universal, entryA, 0)); END;
ENTRY InitIpcSys ænot VersaFså
WITH RECORD t : ^^; END;
BEGIN ObjReturn (MakeRes (Reject*EntryIllegal, Universal, entryA, 0)); END;
ENTRY CreateFile ænot VersaFså
WITH RECORD t : ^^; END;
BEGIN ObjReturn (MakeRes (Reject*EntryIllegal, Universal, entryA, 0)); END;
ENTRY DeleteFile ænot VersaFså
WITH RECORD T : ^^; END;
BEGIN ObjReturn (MakeRes (Reject*EntryIllegal, Universal, entryA, 0)); END;
æ$Eå
æ***** INCLUDE *****å
æ***********************å
ENTRY Include
æ ; IN devName Æ, reaOnlyÅ å
WITH RECORD
t : ^^;
discDriver : ioSysRefType;
END;
VAR
i, k, minBufSize,
daoIndex, devClass, kind, localId, pos, size, used : integer;
accessMode : ioType;
alreadyOpen : boolean;
name, freeEntry : fullName;
dummyRes, res : resultType;
roPtr : ^integer;
readOnly : integer;
buf : catV;
BEGIN
æ*b* printText ('-----vs.Include-----'); *e*å
IN
CheckOk (vsGate.Lock);
DO ænot ok means file system not initializedå
InitFilSys;
WITH vd = VsData^^ DO
BEGIN
IN
æ Take optional readOnly parameter å
IF NextValArg (roPtr)
THEN readOnly := roPtr^
ELSE readOnly := 0;
æ*b* printVar ('readOnly=',readOnly); *e*å
æ Initialization å
k := elements(devName);
FOR i := 1 TO maxIdLength DO freeEntryÆiÅ := space;
FOR i := 1 TO k DO nameÆiÅ := devNameÆiÅ;
FOR i := k+1 TO maxIdLength DO nameÆiÅ := space;
alreadyOpen := false;
æ Search deviceName in device table å
daoIndex := 0;
FOR i := 1 TO maxDisc DO
BEGIN
IF Equal (vd.devTableÆiÅ.deviceName, name) THEN
BEGIN
CASE vd.devTableÆiÅ.deviceState OF
free:
daoIndex := i;
included:
Exception (MakeRes (Reject*FileNameExists, IoFamily,
dNameArg, volAlreadyIncluded));
exNotOk:
BEGIN æExclude has been called, but Dealloc was not succesful,
so the Dao must be de-allocated before re-use å
daoIndex := i;
alreadyOpen := true;
END;
END; æcaseå
END; æequalå
IF daoIndex = 0 THEN
IF Equal (vd.devTableÆiÅ.deviceName, freeEntry) THEN
BEGIN
daoIndex := i;
vd.devTableÆiÅ.deviceName := name;
END;
END; æfor iå
IF (daoIndex = 0) OR alreadyOpen THEN
BEGIN ædevName not found, and no free entries. If any "excludeNotOk"
entry this can be used, otherwise reject å
FOR i := 1 TO maxDisc DO
BEGIN
IF vd.devTableÆiÅ.deviceState = exNotOk THEN
BEGIN
daoIndex := i;
dummyRes := Dealloc (daoÆdaoIndexÅ, daoÆdaoIndexÅ);
vd.devTableÆiÅ.deviceState := free;
vd.devTableÆiÅ.deviceName := name;
END;
END; æfor iå
IF daoIndex = 0 THEN
Exception (MakeRes (Reject*NoResources, Universal,
dNameArg, devTabLimit)); æno free entryå
END; ædaoIndex=0å
DO
BEGIN
dummyRes := vsGate.Open;
ObjReturn (GetException);
END;
æ Now an entry in device table has been found, get driver ref å
IN
æ*b* printVar ('daoIndex = ',daoIndex); *e*å
CheckOk( objDirRef.GetRef (OUT discDriver ;
IN devName, OUT used, OUT kind));
IF (kind <> GeneralObject) AND
(kind <> AccessObject) THEN
Exception (MakeRes (Reject*GiveUp, Universal,
dNameArg, driverObjectKind));
æ Assign disc driver, i.e. create DiscAccessObject (DAO) å
IF readOnly<>0 THEN accessMode := ReadRights
ELSE accessMode := ReadWrite;
æ*b* printVar ('devName= ',devName); *e*å
æ*b* printVar ('used= ',used); *e*å
CheckOk( discDriver.Assign (OUT daoÆdaoIndexÅ ;
IN devNameÆused+1..kÅ, IN accessMode));
IN
æ Check Device Information å
CheckOk( daoÆdaoIndexÅ.GetFileInf (OUT discDriver ;
OUT localId, OUT name, OUT devClass,
OUT i æbytesAllocatedå, OUT minBufSize,
OUT i æcylSizeå ));
DO æ GetFileInf in driver not implemented, assign ok-values å
BEGIN
minBufSize := VersaPageSize;
devClass := Disc;
END;
IF devClass <> Disc THEN
Exception (MakeRes (Reject*GiveUp, Universal,
dNameArg, deviceClass));
IF minBufSize > VersaPageSize THEN
Exception (MakeRes (Reject*GiveUp, Universal,
dNameArg, devicePageSize));
æ Read Sector 0 å
pos := 0;
CheckOk( daoÆdaoIndexÅ.ReadRandom (VAR IN OUT buf ;
OUT size, IN pos, OUT pos));
æ Assign Device Table entry å
WITH ve = vd.devTableÆdaoIndexÅ DO
BEGIN
ve.volName := buf.vidVol; ævolume Idå
ve.pageSize := minBufSize;
if readOnly=0 then ve.readOnly := false
else ve.readOnly := true;
ve.deviceState := included;
æ*b* printVar ('device table entry',ve); *e*å
END;
res := MakeRes (Ok, Ok, Ok, Ok);
DO
BEGIN
dummyRes := Dealloc (daoÆdaoIndexÅ, daoÆdaoIndexÅ);
æcheck result of Deallocå
dummyRes := Copy (void, daoÆdaoIndexÅ);
IF dummyRes.main = Ok
THEN vd.devTableÆdaoIndexÅ.deviceState := free
ELSE vd.devTableÆdaoIndexÅ.deviceState := exNotOk;
res := GetException;
END;
END; æwith vdå
dummyRes := vsGate.Open;
æ*b* printVar ('--end vs.Include-- res=', res); *e*å
ObjReturn (res);
END; æIncludeå
æ$Eå
æ***** TerminateFao *****å
æ****************************å
PROCEDURE TerminateFao (VAR faoEnv : refFao ;
VAR fd : vFaoData;
var daoTmp : faoRefType);
VAR
byteCount, e, pos : integer;
pbuf : catP;
BEGIN
æ*b* printText ('-----TerminateFao-----'); *e*å
æ abort will remove all simple pointers of the envelope,
this may be changed in a later version of the kernel.
until then take a copy of the daoRef and faoGate before abort. å
sCheck ( copy (faoEnv^^.daoRef,daoTmp));
sCheck ( faoEnv^^.faoGate.Lock );
æ prevent other users from accessing the fao during terminate å
sCheck ( Abort (faoEnv));
æ*b* printtext ('=====Abort (faoEnv)==='); *e*å
æ update disc directory: eof position and date å
IF (fd.rwRights > ReadRights) AND
(NOT fd.readOnly) AND
(fd.eofPos <> 0) THEN
BEGIN
pos := fd.pdbPos;
CheckOk( daoTmp.ReadRandom (VAR IN OUT pbuf;
OUT byteCount, IN pos, OUT pos));
æ*b* printtext ('=====ReadpdbEntry====='); *e*å
e := fd.pdbEntry;
WITH pbuf.pdeÆeÅ DO
BEGIN
dirEOF := fd.eofPos;
writeDate := 0; ædate p.t. not implementedå
æ*b* printVar ('update dirEOF= ',dirEOF); *e*å
END; æwith pbufå
CheckOk( daoTmp.WriteRandom (VAR IN OUT pbuf;
OUT byteCount, IN pos, OUT pos));
æ*b* printtext('=====WritepdbEntry====='); *e*å
END; æ update directory å
æ remove faoGate å
sCheck ( faoEnv^^.faoGate.Open );
sCheck ( Dealloc (faoEnv^^.faoGate, faoEnv^^.faoGate));
æ*b* printText ('--end TerminateFao--'); *e*å
END; æ terminateFao å
æ$Eå
æ***** EXCLUDE *****å
æ***********************å
ENTRY Exclude
æ ; IN deviceName Æ, abortAllowedÅ å
WITH RECORD
t : ^^;
tempMan: ^^;
tempEnv: ^^;
faoEnv : refFao;
daoTmp : faoRefType;
END;
VAR
daoIndex, i, k : integer;
res, dummyRes : resultType;
name : fullName;
aaPtr : ^integer;
abortAllowed : integer;
BEGIN
æ*b* printText ('-----vs.Exclude----- '); *e*å
IN
CheckOk (vsGate.Lock);
DO ænot ok means file system not initializedå
InitFilSys;
WITH vd = vsData^^ DO
BEGIN
IN
æTake optional abortAllowed parameterå
IF NextValArg (aaPtr)
THEN abortAllowed := aaPtr^
ELSE abortAllowed := 0;
æ*b* printVar ('abortAllowed= ',abortAllowed); *e*å
k := elements(devName);
FOR i := 1 TO k DO nameÆiÅ := devNameÆiÅ;
FOR i := k+1 TO maxIdLength DO nameÆiÅ := space;
æSearch devName in device tableå
daoIndex := 0;
FOR i := 1 TO maxDisc DO
BEGIN
IF Equal (vd.devTableÆiÅ.deviceName, name) AND
(vd.devTableÆiÅ.deviceState > free) THEN
daoIndex := i;
END; æforå
æ*b* printVar ('daoIndex= ',daoIndex); *e*å
IF daoIndex=0 THEN
Exception (MakeRes (Reject*FileNotFound, IoFamily,
entryA, volNotIncluded));
æNow the device name has been found in device table,
check if any open fao å
res := FirstInSet (faoManÆdaoIndexÅ, faoEnv);
IF res.Main = Ok THEN
BEGIN
IF abortAllowed = 0 THEN
Exception (MAkeRes (Reject*RightsOccupied, IoFamily,
entryA, filesOpen));
REPEAT
WITH fd = faoEnv^^.faoData^^ DO
BEGIN
IF fd.terminated THEN ænothingå
ELSE
BEGIN
terminateFao (faoEnv , fd, daoTmp);
fd.terminated := true;
END;
END; æwithå
sCheck ( Copy (faoEnv, tempEnv));
res := NextInSet (faoManÆdaoIndexÅ, faoEnv);
sCheck ( MoveMan (tempEnv, tempMan)); æremove fao from ManSetå
UNTIL res.main <> ok;
END;
æRemove manager pointerå
res := MoveMan (faoManÆdaoIndexÅ, tempMan);
æDeallocate the disc driverå
res := Dealloc (daoÆdaoIndexÅ, daoÆdaoIndexÅ);
WITH vd.devTableÆdaoIndexÅ DO
BEGIN
IF res.main = Ok THEN
BEGIN
deviceState := free;
FOR i:=1 TO maxIdLength DO deviceNameÆiÅ := space;
END
ELSE
deviceState := exNotOk;
END;
res := MakeRes (Ok, Ok, Ok, Ok);
DO
res := GetException;
END; æwithå
æ*b* printVar ('---end exclude ---, res= ',res); *e*å
dummyRes := vsGate.Open;
ObjReturn (res);
END; æExcludeå
æ$Eå
æ***** CLOSE *****å
æ*********************å
PRIVATE Close
æ fao, faoEnv å
WITH RECORD
t : ^^;
nextFao : refFao;
daoTmp : faoRefType;
END;
VAR
res : resultType;
BEGIN
æ*b* printText ('-----vs.Close-----'); *e*å
IN
CheckOk (vsGate.Lock);
WITH fd = faoEnv^^.faoData^^ DO
BEGIN
IF fd.terminated THEN ænothingå
ELSE
BEGIN
terminateFao (faoEnv , fd, daoTmp);
fd.terminated := true;
æ OBS! For the time being RefEqual is dummy (always true),
so the fao file chain is not maintained. But the chain will
be used only when a file reservation is to be changed, which
is not yet implemented.å
æ Remove current fao from file chain å
IF SameEntity (faoEnv^^.faoChain, faoEnv ) THEN
æ only one fao to this file, nothing to be done å
ELSE
BEGIN
res := Copy (faoEnv, nextFao);
WHILE NOT SameEntity (nextFao^^.faoChain, faoEnv) DO
res := Copy (nextFao^^.faoChain, nextFao);
res := Copy (faoEnv^^.faoChain, nextFao^^.faoChain);
END;
END; ænot previously terminated by Excludeå
END; æwithå
DO begin
res:=getException;
æ*b* printVar ('Close Exception, Res: ',res); *e*å
end;
ægate must be re-openedå
res := vsGate.Open;
æ*b* printText ('-- end vs.Close --'); *e*å
END; æCloseå
OTHERWISE VersOther
WITH RECORD t : ^^; END;
BEGIN
Exception (MakeRes (Reject*EntryIllegal, Universal, entryA, 0));
END; æotherwiseå
END; æVersFilImplementå
INITIALIZE
versFilImplement 'versafs':
allocRef 'allocate',
schedRef 'scheduler',
objDirRef 'objdir',
vsData
END.
«eof»