@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H            SYS162
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL~
~
~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS162
~S~M~OSYS IMPLEMENTATION DESCRIPTION
~
~
~M~OSection 16 Version 2
~S~OSection 16.2 File System (with Remote Access)
~S~O1. General Description
~BThis module provides commands for filing and retrieving segments on local mach
ines as well as remote ones.
It maintains a single level directory structure, with a directory for
each user. Facilities are provided for processes to switch between directories,
and also for a user to selectively permit another user to access the
files in his directory.

~S~O2. Interfaces
Other modules used~
   Section 1 (Coordinator)~
   Section 3 (Drum management)~
   Section 8 (Clocks)~
   Section 13 (Process management)~
   Section 14 (Virtual store management)~
   Section 15 (Message System)~
   Section 17 (User management)~
   Section 18 (Network management)~
   Section 20 (Process zero)~
Interrupt level interface procedures~
   DISC.STATUS (DISC NO, STATUS)~
Organisational commands~
   OPEN.DIR (USERNAME, PASSWORD)~
   OPEN.FILE (FILENAME, USERNAME, SEGMENT, ACCESS)~
   FILE (FILENAME, USERNAME, SEGMENT)~
   DELETE.FILE (FILENAME, USERNAME)~
   RENAME.FILE (OLD FILENAME, USERNAME, NEW FILENAME)~
   CATALOGUE.FILES ()~
   READ.FILE.STATUS (FILENAME, USERNAME)~
   PERMIT (FILENAME, USERNAME, ACCESS)~
   CATALOGUE.PERMIT ()~
   REMOTE.DIR (NEWNAME, USERNAME, PASSWORD, MACHINE, REMOTEUSER)~
Command level interface procedures~
   CLOSE.FILE (SYSTEM SEGMENT)~
~S~O2.1 Hardware Interface
   None.~
~S~O2.2 Software Interface
~
1) CLOSE.FILE (SYSTEM SEGMENT)
~BThis procedure is called by the virtual store manager whenever
a user releases a segment which is already a file.
~
~
2) DISC.STATUS (DISC.NO, STATUS)~
~B This is called by the drum manager to indicate a change in
status of disc DISC.NO. STATUS is zero if the disc is going offline and
one if it is coming online.
~
~
~
~S~O3. Implementation
~S~O3.1 Outline of Operation
~BThe file system maintains a directory for each user. The position and size of
all
the directories is kept in a data structure known as the master block (MB).
Space is allocated at a fixed address on the disc for two copies of the master b
lock.
Whenever changes to a directory are made, the directory concerned is
written to a fresh area of the disc, the master block updated and written to
the appropriate disc copy in turn. Thus, if the machine fails during updating
the directory or master block, the existing directories and at least one of the
master
blocks is secure and valid.
~BA generation number is kept within the master block, and this is incremented
whenever an updated directory and master block is written to disc.
Thus, on restarting, the latest version of the master block (and hence
the latest versions of all the directories) can be selected by examining the
two versions of the master block on disc, and selecting the one with the
latest generation number.
~BUsers are able to share files in two ways. A user is able to switch directorie
s by specifying the username and password
of the user whose directory is required. This naturally implies a certain degree
of trust between the users, as all of the files in a directory are available
once a directory is open. Alternatively, a user may "PERMIT" a file to be
accessed by another user. A file kept at entry 0 in a directory lists the files
and permissions which that user has allowed to other users. Whenever a non-zero
username is specified as a parameter of one of the file organisational
commands, the corresponding permission file is read and checked to see if
the current user may perform the required operations. The permission file cannot
be accessed directly by users.
~BWhen a file is opened, an entry is made in a table called the system
file table (SFT). This has an entry corresponding to each system segment, and ho
lds
the identification of the file.
~BA data structure known as REMOTE.DIRS is associated
with each process. Users are able to perform remote file
operations by defining a remote username. An entry is made
in the REMOTE.DIRS of the current process. If a newname previously
defined in a REMOTE.DIR command is used as a username
parameter of a file command, a message is send to the
appropriate file manager to perform the specified command.
The concurrency control of redundant copies are not directly
taken care by the system. The "user bits" of the file
STATUS variable are available to the user for implementing
sophisticated consistency mechanisms to be used in conjuntion with the
primitives already available.



~S~O3.2 Data structures
~V1 0
~
~T% 25
~

FILE.VARS
~IA type of the variables kept within each PRB, for monitoring the
file usage of a process.~
   :USER.UID
~IThe identification of the directory when the process was created.~
   :DIR.UID
~IThe identification of the directory currently open.~
   :CURRENT.REMOTE.DIR
~IThe index of the currently open remote directory (initially -1).~
DIR.ENTRY
~IThe type of an entry within a directory.~
~IThis has two formats:~
   :NO.OF.FILES
~INumber of files within the directory.~
   :FILESTORE.USED
~IAmount of filestore occupied (in blocks).~
   :NO.OF.PERMISSIONS
~INumber of entries in the permission file.~
   :PERMIT.SIZE
~ISize of the permission file (in blocks).~
   :PERMIT.ADDR
~IDisc address of the permission file.~
~IThis form is only applicable to the first entry in the directory.
Subsequent entries provide information about each of the files owned by
the user, and have the form:~
   :FILENAME
~
   :STATUS
~
   :F.SIZE
~ISize of the file (in blocks).~
   :CREATE.TIME
~
~
   :UPDATE.TIME
~
~
   :FILE.ID
~IUnique File Identifier.~
   :DISC.ADDR
~IStarting disc address of the file (in blocks).~
FILE.MB.ENTRY
~IThe format of a master block.~
   :DISC.ADDR
~IA vector indexed by user identification, giving the starting disc address
of the directory for the user.~
   :D.SIZE
~IA vector giving the size of the directory for each user (in blocks).~
   :GEN.NO
~IThe generation number of the master block.~
SFT.ENTRY
~IThe format of the entries in the system file table (SFT).~
   :FILE.IDENT
~IIdentification of an open file.~
   :COUNT
~ICount of shared access to that file (-1 if exlusively open).~
PERMIT.ENTRY
~IThe format of entries in the permission file.~
   :FILENAME
~IThe file to be shared with other users.~
   :USER
~IThe users who are allowed to access the file.
The name "ALL" allows all users to access the file.~
   :ACCESS
~IThe permission available to the users.~
REMOTE.DIR.TYPE
~IThe format of entries in the USER.REMOTE.DIR.TYPE.~
   :N.NAME
~IThe name which is defined to be used in a remote file command.~
   :U.NAME
~IThe name name of a legal user on the remote machine.~
   :P.WORD
~IThe password of the specified user.~
   :M.NAME
~IThe name of the remote machine.~
   :R.USER
~IThe owner of the file.~
   :DEST
~IA vector of 4 INTEGER entries keeping the destination information
about the file management process on the remote machine. The first
two entries hold the SPN (including machine number) and PID respectively. The th
ird entry
specify the destination mode. The fourth enrty is the destination
sequence number (initially zero) which is incremented each time
a remote file operation involves that directory.~
USER.REMOTE.DIR.TYPE
~IThe format of entries in the USER.REMOTE.DIR.~
USER.REMOTE.DIR
~IA vector of USER.REMOTE.DIR.TYPE holding all the remote definitions.
~
NO.OF.REMOTE.DIRS
~IMaximum number of remote definitions a process may have.~
FILE.LIMIT
~IA vector giving the amount of file space available to each user.
If a user exceeds this limit, subsequent OPEN.FILE requests will
be rejected.~
FILE.DIR.LIMIT
~IA vector giving the maximum number of files which each user may posses.~
SFT
~IA vector of type SFT.ENTRY, with an entry for each system file number
(system segment number), indicating if a segment is also a file, and if so,
to whom it belongs.~
FILE.UID
~IThe identification of the directory required for the current file operation.~
CURRENT.DIR.UID
~IThe identification of the directory currently accessible.~
CURRENT.DIR.SIZE
~IThe size of the currently accessible directory.~
CURRENT.DIR.ADDR
~IThe disc address of the currently accesible directory.~
OLD.DIR.SIZE
~IThe size of the accessible directory before the last file operation.~
OLD.DIR.ADDR
~IThe disc address previously occupied by the directory before the last file
operation.~
CURRENT.MB.ADDR
~IDisc address of the latest version of the master block.~
FILE.TRANSFER.ADDR
~IDisc address of the next file system transfer.~
FILE.TRANSFER.SIZE
~ISize of the next file system transfer.~
FILE.TRANSFER.SEG
~ISegment into which the next file system transfer is to take place.~
DIR.ENTRY.SIZE
~IA literal giving the size of a directory entry (in bytes).~
MB.START.ADDR
~IThe disc address of the first (even numbered) file master block.~
~S~O3.3 Special Notes
~BNone.
~Y
~V9 -1
~P
~V9 -1
~D15
~HFLOWCHARTS
~
~
~H                SYS162
~V9 -1
~F
@TITLE SYS16(2,11)

@COL 1S-2R-3R-4R-5R-6F

@FLOW 1-2-3-4-5-6

@BOX 1.0
FILE SYSTEM
@BOX 4.0
PROCEDURES IN MODULE
   INT1 FILE TRANSFER
   INT2 DISC STATUS
   CMD1 OPEN DIR
   CMD2 OPEN FILE
   CMD3 FILE
   CMD4 DELETE FILE
   CMD5 RENAME FILE
   CMD8 CATALOGUE FILES
   CMD9 READ FILE STATUS
   CMD10 START FILE REQUEST
   CMD11 END FILE REQUEST
   CMD12 SECURE DIR
   CMD13 FIND FILE ENTRY
   CMD14 ALLOCATE FILE ENTRY
   CMD15 DELETE FILE ENTRY
   CMD16 CLOSE FILE
   CMD17 INIT FILES
   CMD18 TINI FILES
   CMD19 PERMIT
   CMD20 GET DIR
   CMD21 GET MB
   CMD22 CATALOGUE PERMIT
   CMD23 REMOTE DIR
   CMD24 CHECK REMOTE
   CMD25 REMOTE FILE REQUEST
   CMD26 DELETE USER DIR
   CMD27 SET DISC INIT
   CMD28 CREATE FILE SEGMENT
   CMD29 CREATE FILE X SEGMENT
   CMD30 CHECK AUX
   CMD31 GET DISC
   TSK1 FILE TASK
   TSK2 INIT FILE DISC
@BOX 6.0
END
@BOX 1.1
#SYS16/1
MODULE SYS16 (OPEN.DIR, OPEN.FILE, FILE, DELETE.FILE, RENAME.FILE,
   CATALOGUE.FILES, READ.FILE.STATUS, PERMIT, CLOSE.FILE,
   CATALOGUE.PERMIT, INIT.FILES, TINI.FILES, REMOTE.DIR, DELETE.USER.DIR,
   FILE.TASK, DISC.STATUS, INIT.DISC,
   FILE.VARS, AUX.DIR.TYPE, REMOTE.DIR.TYPE, STATS.TYPE,
   CREATE.FILE.SEGMENT, CREATE.FILE.X.SEGMENT, INIT.FILE.TASK);
@BOX 2.1
TYPE SFT.ENTRY IS
   INTEGER32 FILE.IDENT
   INTEGER8 COUNT, DISC.NO;
TYPE DIR.ENTRY IS
   INTEGER16 NO.OF.FILES, FILE.STORE.USED, NO.OF.PERMISSIONS, PERMIT.SIZE
   INTEGER32 PERMIT.ADDR
OR
   LOGICAL64 FILE.NAME
   INTEGER16 STATUS, F.SIZE, C.SIZE
   INTEGER32 CREATE.TIME, UPDATE.TIME, FILE.ID
   INTEGER32 DISC.ADDR
   LOGICAL8 [2] FILLER;
TYPE FILE.MB.ENTRY IS
   INTEGER32 [NO.OF.DIRS] DISC.ADDR
   INTEGER16 [NO.OF.DIRS] D.SIZE
   INTEGER8 [MB.FILLER.SIZE] FILLER
   LOGICAL64 MB.DISC.NAME
   INTEGER32 FILLER2, GEN.NO;
TYPE PERMIT.ENTRY IS
   LOGICAL64 F.NAME, USER
   LOGICAL32 ACCESS;
TYPE AUX.DIR.TYPE IS
   INTEGER AUX.UID
   LOGICAL64 AUX.DIR.NAME, AUX.DISC.NAME
OR
   INTEGER AUX.LINK;
TYPE REMOTE.DIR.TYPE IS
   LOGICAL64 N.NAME, U.NAME, P.WORD, M.NAME, DISC, R.USER
   INTEGER [4] DEST
OR
   INTEGER REMOTE.LINK;
TYPE FILE.VARS IS
   INTEGER16 USER.UID, DIR.UID, DIR.TYPE
   INTEGER16 [NO.OF.REMOTE.DIRS] REMOTE.TABLE
   INTEGER16 [NO.OF.AUX.DIRS] AUX.TABLE;
TYPE DISC.VARS.TYPE IS
   INTEGER CURRENT.DIR.UID, CURRENT.DIR.SIZE, CURRENT.DIR.ADDR, CURRENT.MB.ADDR
   LOGICAL64 DISC.NAME
   LOGICAL8 DISC.STATE;
TYPE STATS.TYPE IS
  INTEGER32 FILES.OPENED, FILES.CREATED, FILES.UPDATED;
@BOX 3.1
*GLOBAL 5;
INTEGER FILE.UID, FILE.DISC, OLD.DIR.SIZE, FILE.TRANSFER.STATUS, OLD.DIR.SEG;
INTEGER FILE.TRANSFER.ADDR, OLD.DIR.ADDR, REBUILD.FLAG;
DISC.VARS.TYPE [SYS03.NO.OF.DISCS] DISC.VARS;
ADDR FILE.VARS C.FILE.VARS;
ADDR [DIR.ENTRY] DIR;
ADDR FILE.MB.ENTRY MB;
ADDR [PERMIT.ENTRY] PERMISSIONS;
ADDR STATS.TYPE STATS;
INTEGER REMOTE.FREE, AUX.FREE;
*GLOBAL 28;
REMOTE.DIR.TYPE [NO.OF.SYS.REMOTE.DIRS] REMOTE.DIRS;
AUX.DIR.TYPE [NO.OF.SYS.AUX.DIRS] AUX.DIR;
*GLOBAL 28;
SFT.ENTRY [SYS14.NO.OF.SYS.SEGS] SFT;
LITERAL / INTEGER TRANSFER.FAIL = %1601;
LITERAL / INTEGER DISC.ONLINE = 1, DISC.STATE.MASK = %FE, DISC.TASK.REQUEST = 2,
   DISC.INIT = 8, DISC.NAME.CHANGE = 4, TEMP.DISC.NAME = 16;
LITERAL / INTEGER REM.DIR = 1, AUXIL.DIR = 2;
LITERAL / INTEGER DIR.ENTRY.SIZE = 40, PERMIT.ENTRY.SIZE = 24;
@BOX 4.1
#SYS16/2
@BOX 5.1
*CODE 7;
::*INIT %6000;
PSPEC INIT.SYS16 ();
INIT.SYS16 ();
PROC INIT.SYS16;
MAKE (STATS.TYPE, 0, SYS21.GET.STATS (16)) => STATS;
END
@BOX 6.1
*END
@END

@TITLE SYS16/1(2,10)

@COL 1S-2R-3R-4R

@FLOW 1-2-3-4

@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
SYS01 COORDINATOR
SYS03 DRUM MANAGER
SYS08 CLOCKS
SYS13 PROCESS MANAGER
SYS14 VIRTUAL STORE MANAGER
SYS17 USER MANAGER
SYS20 PROCESS ZERO
@BOX 1.1
::EXTERNAL ENVIRONMENT
@BOX 2.1
IMPORT LITERAL FILE.MAPPED.SEG, FILE.SEG, PERMIT.MAPPED.SEG,
   CATALOGUE.MAPPED.SEG, NO.OF.DIRS, MB.FILLER.SIZE,
   NO.OF.REMOTE.DIRS, NO.OF.AUX.DIRS,
   NO.OF.SYS.REMOTE.DIRS, NO.OF.SYS.AUX.DIRS;
IMPORT LITERAL SYS03.NO.OF.DISCS;
LOGICAL [SYS03.NO.OF.DISCS] MB.START.ADDR;
ADDR PW0, PW1, PW2, PW3, PW4, PW5, PW6;
LOGICAL64 PWW1, PWW2, PWW3, PWW4;
@BOX 3.1
@BOX 4.1
PSPEC SYS01.CHECKIN (INTEGER, INTEGER);
PSPEC SYS01.CHECKOUT (INTEGER, INTEGER);
::IMPORT LITERAL SYS03.NO.OF.DISCS;
PSPEC SYS03.REQUEST.DRUM.TRANSFER (INTEGER, INTEGER, INTEGER, INTEGER,
   INTEGER, INTEGER) / INTEGER;
PSPEC SYS03.CHANGE.DRUM.SIZE (INTEGER, INTEGER, INTEGER, INTEGER);
PSPEC SYS03.CMD.ALLOCATE.DRUM.BLOCK (INTEGER, INTEGER) / INTEGER;
PSPEC SYS03.RESERVE.DRUM.SPACE (INTEGER, INTEGER, INTEGER);
PSPEC TIME.AND.DATE ();
PSPEC SYS12.SYSTEM.ERROR (INTEGER);
IMPORT LITERAL SYS13.NO.OF.PROCS;
INTEGER SYS13.CURRENT.SPN;
PSPEC SYS13.CHECK.PRIV ();
PSPEC LOOK.UP.PROCESS (LOGICAL64, LOGICAL64);
PSPEC SYS13.INT.PROC (LOGICAL, LOGICAL);
PSPEC SYS13.ENTER.INT.LEVEL (ADDR SYS13.INT.PROC, LOGICAL, LOGICAL);
PSPEC SYS13.GET.PRB (INTEGER, INTEGER) / ADDR;
PSPEC NAMES ();
IMPORT LITERAL SYS14.PAGE.SIZE, SYS14.PAGE.SHIFT, SYS14.NO.OF.SYS.SEGS,
    SYS14.X.SEG.SIZE;
IMPORT LITERAL ADDR SYS14.SEG.SIZE;
PSPEC SYS14.GET.BLOCK (INTEGER, INTEGER) / INTEGER32;
PSPEC SYS14.UPDATE.BLOCK (INTEGER32);
PSPEC SYS14.REL.BLOCK (INTEGER32);
PSPEC COPY.BLOCK (INTEGER, INTEGER, INTEGER, INTEGER);
PSPEC READ.SEGMENT.STATUS (INTEGER);
PSPEC SYS14.READ.SYS.SEGMENT.STATUS (INTEGER);
PSPEC CREATE.SEGMENT (INTEGER, ADDR);
PSPEC SYS14.CREATE.DISC.SEGMENT (INTEGER, ADDR, INTEGER);
PSPEC SYS14.CREATE.DISC.X.SEGMENT (INTEGER, INTEGER);
PSPEC RELEASE.SEGMENT (INTEGER);
PSPEC SYS14.ALLOCATE.SYS.SEG (INTEGER, INTEGER, INTEGER, INTEGER, INTEGER) / INT
EGER;
PSPEC SYS14.ASSIGN.USER.SEGMENT (INTEGER, INTEGER, LOGICAL);
PSPEC SECURE.SEGMENT (INTEGER);
PSPEC SYS14.PROTECT (INTEGER, INTEGER);
PSPEC MAP (INTEGER, INTEGER, INTEGER);
PSPEC SYS14.CMD.MAP (INTEGER, INTEGER);
PSPEC SYS14.RELEASE.SYS.SEGMENT (INTEGER);
PSPEC SYS14.RESERVE.SEG (INTEGER, INTEGER, INTEGER, INTEGER);
PSPEC WAIT (LOGICAL, INTEGER);
PSPEC SET.CH.STATUS (INTEGER, INTEGER, INTEGER, INTEGER);
PSPEC SEND.MESSAGE (ADDR [LOGICAL8], ADDR [INTEGER],
   INTEGER, INTEGER, INTEGER, LOGICAL);
PSPEC READ.MESSAGE (ADDR [LOGICAL8], ADDR [INTEGER], INTEGER, INTEGER);
IMPORT LITERAL SYS17.NO.OF.FILES, SYS17.FILE.STORE;
PSPEC FIND.U (LOGICAL64, LOGICAL64);
PSPEC SYS17.FIND.UID (LOGICAL64);
PSPEC SYS17.GET.USER.PARAM (INTEGER, INTEGER) / INTEGER;
IMPORT LITERAL SYS20.FILE.TASK;
PSPEC SYS20.SET.TASK (INTEGER, INTEGER);
PSPEC SYS21.GET.STATS (INTEGER) / ADDR;
@END

@TITLE SYS16/2(2,11)

@COL 1S

@BOX 1.1
*CODE 2;
::*INIT %6000;
PSPEC FILE.TRANSFER (INTEGER, INTEGER);
PSPEC DISC.STATUS (INTEGER, INTEGER);
   #SYSINT16.1
   #SYSINT16.2
*CODE 19;
::*INIT %7000;
PSPEC INIT.FILES (ADDR FILE.VARS, INTEGER);
PSPEC TINI.FILES (INTEGER);
   #SYSCMD16.17
   #SYSCMD16.18
*CODE 20;
LSPEC OPEN.DIR (LOGICAL64, LOGICAL64);
LSPEC OPEN.FILE (ADDR [LOGICAL8], LOGICAL64, INTEGER, LOGICAL);
LSPEC FILE (ADDR [LOGICAL8], LOGICAL64, INTEGER);
LSPEC DELETE.FILE (ADDR [LOGICAL8], LOGICAL64);
LSPEC RENAME.FILE (ADDR [LOGICAL8], LOGICAL64, ADDR [LOGICAL8]);
LSPEC CATALOGUE.FILES ();
LSPEC READ.FILE.STATUS (ADDR [LOGICAL8], LOGICAL64);
PSPEC START.FILE.REQUEST (LOGICAL64, LOGICAL64, LOGICAL);
PSPEC END.FILE.REQUEST ();
PSPEC SECURE.DIR ();
PSPEC FIND.FILE.ENTRY (LOGICAL64) / INTEGER;
PSPEC ALLOCATE.FILE.ENTRY () / INTEGER;
PSPEC DELETE.FILE.ENTRY (INTEGER);
LSPEC PERMIT (ADDR [LOGICAL8], LOGICAL64, LOGICAL64);
PSPEC GET.DIR ();
PSPEC GET.MB (INTEGER, INTEGER);
LSPEC CATALOGUE.PERMIT ();
LSPEC REMOTE.DIR (LOGICAL64, LOGICAL64, LOGICAL64, LOGICAL64,
   LOGICAL64, LOGICAL64);
PSPEC CHECK.REMOTE (LOGICAL64) / INTEGER;
PSPEC DELETE.USER.DIR (INTEGER16) / INTEGER;
PSPEC REMOTE.FILE.REQUEST (INTEGER, INTEGER, LOGICAL64, LOGICAL64, LOGICAL64);
LSPEC INIT.DISC (INTEGER, LOGICAL64, INTEGER);
LSPEC CREATE.FILE.SEGMENT (INTEGER, ADDR, ADDR [LOGICAL8], LOGICAL64);
LSPEC CREATE.FILE.X.SEGMENT (INTEGER, ADDR [LOGICAL8], LOGICAL64);
PSPEC CHECK.AUX (LOGICAL64) / INTEGER;
PSPEC GET.DISC.NO (LOGICAL64) / INTEGER;
PSPEC TRANSFORM.NAME (ADDR [LOGICAL8])/LOGICAL64;
   #SYSCMD16.1
   #SYSCMD16.2
   #SYSCMD16.3
   #SYSCMD16.4
   #SYSCMD16.5
   #SYSCMD16.8
   #SYSCMD16.9
   #SYSCMD16.10
   #SYSCMD16.11
   #SYSCMD16.12
   #SYSCMD16.13
   #SYSCMD16.14
   #SYSCMD16.15
   #SYSCMD16.19
   #SYSCMD16.20
   #SYSCMD16.21
   #SYSCMD16.22
   #SYSCMD16.23
   #SYSCMD16.24
   #SYSCMD16.26
   #SYSCMD16.27
   #SYSCMD16.28
   #SYSCMD16.29
   #SYSCMD16.30
   #SYSCMD16.31
PROC TRANSFORM.NAME (IN.NAME);
INTEGER PTR, MAXCH;
LOGICAL64 OUT.NAME;
0 => OUT.NAME;
IF SIZE (IN.NAME) => MAXCH > 0 THEN
   FOR PTR < MAXCH DO
      OUT.NAME <<- 8 ! IN.NAME^ [PTR] => OUT.NAME;
   OD;
FI;
OUT.NAME => TRANSFORM.NAME;
END
*CODE 16;
PSPEC CLOSE.FILE (INTEGER);
::PSPEC REMOTE.FILE.REQUEST (INTEGER, INTEGER, LOGICAL64, LOGICAL64, LOGICAL64);
   #SYSCMD16.16
   #SYSCMD16.25
*CODE 4;
PSPEC FILE.TASK ();
PSPEC INIT.FILE.TASK ();
PSPEC INIT.FILE.DISC (INTEGER, LOGICAL64);
   #SYSTSK16.1
   #SYSTSK16.2
   #SYSTSK16.3
@END
@TITLE SYSINT16.1(2,9)
@COL 1S-8R-7T-2R-3T-4R-5R-9R-6F

@FLOW 1-8-7NO-2-3OK-4-5-7
@FLOW 7YES-6
@FLOW 3FAIL-9-6

@BOX 1.0
FILE TRANSFER (DIRECTION, OFFSET)
@BOX 2.0
LOCK SPECIFIED BLOCK
INTO CORE
[SYS14]
@BOX 3.0
REQUEST DRUM TRANSFER
INTO BLOCK
[SYS03]
@BOX 4.0
MARK BLOCK ALTERED
IF TRANSFER INTO CORE
[SYS14]
@BOX 5.0
RELEASE LOCKIN ON BLOCK
[SYS14]
@BOX 6.0
END
@BOX 7.0
IS TRANSFER COMPLETE?
@BOX 8.0
FIND SIZE OF TRANSFER
@BOX 9.0
INDICATE FILE TRANSFER FAILED
@BOX 1.1
PROC FILE.TRANSFER (DIRN, OFFSET);
INTEGER32 CORE.ADDR;
INTEGER BLOCK.NO, FILE.TRANSFER.SIZE;
@BOX 2.1
IF SYS14.GET.BLOCK (FILE.SEG + FILE.DISC, BLOCK.NO + OFFSET)
   => CORE.ADDR < 0 THEN
   SYS12.SYSTEM.ERROR (TRANSFER.FAIL);
FI
@BOX 3.1
IF SYS03.REQUEST.DRUM.TRANSFER (FILE.DISC, CORE.ADDR ->> SYS14.PAGE.SHIFT,
   FILE.TRANSFER.ADDR, BLOCK.NO, 1, DIRN) /= 0
@BOX 4.1
IF DIRN = 0 THEN
   SYS14.UPDATE.BLOCK (CORE.ADDR);
FI
@BOX 5.1
SYS14.REL.BLOCK (CORE.ADDR);
@BOX 6.1
END
@BOX 7.1
IF 1 +> BLOCK.NO >= FILE.TRANSFER.SIZE
@BOX 8.1
-1 => BLOCK.NO;
0 => FILE.TRANSFER.STATUS;
SELECT DISC.VARS [FILE.DISC];
IF OFFSET = 2 THEN
   CURRENT.DIR.SIZE => FILE.TRANSFER.SIZE;
ELSE
   1 => FILE.TRANSFER.SIZE;
FI
@BOX 9.1
SYS14.REL.BLOCK (CORE.ADDR);
1 => FILE.TRANSFER.STATUS;
@END

@TITLE SYSINT16.2(2,10)

@COL 1S-3T-4R-5F
@COL 2R

@ROW 4-2

@FLOW 1-3NO-4-5
@FLOW 3YES-2-5

@BOX 1.0
DISC STATUS (DISC NO., STATUS)
@BOX 2.0
NOTE DISC OFFLINE
@BOX 3.0
DISC OFF LINE?
@BOX 4.0
SET TASK REQUEST
[SYS20]
@BOX 5.0
END
@BOX 1.1
PROC DISC.STATUS (DISC.NO, STATUS);
SELECT DISC.VARS [DISC.NO];
@BOX 2.1
0 => DISC.STATE;
@BOX 3.1
IF STATUS & DISC.ONLINE = 0
@BOX 4.1
DISC.TASK.REQUEST ! DISC.ONLINE !> DISC.STATE;
SYS20.SET.TASK (SYS20.FILE.TASK, 0);
@BOX 5.1
END
@END
@TITLE SYSCMD16.1(2,9)

@COL 7R-8R-9N
@COL 1S-2T-23T-10T-3T-4R-5F
@COL 6R

@ROW 7-3
@ROW 6-23

@FLOW 23REMOTE-7-9-5
@FLOW 1-2NO-23LOCAL-10NO-3NO-4-5
@FLOW 2YES-6-5
@FLOW 10YES-8-9
@FLOW 3YES-5

@BOX 1.0
OPEN DIR (USERNAME, PASSWORD)
@BOX 2.0
IS USERNAME ZERO?
@BOX 3.0
ARE USERNAME OR
PASSWORD INVALID?
[SYS17]
@BOX 4.0
RESET DIRECTORY
TO NEW USER
@BOX 5.0
END
@BOX 6.0
RESET DIRECTORY TO
ORIGINAL USER
@BOX 7.0
SET DIRECTORY TO
REMOTE DIR
@BOX 8.0
SET DIRECTORY TO AUXILIARY DIR
@BOX 10.0
AUXILIARY DIRECTORY NAME?
[SYSCMD16.30]
@BOX 23.0
REMOTE DIRECTORY NAME?
[SYSCMD16.24]
@BOX 1.1
PROC OPEN.DIR (U.NAME, P.WORD);
ADDR FILE.VARS C.FILE.VARS;
INTEGER DIR.NO;
0 => PW0;
@BOX 2.1
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
IF U.NAME = 0
@BOX 3.1
FIND.U (U.NAME, P.WORD);
IF PW0 /= 0
@BOX 4.1
0 => DIR.TYPE;
PW1 => DIR.UID;
@BOX 5.1
END
@BOX 6.1
USER.UID => DIR.UID;
0 => DIR.TYPE;
@BOX 7.1
DIR.NO => DIR.UID;
REM.DIR => DIR.TYPE;
@BOX 8.1
DIR.NO => DIR.UID;
AUXIL.DIR => DIR.TYPE;
@BOX 10.1
IF CHECK.AUX (U.NAME) => DIR.NO >= 0
@BOX 23.1
IF CHECK.REMOTE (U.NAME) => DIR.NO >= 0
@END

@TITLE SYSCMD16.2(2,11)

@COL 1S-23T-2T-3T-4T-5T-6T-21T-7R-9R-15N-10R-11N-12F
@COL 19N-24R-13R-14R-20T-17R-16N-18N

@ROW 23-19
@ROW 3-13
@ROW 6-14
@ROW 7-20
@ROW 15-16
@ROW 11-18

@FLOW 1-23LOCAL-2NO-3-4NO-5NO-6NO-21OK-7-9-15-10-11-12
@FLOW 23REMOTE-19-24-18
@FLOW 2YES-13-18-11
@FLOW 3FAIL-15
@FLOW 4YES-15
@FLOW 5YES-14-16-15
@FLOW 6YES-20NO-17-16
@FLOW 20YES-9
@FLOW 21FAIL-15

@BOX 1.0
OPEN FILE (FILENAME, USERNAME, SEG, ACCESS)
@BOX 2.0
IS SEGMENT OCCUPIED
OR INVALID?
@BOX 3.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 4.0
IS FILE NON-EXISTENT?
[SYSCMD16.13]
@BOX 5.0
FILE LIMIT EXCEEDED?
@BOX 6.0
IS FILE ALREADY OPEN?
@BOX 7.0
INITIALISE A FILE TABLE ENTRY
@BOX 9.0
OPEN FILE INTO
USERS VIRTUAL STORE
@BOX 10.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 12.0
END
@BOX 13.0
RETURN FAULT STATUS -46
(ILLEGAL SEGMENT SPECIFIED)
@BOX 14.0
RETURN FAULT STATUS -41
(FILE STORE LIMIT EXCEEDED)
@BOX 17.0
RETURN FAULT STATUS -44
(EXCLUSIVE ACCESS FAULT)
@BOX 20.0
SHARED ACCESS ALLOWED?
@BOX 21.0
ALLOCATE SYSTEM SEGMENT
[SYS14]
@BOX 23.0
IS FILE REMOTE?
[SYSCMD16.24]
@BOX 24.0
REQUEST A COPY OF THE FILE FROM
THE FILE MANAGER OF THE
SPECIFIED MACHINE
[SYSCMD16.25]
@BOX 1.1
PROC OPEN.FILE (PATH.NAME, U.NAME, SEG, ACCESS);
INTEGER FILE.NO, SSN, REMOTE.DIR.NO;
LOGICAL64 F.NAME;
0 => PW0;
TRANSFORM.NAME (PATH.NAME) => F.NAME;
@BOX 2.1
IF SEG < 0 THEN
   -6 => PW0;
ELSE
   READ.SEGMENT.STATUS (SEG);
FI
IF PW0 /= -6
@BOX 3.1
START.FILE.REQUEST (F.NAME, U.NAME, ACCESS & %17);
IF PW0 /= 0
@BOX 4.1
IF FIND.FILE.ENTRY (F.NAME) => FILE.NO < 0
@BOX 5.1
PW1 => SSN;
IF FILE.STORE.USED OF DIR^ [0] >
   SYS17.GET.USER.PARAM (FILE.UID, SYS17.FILE.STORE)
@BOX 6.1
IF SSN >= 0
@BOX 7.1
SYS14.PROTECT (SSN, 1);
FILE.ID => FILE.IDENT OF SFT [SSN];
FILE.DISC => DISC.NO OF SFT [SSN];
@BOX 9.1
IF ACCESS & %20 /= 0 THEN
   -1 => COUNT OF SFT [SSN];
FI
1 +> FILES.OPENED OF STATS^;
SYS14.ASSIGN.USER.SEGMENT (SSN, SEG, ACCESS & %1F);
@BOX 10.1
END.FILE.REQUEST ();
@BOX 12.1
END
@BOX 13.1
-46 => PW0;
@BOX 14.1
-41 => PW0;
@BOX 17.1
-44 => PW0;
@BOX 20.1
IF ACCESS & %20 = 0 OR
   COUNT OF SFT [SSN] >= 0
@BOX 21.1
SELECT DIR^ [FILE.NO];
SYS14.ALLOCATE.SYS.SEG (DISC.ADDR, FILE.DISC,
   F.SIZE, C.SIZE, STATUS) => SSN;
IF PW0 /= 0
@BOX 23.1
IF ACCESS =< 0 THEN
   %1E => ACCESS;
FI
IF CHECK.REMOTE (U.NAME) => REMOTE.DIR.NO >= 0
@BOX 24.1
REMOTE.FILE.REQUEST (REMOTE.DIR.NO,
   0, F.NAME, ACCESS, SEG);
@END


@TITLE SYSCMD16.3(2,11)

@COL 1S-2T-23T-3T-4T-27T-5R-6T-7T-8R-9T-10R-11R-29N-12R-13N-14F
@COL 26N-25R-24R-15R-28T-16R-17R-19N-18N

@ROW 2-26
@ROW 3-24
@ROW 4-15
@ROW 7-17
@ROW 19-29
@ROW 13-18

@FLOW 1-2NO-23LOCAL-3NO-4-27NO-5-6NO-7-8-9OK-10-11-29-12-13-14
@FLOW 23REMOTE-24-18
@FLOW 2YES-26-25-18-13
@FLOW 3YES-15-18
@FLOW 4FAIL-29
@FLOW 6YES-17-9
@FLOW 7FAIL-29
@FLOW 27YES-28FAIL-19-29
@FLOW 28-16-5
@FLOW 9FAIL-29

@BOX 1.0
FILE (FILENAME, USERNAME, SEG)
@BOX 2.0
IS SEGMENT UNDEFINED?
@BOX 3.0
IS SEGMENT ALREADY A FILE?
@BOX 4.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 5.0
SECURE SEGMENT
[SYS14]
@BOX 6.0
DOES FILE OF THIS NAME
ALREADY EXIST?
[SYSCMD16.13]
@BOX 7.0
ALLOCATE A DIRECTORY ENTRY
[SYSCMD16.14]
@BOX 8.0
INITIALISE DIRECTORY ENTRY
@BOX 9.0
UPDATE DIRECTORY
AND SECURE IT
[SYSCMD16.12]
@BOX 10.0
NOTE SEGMENT IS NOW
FILE
[SYS14]
@BOX 11.0
RELEASE OLD FILE SPACE
IF NECESSARY
[SYS03]
@BOX 12.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 14.0
END
@BOX 15.0
RETURN FAULT STATUS -46
(ILLEGAL SEGMENT SPECIFIED)
@BOX 16.0
COPY FILE TO
CORRECT DISC
@BOX 17.0
NOTE SSN, DISC ADDRESS AND
SIZE OF FILE
@BOX 23.0
IS FILE REMOTE?
[SYSCMD16.24]
@BOX 24.0
FILE THE SEGMENT IN THE
SPECIFIED MACHINE
[SYSCMD16.25]
@BOX 25.0
RETURN FAULT STATUS -46
(ILLEGAL SEGMENT SPECIFIED)
@BOX 27.0
IS SEGMENT ON WRONG DISC?
@BOX 28.0
CREATE SEGMENT ON
CORRECT DISC
@BOX 1.1
PROC FILE (PATH.NAME, U.NAME, SEG);
INTEGER SSN, FILE.NO, CURR.FILE.SSN, CURR.FILE.SIZE, FILE.SIZE,
   FILE.STATUS, FILE.CSIZE, CURR.FILE.ADDR, FILE.ADDR,
   CURR.FILE.STATUS, CURR.FILE.CSIZE, REMOTE.DIR.NO, SEG.DISC,
   COPY.SEG, I;
LOGICAL64 F.NAME;
TRANSFORM.NAME (PATH.NAME) => F.NAME;
@BOX 2.1
SYS14.READ.SYS.SEGMENT.STATUS (SEG);
PW1 => FILE.SIZE;
PW2 => FILE.STATUS;
PW5 => SEG.DISC;
IF PW0 /= 0
@BOX 3.1
IF FILE.IDENT OF SFT [PW3 => SSN] /= 0
@BOX 4.1
START.FILE.REQUEST (F.NAME, U.NAME, %20);
IF PW0 /= 0
@BOX 5.1
SECURE.SEGMENT (COPY.SEG);
SYS14.READ.SYS.SEGMENT.STATUS (COPY.SEG);
PW1 => FILE.SIZE;
PW2 => FILE.STATUS;
PW3 => SSN;
PW4 => FILE.CSIZE;
PWW1 => FILE.ADDR;
TIME.AND.DATE ();
@BOX 6.1
0 => CURR.FILE.SSN;
IF FIND.FILE.ENTRY (F.NAME) => FILE.NO > 0
@BOX 7.1
IF ALLOCATE.FILE.ENTRY () => FILE.NO < 0
@BOX 8.1
PWW1 => CREATE.TIME OF DIR^ [FILE.NO];
F.NAME => FILE.NAME OF DIR^ [FILE.NO];
FILE.SIZE +> FILE.STORE.USED OF DIR^ [0];
1 +> FILES.CREATED OF STATS^;
@BOX 9.1
0 => PW0;
PWW1 => UPDATE.TIME OF DIR^ [FILE.NO];
FILE.SIZE => F.SIZE OF DIR^ [FILE.NO];
FILE.CSIZE => C.SIZE OF DIR^ [FILE.NO];
FILE.STATUS => STATUS OF DIR^ [FILE.NO];
FILE.ADDR => DISC.ADDR OF DIR^ [FILE.NO];
1 + GEN.NO OF MB^ => FILE.ID OF DIR^ [FILE.NO];
SECURE.DIR ();
IF PW0 /= 0
@BOX 10.1
FILE.ID OF DIR^ [FILE.NO] => FILE.IDENT OF SFT [SSN];
FILE.DISC => DISC.NO OF SFT [SSN];
SYS14.PROTECT (SSN, 1);
IF SEG /= COPY.SEG THEN
   RELEASE.SEGMENT (COPY.SEG);
FI
@BOX 11.1
IF CURR.FILE.SSN < 0 THEN
   SYS14.ALLOCATE.SYS.SEG (CURR.FILE.ADDR, FILE.DISC, CURR.FILE.SIZE,
      CURR.FILE.CSIZE, CURR.FILE.STATUS) => CURR.FILE.SSN;
   IF PW0 = 0 THEN
      SYS14.RELEASE.SYS.SEGMENT (CURR.FILE.SSN);
   FI
ELSE
   IF CURR.FILE.SSN > 0 THEN
      0 => FILE.IDENT OF SFT [CURR.FILE.SSN];
      SYS14.PROTECT (CURR.FILE.SSN, 0);
   FI
FI
@BOX 12.1
END.FILE.REQUEST ();
@BOX 14.1
END
@BOX 15.1
-46 => PW0;
@BOX 16.1
FOR I < FILE.SIZE DO
   COPY.BLOCK (SEG, I, COPY.SEG, I);
OD
@BOX 17.1
1 +> FILES.UPDATED OF STATS^;
PW1 => CURR.FILE.SSN;
DISC.ADDR OF DIR^ [FILE.NO] => CURR.FILE.ADDR;
C.SIZE OF DIR^ [FILE.NO] => CURR.FILE.CSIZE;
STATUS OF DIR^ [FILE.NO] => CURR.FILE.STATUS;
F.SIZE OF DIR^ [FILE.NO] => CURR.FILE.SIZE
   - FILE.SIZE -> FILE.STORE.USED OF DIR^ [0];
@BOX 23.1
IF CHECK.REMOTE (U.NAME) => REMOTE.DIR.NO >= 0
@BOX 24.1
REMOTE.FILE.REQUEST (REMOTE.DIR.NO,
   1, F.NAME, 0, SEG);
@BOX 25.1
-46 => PW0;
@BOX 27.1
SEG => COPY.SEG;
IF SEG.DISC /= FILE.DISC
@BOX 28.1
SYS14.CREATE.DISC.X.SEGMENT (FILE.SIZE, FILE.DISC);
PW1 => COPY.SEG;
IF PW0 /= 0
@END


@TITLE SYSCMD16.4(2,11)

@COL 1S-23T-2T-3T-4T-5R-6R-7T-8R-9R-10F
@COL 24R

@ROW 2-24

@FLOW 23REMOTE-24-10
@FLOW 1-23LOCAL-2-3NO-4NO-5-6-7OK-8-9-10
@FLOW 2FAIL-9
@FLOW 3YES-9
@FLOW 4YES-6
@FLOW 7FAIL-9

@BOX 1.0
DELETE FILE (FILENAME, USERNAME)
@BOX 2.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 3.0
IS FILE NON-EXISTENT?
[SYSCMD16.13]
@BOX 4.0
IS FILE OPEN?
@BOX 5.0
REMEMBER DISC ADDRESS OF FILE
@BOX 6.0
DELETE DIRECTORY ENTRY
FOR THE FILE
[SYSCMD16.15]
@BOX 7.0
UPDATE DIRECTORY
ON DISC
[SYSCMD16.12]
@BOX 8.0
RELEASE DISC SPACE
OCCUPIED BY FILE
[SYS03]
@BOX 9.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 10.0
END
@BOX 23.0
IS FILE REMOTE?
[SYSCMD16.24]
@BOX 24.0
DELETE THE REMOTE FILE
[SYSCMD16.25]
@BOX 1.1
PROC DELETE.FILE (PATH.NAME, U.NAME);
INTEGER FILE.NO, FILE.SIZE, CURR.FILE.SSN,
   FILE.ADDR, REMOTE.DIR.NO, CURR.SIZE, FILE.STATUS;
LOGICAL64 F.NAME;
TRANSFORM.NAME (PATH.NAME) => F.NAME;
@BOX 2.1
START.FILE.REQUEST (F.NAME, U.NAME, %40);
IF PW0 /= 0
@BOX 3.1
IF FIND.FILE.ENTRY (F.NAME) => FILE.NO < 0
@BOX 4.1
SELECT DIR^ [FILE.NO];
C.SIZE => CURR.SIZE;
STATUS => FILE.STATUS;
F.SIZE => FILE.SIZE;
IF PW1 => CURR.FILE.SSN >= 0
@BOX 5.1
DISC.ADDR => FILE.ADDR;
@BOX 6.1
DELETE.FILE.ENTRY (FILE.NO);
FILE.SIZE -> FILE.STORE.USED OF DIR^ [0];
@BOX 7.1
SECURE.DIR ();
IF PW0 /= 0
@BOX 8.1
IF CURR.FILE.SSN >= 0 THEN
   0 => FILE.IDENT OF SFT [CURR.FILE.SSN];
   SYS14.PROTECT (CURR.FILE.SSN, 0);
ELSE
   SYS14.ALLOCATE.SYS.SEG (FILE.ADDR, FILE.DISC, FILE.SIZE,
      CURR.SIZE, FILE.STATUS) => CURR.FILE.SSN;
   IF PW0 = 0 THEN
      SYS14.RELEASE.SYS.SEGMENT (CURR.FILE.SSN);
   FI
FI
@BOX 9.1
END.FILE.REQUEST ();
@BOX 10.1
END
@BOX 23.1
IF CHECK.REMOTE (U.NAME) => REMOTE.DIR.NO >= 0
@BOX 24.1
REMOTE.FILE.REQUEST (REMOTE.DIR.NO, 2, F.NAME, 0, 0);
@END


@TITLE SYSCMD16.5(2,1)

@COL 1S-23T-2T-8T-3T-4R-5R-6R-10N-7F
@COL 24R-9R-11N

@ROW 2-24
@ROW 3-9
@ROW 10-11

@FLOW 23REMOTE-24-11-10
@FLOW 1-23LOCAL-2-8NO-3NO-4-5-6-10-7
@FLOW 2FAIL-6
@FLOW 8YES-9-6
@FLOW 3YES-6

@BOX 1.0
RENAME FILE (OLD FILENAME, USERNAME, NEW FILENAME)
@BOX 2.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 3.0
IS FILE NON-EXISTENT?
[SYSCMD16.13]
@BOX 4.0
CHANGE NAME IN
FILE DIRECTORY
@BOX 5.0
SECURE DIRECTORY
[SYSCMD16.12]
@BOX 6.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 7.0
END
@BOX 8.0
DOES NEW FILENAME
ALREADY EXIST?
@BOX 9.0
RETURN FAULT STATUS -47
(FILE NAME ALREADY EXISTS)
@BOX 23.0
IS FILE REMOTE?
[SYSCMD16.24]
@BOX 24.0
CHANGE THE NAME OF THE
REMOTE FILE [SYSCMD16.25]
@BOX 1.1
PROC RENAME.FILE (OPATH.NAME, U.NAME, NPATH.NAME);
INTEGER FILE.NO, REMOTE.DIR.NO;
LOGICAL64 OF.NAME, NF.NAME;
TRANSFORM.NAME (OPATH.NAME) => OF.NAME;
TRANSFORM.NAME (NPATH.NAME) => NF.NAME;
@BOX 2.1
START.FILE.REQUEST (OF.NAME, U.NAME, %80);
IF PW0 /= 0
@BOX 3.1
0 => PW0;
IF FIND.FILE.ENTRY (OF.NAME) => FILE.NO < 0
@BOX 4.1
NF.NAME => FILE.NAME OF DIR^ [FILE.NO];
@BOX 5.1
SECURE.DIR ();
@BOX 6.1
END.FILE.REQUEST ();
@BOX 7.1
END
@BOX 8.1
IF FIND.FILE.ENTRY (NF.NAME) >= 0
@BOX 9.1
-47 => PW0;
@BOX 23.1
IF CHECK.REMOTE (U.NAME) => REMOTE.DIR.NO >= 0
@BOX 24.1
REMOTE.FILE.REQUEST (REMOTE.DIR.NO,
   3, OF.NAME, NF.NAME, 0);
@END



@TITLE SYSCMD16.8(2,9)

@COL 1S-23T-2T-7T-3T-4R-5R-6F
@COL 24R

@ROW 7-24

@FLOW 23REMOTE-24-6
@FLOW 1-23LOCAL-2OK-7-3-4-5-6
@FLOW 2FAIL-5
@FLOW 7NONE-5
@FLOW 3FAIL-5

@BOX 1.0
CATALOGUE FILES
@BOX 2.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 3.0
CREATE SEGMENT FOR
FILE CATALOGUE
@BOX 4.0
COPY DIRECTORY INFORMATION
INTO SEGMENT
@BOX 5.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 6.0
END
@BOX 7.0
ANY FILES IN DIRECTORY?
@BOX 23.0
IS FILE REMOTE?
[SYSCMD16.24]
@BOX 24.0
CATALOGUE THE REMOTE DIRECTORY
[SYSCMD16.25]
@BOX 1.1
PROC CATALOGUE.FILES;
INTEGER COUNT, PTR, PTR8, SEG.NO, FILE.LIM;
ADDR [LOGICAL32] SEG;
ADDR [LOGICAL64] SEG64;
ADDR FILE.VARS C.FILE.VARS;
@BOX 2.1
START.FILE.REQUEST (0, 0, 0);
IF PW0 /= 0
@BOX 3.1
CREATE.SEGMENT (-1, COUNT * 32);
PW1 => SEG.NO;
IF PW0 /= 0
@BOX 4.1
SEG.NO => PW2;
FILE.STORE.USED OF DIR^ [0] => PW4;
0 => PTR;
SYS14.CMD.MAP (SEG.NO, CATALOGUE.MAPPED.SEG);
MAKE (LOGICAL32, COUNT * 8, PW6 * SYS14.SEG.SIZE) => SEG;
MAKE (LOGICAL64, COUNT * 4, PW6 * SYS14.SEG.SIZE) => SEG64;
WHILE 1 +> PTR =< COUNT DO
   SELECT DIR^ [PTR];
   PTR - 1 * 8 => PTR8;
   FILE.NAME => SEG64^ [PTR8 / 2];
   STATUS => SEG^ [PTR8 + 2];
   F.SIZE => SEG^ [PTR8 + 3];
   UPDATE.TIME => SEG^ [PTR8 + 4];
   CREATE.TIME => SEG^ [PTR8 + 5];
   DISC.ADDR => SEG^ [PTR8 + 6];
OD
SYS14.CMD.MAP (PW1, CATALOGUE.MAPPED.SEG);
COUNT => PW1;
FILE.LIM => PW3;
@BOX 5.1
END.FILE.REQUEST ();
@BOX 6.1
END
@BOX 7.1
IF FILE.DISC = 0 THEN
   SYS17.GET.USER.PARAM (FILE.UID, SYS17.NO.OF.FILES) => PW3 => FILE.LIM;
   SYS17.GET.USER.PARAM (FILE.UID, SYS17.FILE.STORE) => PW5;
ELSE
   0 => PW3 => PW5 => FILE.LIM;
FI
0  => PW1 => PW2 => PW4;
IF NO.OF.FILES OF DIR^ [0] => COUNT = 0
@BOX 23.1
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
IF DIR.TYPE = REM.DIR
@BOX 24.1
REMOTE.FILE.REQUEST (DIR.UID,
   4, 0, 0, 0);
@END



@TITLE SYSCMD16.9(2,11)

@COL 1S-2T-3T-4R-5R-6F

@FLOW 1-2-3NO-4-5-6
@FLOW 2FAIL-5
@FLOW 3YES-5

@BOX 1.0
READ FILE STATUS (FILENAME, USERNAME)
@BOX 2.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 3.0
IS FILE NON-EXISTENT?
@BOX 4.0
READ STATUS INFORMATION
ABOUT THE FILE
@BOX 5.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 6.0
END
@BOX 1.1
PROC READ.FILE.STATUS (PATH.NAME, U.NAME);
INTEGER CURR.FILE.SSN, FILE.NO;
LOGICAL64 F.NAME;
0 => PW0;
TRANSFORM.NAME (PATH.NAME) => F.NAME;
@BOX 2.1
START.FILE.REQUEST (F.NAME, U.NAME, 0);
IF PW0 /= 0
@BOX 3.1
IF FIND.FILE.ENTRY (F.NAME) => FILE.NO < 0
@BOX 4.1
PW1 => CURR.FILE.SSN;
SELECT DIR^ [FILE.NO];
STATUS => PW1;
F.SIZE <<- SYS14.PAGE.SHIFT => PWW1;
UPDATE.TIME => PWW2;
CREATE.TIME => PWW3;
IF CURR.FILE.SSN >= 0 THEN
   %C !> PW1;
FI
@BOX 5.1
END.FILE.REQUEST ();
@BOX 6.1
END
@END

@TITLE SYSCMD16.10(2,9)

@COL 1S-2R-8T-3T-4T-5R-7F
@COL 9T-10R

@ROW 9-3

@FLOW 1-2-8NO-3-4OK-5-7
@FLOW 3FAIL-7
@FLOW 4FAIL-7
@FLOW 8YES-9OK-10-7
@FLOW 9FAIL-7

@BOX 1.0
START FILE REQUEST (FILENAME, USERNAME, ACCESS)
@BOX 2.0
CHECKIN
[SYS01]
@BOX 3.0
FIND UID OF
FILE OWNER
@BOX 4.0
GET DIRECTORY FOR
SPECIFIED USER
[SYSCMD16.20]
@BOX 5.0
CHECK ACCESS PERMISSION
   #SYSCMD16.10.1
@BOX 7.0
END
@BOX 8.0
AUXILIARY DIRECTORY?
[SYSCMD16.30]
@BOX 9.0
OBTAIN DISC NUMBER
[SYSCMD16.31]
@BOX 10.0
GET DIRECTORY
[SYSCMD16.20]
@BOX 1.1
PROC START.FILE.REQUEST (F.NAME, U.NAME, ACC);
0 => PW0;
@BOX 2.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 3.1
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
DIR.UID OF C.FILE.VARS^ => FILE.UID;
0 => FILE.DISC;
IF U.NAME /= 0 THEN
   SYS17.FIND.UID (U.NAME);
   PW1 => FILE.UID;
FI
IF PW0 /= 0
@BOX 4.1
GET.DIR ();
IF PW0 /= 0
@BOX 5.1
IF U.NAME /= 0 AND FILE.UID /= USER.UID OF C.FILE.VARS^ THEN
   #SYSCMD16.10.1
FI
@BOX 7.1
END
@BOX 8.1
-1 => OLD.DIR.SEG;
IF CHECK.AUX (U.NAME) >= 0
@BOX 9.1
PW1 => FILE.UID;
GET.DISC.NO (PWW1) => FILE.DISC;
IF PW0 /= 0
@BOX 10.1
GET.DIR ();
@END



@TITLE SYSCMD16.10.1(2,9)

@COL 1S-2T-8R-3T-4T-5T-6F
@COL 9R-7R-10N

@ROW 9-8
@ROW 4-7

@FLOW 1-2OK-8-3FOUND-4THIS USER-5-6
@FLOW 2FAIL-9-10-6
@FLOW 3AT END-7-10
@FLOW 4-3
@FLOW 5YES-3

@BOX 1.0
CHECK ACCESS
@BOX 2.0
READ PERMISSION FILE
@BOX 3.0
SEARCH FILE FOR
REQUIRED FILENAME
@BOX 4.0
ENTRY NOT FOR THIS USER?
@BOX 5.0
REQUIRED ACCESS INVALID?
@BOX 6.0
END
@BOX 7.0
RETURN FAULT STATUS -45
(ILLEGAL ACCESS REQUESTED)
@BOX 8.0
GET USER NAME
@BOX 9.0
RETURN FAULT STATUS -49
(DISC TRANSFER FAILED)
@BOX 1.1
CHECK.ACCESS: BEGIN
INTEGER COUNT, PTR;
@BOX 2.1
SELECT DIR^ [0];
PERMIT.ADDR => FILE.TRANSFER.ADDR;
0 => FILE.TRANSFER.STATUS;
NO.OF.PERMISSIONS => COUNT;
IF COUNT > 0 THEN
   SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 0, 1);
FI
IF FILE.TRANSFER.STATUS /= 0
@BOX 3.1
WHILE 1 +> PTR < COUNT AND
   F.NAME OF PERMISSIONS^ [PTR] /= "ALL" AND
   F.NAME OF PERMISSIONS^ [PTR] /= F.NAME DO OD
IF PTR = COUNT
@BOX 4.1
IF USER OF PERMISSIONS^ [PTR] /= "ALL"
   AND USER OF PERMISSIONS^ [PTR] /= PWW1
@BOX 5.1
IF ACCESS OF PERMISSIONS^ [PTR] & ACC /= ACC
@BOX 6.1
END
@BOX 7.1
-45 => PW0;
@BOX 8.1
NAMES ();
-1 => PTR;
@BOX 9.1
-49 => PW0;
@END


@TITLE SYSCMD16.11(2,9)

@COL 1S-3R-4F

@FLOW 1-3-4

@BOX 1.0
END FILE REQUEST
@BOX 3.0
CHECKOUT
[SYS01]
@BOX 4.0
END
@BOX 1.1
PROC END.FILE.REQUEST;
INTEGER SAVE.PW1;
@BOX 3.1
PW1 => SAVE.PW1;
SYS14.CMD.MAP (OLD.DIR.SEG, FILE.MAPPED.SEG);
SAVE.PW1 => PW1;
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@BOX 4.1
END
@END



@TITLE SYSCMD16.12(2,11)


@COL 1S-2T-3T-4R-5T-6R-7F
@COL 11N-8N-9R-10R-12R

@ROW 2-11
@ROW 8-3
@ROW 9-6

@FLOW 1-2OK-3OK-4-5OK-6-7
@FLOW 2FAIL-11-12-7
@FLOW 3FAIL-8-10-12
@FLOW 5FAIL-9-10

@BOX 1.0
SECURE DIR
@BOX 2.0
ALLOCATE NEW DISC BLOCK
FOR COPY OF DIRECTORY
[SYS03]
@BOX 3.0
ENTER INTERRUPT LEVEL TO
SECURE COPY OF DIRECTORY
[SYSINT16.1]
@BOX 4.0
UPDATE MASTER BLOCK
@BOX 5.0
ENTER INTERRUPT LEVEL TO
SECURE COPY OF MASTER BLOCK
[SYSINT16.1]
@BOX 6.0
RELEASE SPACE OCCUPIED BY
PREVIOUS COPY OF DIRECTORY
[SYS03]
@BOX 7.0
END
@BOX 9.0
RESET MASTER BLOCK
@BOX 10.0
RELEASE DISC BLOCK FOR
NEW DIRECTORY
@BOX 12.0
RETURN FAULT STATUS -49
(DISC TRANSFER FAIL)
@BOX 1.1
PROC SECURE.DIR;
SELECT DISC.VARS [FILE.DISC];
@BOX 2.1
CURRENT.DIR.ADDR => OLD.DIR.ADDR;
SYS03.CMD.ALLOCATE.DRUM.BLOCK (FILE.DISC, CURRENT.DIR.SIZE)
   => CURRENT.DIR.ADDR => FILE.TRANSFER.ADDR;
IF PW0 /= 0
@BOX 3.1
SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 1, 2);
IF FILE.TRANSFER.STATUS /= 0
@BOX 4.1
CURRENT.DIR.ADDR => DISC.ADDR [CURRENT.DIR.UID] OF MB^;
CURRENT.DIR.SIZE => D.SIZE [CURRENT.DIR.UID] OF MB^;
1 +> GEN.NO OF MB^;
1 -=> CURRENT.MB.ADDR => FILE.TRANSFER.ADDR;
@BOX 5.1
SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 1, 0);
IF FILE.TRANSFER.STATUS /= 0
@BOX 6.1
SYS03.CHANGE.DRUM.SIZE (FILE.DISC, OLD.DIR.ADDR,
   OLD.DIR.SIZE, 0);
@BOX 7.1
END
@BOX 9.1
OLD.DIR.ADDR => DISC.ADDR [CURRENT.DIR.UID] OF MB^;
OLD.DIR.SIZE => D.SIZE [CURRENT.DIR.UID] OF MB^;
1 -> GEN.NO OF MB^;
1 -=> CURRENT.MB.ADDR;
@BOX 10.1
SYS03.CHANGE.DRUM.SIZE (FILE.DISC, CURRENT.DIR.ADDR,
   CURRENT.DIR.SIZE, 0);
@BOX 12.1
-1 => CURRENT.DIR.UID;
-49 => PW0;
@END


@TITLE SYSCMD16.13(2,9)

@COL 1S-2T-3R-6R-4F
@COL 5R

@ROW 3-5

@FLOW 1-2FOUND-3-6-4
@FLOW 2NOT FOUND-5-4

@BOX 1.0
FIND FILE ENTRY (FILENAME)
@BOX 2.0
SEARCH DIRECTORY FOR
REQUIRED FILENAME
@BOX 3.0
RETURN INDEX OF FILE
INTO DIRECTORY
@BOX 4.0
END
@BOX 5.0
RETURN FAULT STATUS -43
(FILE DOES NOT EXIST)
@BOX 6.0
RETURN INDEX INTO SFT
IF FILE OPEN
@BOX 1.1
PROC FIND.FILE.ENTRY (F.NAME);
INTEGER COUNT, SFN, FILE.NO, FILE.IDENTITY;
@BOX 2.1
NO.OF.FILES OF DIR^ [0] => COUNT;
0 => FILE.NO;
WHILE 1 +> FILE.NO =< COUNT AND
   F.NAME /= FILE.NAME OF DIR^ [FILE.NO] DO OD
IF FILE.NO > COUNT
@BOX 3.1
FILE.NO => FIND.FILE.ENTRY;
FILE.ID OF DIR^ [FILE.NO] => FILE.IDENTITY;
@BOX 4.1
END
@BOX 5.1
-43 => PW0 => FIND.FILE.ENTRY;
@BOX 6.1
-1 => SFN;
WHILE 1 +> SFN < SYS14.NO.OF.SYS.SEGS AND
   [FILE.IDENTITY /= FILE.IDENT OF SFT [SFN] OR
      FILE.DISC /= DISC.NO OF SFT [SFN]] DO OD
IF SFN => PW1 = SYS14.NO.OF.SYS.SEGS THEN
   -1 => PW1;
FI
@END


@TITLE SYSCMD16.14(2,9)

@COL 1S-2T-3R-4R-5F
@COL 6R

@ROW 3-6

@FLOW 1-2NO-3-4-5
@FLOW 2YES-6-5

@BOX 1.0
ALLOCATE FILE ENTRY
@BOX 2.0
FILE LIMIT EXCEEDED?
@BOX 3.0
ALLOCATE NEW DIRECTORY ENTRY
@BOX 4.0
COMPUTE NEW SIZE OF DIRECTORY
@BOX 5.0
END
@BOX 6.0
RETURN FAULT STATUS -41
(FILE LIMIT EXCEEDED)
@BOX 1.1
PROC ALLOCATE.FILE.ENTRY;
SELECT DISC.VARS [FILE.DISC];
@BOX 2.1
SELECT DIR^ [0];
IF FILE.DISC = 0 AND
   [NO.OF.FILES >= SYS17.GET.USER.PARAM (FILE.UID, SYS17.NO.OF.FILES) OR
   FILE.STORE.USED > SYS17.GET.USER.PARAM (FILE.UID, SYS17.FILE.STORE)]
@BOX 3.1
1 +> NO.OF.FILES => ALLOCATE.FILE.ENTRY;
@BOX 4.1
CURRENT.DIR.SIZE => OLD.DIR.SIZE;
NO.OF.FILES + 1 * DIR.ENTRY.SIZE + SYS14.PAGE.SIZE - 1
   ->> SYS14.PAGE.SHIFT => CURRENT.DIR.SIZE;
@BOX 5.1
END
@BOX 6.1
-41 => PW0 => ALLOCATE.FILE.ENTRY;
@END


@TITLE SYSCMD16.15(2,9)

@COL 1S-2R-3R-4F

@FLOW 1-2-3-4

@BOX 1.0
DELETE FILE ENTRY (FILE NO)
@BOX 2.0
RECOVER ENTRY IN
FILE DIRECTORY
@BO 3.0
COMPUTE NEW SIZE
OF DIRECTORY
@BOX 4.0
END
@BOX 1.1
PROC DELETE.FILE.ENTRY (FILE.NO);
INTEGER COUNT;
ADDR DIR.ENTRY DIR.TEMP1, DIR.TEMP2;
SELECT DISC.VARS [FILE.DISC];
@BOX 2.1
1 -> NO.OF.FILES OF DIR^ [0] => COUNT;
WHILE FILE.NO =< COUNT DO
::   DIR^ [FILE.NO + 1] => DIR^ [FILE.NO];
   ^DIR^ [FILE.NO + 1] => DIR.TEMP1;
   ^DIR^ [FILE.NO] => DIR.TEMP2;
   DIR.TEMP1^ => DIR.TEMP2^;
   1 +> FILE.NO;
OD
@BOX 3.1
CURRENT.DIR.SIZE => OLD.DIR.SIZE;
COUNT + 1 * DIR.ENTRY.SIZE + SYS14.PAGE.SIZE - 1
   ->> SYS14.PAGE.SHIFT => CURRENT.DIR.SIZE;
@BOX 4.1
END
@END


@TITLE SYSCMD16.16(2,9)

@COL 1S-5R-6F

@FLOW 1-5-6

@BOX 1.0
CLOSE FILE
@BOX 5.0
NOTE FILE CLOSED
@BOX 6.0
END
@BOX 1.1
PROC CLOSE.FILE (SSN);
@BOX 5.1
0 => FILE.IDENT OF SFT [SSN]
   => COUNT OF SFT [SSN]
   => DISC.NO OF SFT [SSN];
@BOX 6.1
END
@END


@TITLE SYSCMD16.17(2,10)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
INIT FILES (FILE VARS, UID)
@BOX 2.0
INITIALISE FILE VARIABLES
IN SPECIFIED PRB
@BOX 3.0
END
@BOX 1.1
PROC INIT.FILES (FILE.VARS, UID);
INTEGER I;
SELECT FILE.VARS^;
@BOX 2.1
UID => USER.UID => DIR.UID;
0 => DIR.TYPE;
FOR I < NO.OF.REMOTE.DIRS DO
   -1 => REMOTE.TABLE [I];
OD
FOR I < NO.OF.AUX.DIRS DO
   -1 => AUX.TABLE [I];
OD
@BOX 3.1
END
@END


@TITLE SYSCMD16.18(2,10)

@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
TINI FILES (SPN)
@BOX 2.0
RESET REMOTE DEFINITION
@BOX 3.0
END
@BOX 1.1
PROC TINI.FILES (SPN);
INTEGER I, J;
ADDR FILE.VARS C.FILE.VARS;
MAKE (FILE.VARS, 0, SYS13.GET.PRB (SPN, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
@BOX 2.1
FOR I < NO.OF.REMOTE.DIRS DO
   IF REMOTE.TABLE [I] => J >= 0 THEN
      REMOTE.FREE => REMOTE.LINK OF REMOTE.DIRS [J];
      J => REMOTE.FREE;
   FI
OD
FOR I < NO.OF.AUX.DIRS DO
   IF AUX.TABLE [I] => J >= 0 THEN
      AUX.FREE => AUX.LINK OF AUX.DIR [J];
      J => AUX.FREE;
   FI
OD
@BOX 3.1
END
@END


@TITLE SYSCMD16.19(2,11)

@COL 1S-23T-2T-3T-4T-5T-6R-13T-7T-8T-9R-10R-15N-11F
@COL 24R-17N-12T-18R-16N

@ROW 17-3
@ROW 18-8
@ROW 2-24
@ROW 5-12
@ROW 15-16

@FLOW 1-23LOCAL-2OK-3OK-4FOUND-5THIS USER-6-13NO-7OK-8OK-9-10-15-11
@FLOW 23REMOTE-24-16-15
@FLOW 3FAIL-17-18-10
@FLOW 7FAIL-18
@FLOW 8FAIL-10
@FLOW 2FAIL-10
@FLOW 5-4AT END-12OK-6
@FLOW 12NO SPACE-18
@FLOW 13YES-10

@BOX 1.0
PERMIT (FILENAME, USERNAME, ACCESS)
@BOX 2.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 3.0
READ PERMISSION FILE
@BOX 4.0
SEARCH PERMISSION FILE
FOR REQUIRED FILENAME
@BOX 5.0
ENTRY NOT FOR THIS USER
@BOX 6.0
UPDATE PERMISSION INFORMATION
@BOX 7.0
WRITE PERMISSION FILE
TO DISC
@BOX 8.0
SECURE COPY OF DIRECTORY
ON DISC
[SYSCMD16.12]
@BOX 9.0
RELEASE SPACE PREVIOUSLY
OCCUPIED BY PERMISSION FILE
@BOX 10.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 11.0
END
@BOX 12.0
ALLOCATE ENTRY IN
PERMISSION FILE
@BOX 13.0
INVALID ACCESS SPECIFIED?
@BOX 18.0
RETURN FAULT STATUS -49
(DISC TRANSFER FAILED)
@BOX 23.0
IS FILE REMOTE?
[SYSCMD16.24]
@BOX 24.0
ISSUE THE REQUIRED PERMIT
FOR THE REMOTE USER
[SYSCMD16.25]
@BOX 1.1
PROC PERMIT (FILE.N, U.NAME, ACC);
INTEGER P.SIZE, COUNT, PTR, INDEX, P.ADDR;
LOGICAL8 CH;
ADDR FILE.VARS C.FILE.VARS;
LOGICAL64 FL.NAME;
0 => PW0;
TRANSFORM.NAME(FILE.N) => FL.NAME;
@BOX 2.1
START.FILE.REQUEST (0, 0, 0);
IF PW0 /= 0
@BOX 3.1
SELECT DIR^ [0];
PERMIT.SIZE => P.SIZE;
PERMIT.ADDR => P.ADDR => FILE.TRANSFER.ADDR;
NO.OF.PERMISSIONS => COUNT;
IF COUNT > 0 THEN
   SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 0, 1);
FI
-1 => PTR;
IF COUNT > 0 AND FILE.TRANSFER.STATUS /= 0
@BOX 4.1
WHILE 1 +> PTR < COUNT AND
   FL.NAME /= F.NAME OF PERMISSIONS^ [PTR] DO OD
IF PTR = COUNT
@BOX 5.1
IF USER OF PERMISSIONS^ [PTR] /= U.NAME
@BOX 6.1
IF ACC = 0 THEN
   1 -> COUNT
   WHILE PTR < COUNT DO
      PERMISSIONS^ [PTR + 1] => PERMISSIONS^ [PTR];
      1 +> PTR;
   OD
ELSE
   SELECT PERMISSIONS^ [PTR];
   0 => ACCESS;
   FL.NAME => F.NAME;
   U.NAME => USER;
   DATAVEC ACCESS.PERMISSIONS (LOGICAL8)
   "X" "W" "R" "E" "C" "U" "D" "N"
   END
   WHILE ACC /= 0 AND PW0 = 0 DO
      ACC & %FF => CH;
      ACC ->> 8 => ACC;
      -1 => INDEX;
      WHILE 1 +> INDEX < 8 AND CH /= ACCESS.PERMISSIONS [INDEX] DO OD;
      IF INDEX < 8 THEN
         1 <<- INDEX !> ACCESS;
      ELSE
         -45 => PW0;
      FI
   OD
FI
@BOX 7.1
0 => PERMIT.SIZE;
IF COUNT => NO.OF.PERMISSIONS > 0 THEN
   SYS03.CMD.ALLOCATE.DRUM.BLOCK (FILE.DISC, 1 => PERMIT.SIZE)
      => PERMIT.ADDR => FILE.TRANSFER.ADDR;
   SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 1, 1);
FI
IF NO.OF.PERMISSIONS > 0 AND FILE.TRANSFER.STATUS /= 0
@BOX 8.1
SECURE.DIR ();
IF PW0 /= 0
@BOX 9.1
IF P.SIZE > 0 THEN
   SYS03.CHANGE.DRUM.SIZE (FILE.DISC, P.ADDR, P.SIZE, 0);
FI
@BOX 10.1
END.FILE.REQUEST ();
@BOX 11.1
END
@BOX 12.1
IF 1 +> COUNT < PERMIT.ENTRY.SIZE * SYS14.PAGE.SIZE
@BOX 13.1
IF PW0 /= 0
@BOX 18.1
-49 => PW0;
@BOX 23.1
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
IF DIR.TYPE = REM.DIR
@BOX 24.1
REMOTE.FILE.REQUEST (DIR.UID,
   5, FL.NAME, ACC, U.NAME);
@END


@TITLE SYSCMD16.20(2,10)

@COL 1S-8R-2T-3R-4T-7R-5R-6F

@FLOW 1-8-2NO-3-4FAIL-7-5-6
@FLOW 2YES-5
@FLOW 4OK-5

@BOX 1.0
GET DIR
@BOX 2.0
DIRECTORY CURRENTLY AVAILABLE?
@BOX 3.0
READ DISC ADDRESS AND
SIZE OF DIRECTORY
@BOX 4.0
ENTER INTERRUPT LEVEL TO
RETRIEVE DIRECTORY
[SYSINT16.1]
@BOX 5.0
SET POINTER TO DIRECTORY
@BOX 6.0
END
@BOX 7.0
RETURN FAULT STATUS -49
(DISC TRANSFER FAILED)
@BOX 8.0
MAP MASTER BLOCK
AND DIRECTORY
@BOX 1.1
PROC GET.DIR;
ADDR FILE.SEG.ADDR;
SELECT DISC.VARS [FILE.DISC];
@BOX 2.1
IF FILE.UID = CURRENT.DIR.UID
@BOX 3.1
FILE.UID => CURRENT.DIR.UID;
DISC.ADDR [FILE.UID] OF MB^ => CURRENT.DIR.ADDR => FILE.TRANSFER.ADDR;
D.SIZE [FILE.UID] OF MB^ => CURRENT.DIR.SIZE;
@BOX 4.1
SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 0, 2);
IF FILE.TRANSFER.STATUS = 0
@BOX 5.1
MAKE (DIR.ENTRY, CURRENT.DIR.SIZE <<- SYS14.PAGE.SHIFT / DIR.ENTRY.SIZE,
   SYS14.PAGE.SIZE + FILE.SEG.ADDR) => DIR;
CURRENT.DIR.SIZE => OLD.DIR.SIZE;
@BOX 6.1
END
@BOX 7.1
-1 => CURRENT.DIR.UID;
-49 => PW0;
@BOX 8.1
SYS14.CMD.MAP (FILE.SEG + FILE.DISC, FILE.MAPPED.SEG);
PW1 => OLD.DIR.SEG;
PW6 * SYS14.SEG.SIZE => FILE.SEG.ADDR;
MAKE (FILE.MB.ENTRY, 0, FILE.SEG.ADDR) => MB;
MAKE (PERMIT.ENTRY, SYS14.PAGE.SIZE / PERMIT.ENTRY.SIZE,
   SYS14.PAGE.SIZE +> FILE.SEG.ADDR) => PERMISSIONS;
@END


@TITLE SYSCMD16.21(2,9)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
GET MB (VERSION, DISC NO.)
@BOX 2.0
ENTER INTERRUPT LEVEL TO
READ SPECIFIED MASTER BLOCK
@BOX 3.0
END
@BOX 1.1
PROC GET.MB (VERSION, DISC.NO);
@BOX 2.1
MB.START.ADDR [DISC.NO] -= VERSION => FILE.TRANSFER.ADDR
   => CURRENT.MB.ADDR OF DISC.VARS [DISC.NO => FILE.DISC];
SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 0, 0);
IF FILE.TRANSFER.STATUS /= 0 THEN
   -49 =>PW0;
FI
@BOX 3.1
END
@END


@TITLE SYSCMD16.22(2,9)
@COL 1S-23T-2T-3T-4T-5T-6R-7R-28N-10F
@COL 24R-25R-27N

@ROW 2-24
@ROW 25-6
@ROW 27-28

@FLOW 23LOCAL-24-27-28
@FLOW 1-23LOCAL-2OK-3-4-5OK-6-7-28-10
@FLOW 2FAIL-7
@FLOW 5FAIL-25-7
@FLOW 3NONE-7
@FLOW 4FAIL-7
@BOX 1.0
CATALOGUE PERMIT
@BOX 2.0
START FILE REQUEST
[SYSCMD16.10]
@BOX 3.0
ANY ENTRY IN THE
PERMISSION FILE?
@BOX 4.0
CREATE A SEGMENT FOR
THE PERMISSION FILE
@BOX 5.0
READ PERMISSION FILE
@BOX 6.0
COPY FILE INTO SEGMENT
@BOX 7.0
END FILE REQUEST
[SYSCMD16.11]
@BOX 10.0
END
@BOX 23.0
IS FILE REMOTE?
[SYSCMD16.24]
@BOX 24.0
CATALOGUE PERMISSION FILE
FOR THE REMOTE DIRECTORY
[SYSCMD16.25]
@BOX 25.0
RETURN FAULT STATUS -49
(DISC TRANSFER FAILED)
@BOX 1.1
PROC CATALOGUE.PERMIT;
INTEGER SEG.NO, OLD.SEG.NO, I;
ADDR FILE.VARS C.FILE.VARS;
ADDR [PERMIT.ENTRY] PERMIT.COPY;
0 => PW0;
@BOX 2.1
START.FILE.REQUEST (0, 0, 0);
IF PW0 /= 0
@BOX 3.1
0 => PW1 => PW2 => PW4;
SELECT DIR^ [0];
IF NO.OF.PERMISSIONS = 0
@BOX 4.1
CREATE.SEGMENT (-1, NO.OF.PERMISSIONS * 18);
PW1 => SEG.NO;
IF PW0 /= 0
@BOX 5.1
PERMIT.ADDR => FILE.TRANSFER.ADDR;
SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 0, 1);
IF FILE.TRANSFER.STATUS /= 0
@BOX 6.1
SYS14.CMD.MAP (SEG.NO, PERMIT.MAPPED.SEG);
PW1 => OLD.SEG.NO;
MAKE (PERMIT.ENTRY, NO.OF.PERMISSIONS, PW6 * SYS14.SEG.SIZE) => PERMIT.COPY;
FOR I < NO.OF.PERMISSIONS DO
   PERMISSIONS^ [I] => PERMIT.COPY^ [I];
OD
SYS14.CMD.MAP (OLD.SEG.NO, PERMIT.MAPPED.SEG);
NO.OF.PERMISSIONS => PW1;
SEG.NO => PW2;
@BOX 7.1
END.FILE.REQUEST ();
@BOX 10.1
END
@BOX 23.1
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
IF DIR.TYPE = REM.DIR
@BOX 24.1
REMOTE.FILE.REQUEST (DIR.UID,
   6, 0, 0, 0);
@BOX 25.1
RELEASE.SEGMENT (SEG.NO);
-49 => PW0;
@END
@TITLE SYSCMD16.23(2,10)

@COL 1S-10T-2T-6R-3T-5R-15R-17N-7F
@COL 9R-16N
@COL 11T-8R-12T-13R-14N
@ROW 11-2
@ROW 5-9-13
@ROW 17-16-14
@FLOW 1-10REMOTE-2VALID-6-3OK-5-15-17-7
@FLOW 10LOCAL-11OK-8-12OK-13-15
@FLOW 2-17
@FLOW 3NONE-9-15
@FLOW 11FAIL-14-16-17
@FLOW 12FAIL-9
@BOX 1.0
REMOTE DIR (NEWNAME, USERNAME, PASSWORD, MACHINE, REMOTEUSER)
@BOX 2.0
MACHINE NAME VALID?
@BOX 3.0
SEARCH FOR AN USEABLE ENTRY
IN REMOTE DIRECTORY TABLE
@BOX 5.0
MAKE AN ENTRY IN
NEWNAME TABLE OF THE
CURRENT PROCESS
@BOX 6.0
CHECKIN
[SYS01]
@BOX 7.0
END
@BOX 8.0
CHECKIN
[SYS01]
@BOX 9.0
SET FAULT STATUS -56
(TOO MANY DEFINITIONS)
@BOX 10.0
LOCAL DIRECTORY?
@BOX 11.0
CHECK USERNAME AND PASSWORD
@BOX 12.0
SEARCH FOR USEABLE ENTRY
IN AUXILIARY DIRECTORY TABLE
@BOX 13.0
INSERT ENTRY
@BOX 15.0
CHECKOUT
[SYS01]
@BOX 1.1
PROC REMOTE.DIR (NEWNAME, USERNAME, PASSWORD, DISC.NAME, MACHINE, REMOTEUSER);
INTEGER I, J, SPN, PID, UID;
ADDR FILE.VARS C.FILE.VARS;
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
0 => PW0;
@BOX 2.1
LOOK.UP.PROCESS ("FILMAN", MACHINE);
PW1 => SPN;
PW2 => PID;
IF PW0 /= 0
@BOX 3.1
-1 => I;
WHILE 1 +> I < NO.OF.REMOTE.DIRS AND REMOTE.TABLE [I] => J >= 0
   AND N.NAME OF REMOTE.DIRS [J] /= NEWNAME DO OD
IF I = NO.OF.REMOTE.DIRS OR [J < 0 AND REMOTE.FREE < 0]
@BOX 5.1
IF J < 0 THEN
   REMOTE.FREE => REMOTE.TABLE [I] => J;
   REMOTE.LINK OF REMOTE.DIRS [J] => REMOTE.FREE;
FI
SELECT REMOTE.DIRS [J];
NEWNAME => N.NAME;
USERNAME => U.NAME;
PASSWORD => P.WORD;
DISC.NAME => DISC;
REMOTEUSER => R.USER;
MACHINE => M.NAME;
SPN => DEST [0];
PID => DEST [1];
%8 => DEST [2];
0 => DEST [3];
-1 => I;
WHILE 1 +> I < NO.OF.AUX.DIRS AND
   AUX.TABLE [I] => J >= 0 AND
   AUX.DIR.NAME OF AUX.DIR [J] /= NEW.NAME DO OD
IF I /= NO.OF.AUX.DIRS AND J >= 0 THEN
   0 => AUX.DIR.NAME OF AUX.DIR [J];
FI
@BOX 6.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 7.1
END
@BOX 8.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 9.1
-56 => PW0;
@BOX 10.1
IF MACHINE = 0
@BOX 11.1
FIND.U (USERNAME,PASSWORD);
IF PW0 /= 0
@BOX 12.1
PW1 =>UID;
-1 => I;
WHILE 1 +> I < NO.OF.AUX.DIRS AND
   AUX.TABLE [I] => J >= 0 AND
   AUX.DIR.NAME OF AUX.DIR [J] /= NEW.NAME DO OD
IF I = NO.OF.AUX.DIRS OR [J < 0 AND AUX.FREE < 0]
@BOX 13.1
IF J < 0 THEN
   AUX.FREE => AUX.TABLE [I] => J;
   AUX.LINK OF AUX.DIR [J] => AUX.FREE;
FI
SELECT AUX.DIR [J];
NEW.NAME => AUX.DIR.NAME;
UID => AUX.UID;
DISC.NAME => AUX.DISC.NAME;
-1 => I;
WHILE 1 +> I < NO.OF.REMOTE.DIRS AND
   REMOTE.TABLE [I] => J >= 0 AND
   N.NAME OF REMOTE.DIRS [J] /= NEWNAME DO OD
IF I /= NO.OF.REMOTE.DIRS AND J >= 0 THEN
   0 => N.NAME OF REMOTE.DIRS [J];
FI
@BOX 15.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@END
@TITLE SYSCMD16.24(2,10)

@COL 1S-9T-12T-13R-20N-5F
@COL 22N-10R-17R-21N
@ROW 9-22
@ROW 13-17
@ROW 20-21
@FLOW 1-9SPECIFIED-12FOUND-13-20-5
@FLOW 9-22-10-21-20
@FLOW 12-17-21
@BOX 1.0
CHECK REMOTE (NAME)
@BOX 5.0
END
@BOX 9.0
IS NAME UNSPECIFIED?
@BOX 10.0
RETURN THE CURRENT REMOTE
DIRECTORY INDEX
@BOX 12.0
IS NAME PREVIOUSLY DECLARED
IN A REMOTE DIR COMMAND?
@BOX 13.0
NOTE THE INDEX OF THE
REMOTE DEFINITION
@BOX 17.0
NOTE LOCAL
@BOX 1.1
PROC CHECK.REMOTE (NAME);
INTEGER I, J;
ADDR FILE.VARS C.FILE.VARS;
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
@BOX 5.1
END
@BOX 9.1
IF NAME = 0
@BOX 10.1
IF DIR.TYPE = REM.DIR THEN
   DIR.UID => CHECK.REMOTE;
ELSE
   -1 => CHECK.REMOTE;
FI
@BOX 12.1
-1 => I;
WHILE 1 +> I < NO.OF.REMOTE.DIRS AND
   REMOTE.TABLE [I] => J >= 0 AND
   N.NAME OF REMOTE.DIRS [J] /= NAME DO OD
IF I = NO.OF.REMOTE.DIRS OR J < 0
@BOX 13.1
J => CHECK.REMOTE;
@BOX 17.1
-1 => CHECK.REMOTE;
@END
@TITLE SYSCMD16.25(2,10)

@COL 1S-4R-5R-15N-16T-6R-7T-17R-11F
@COL 20N-21N-12T-13R
@ROW 15-20
@ROW 16-21
@FLOW 1-4-5-15-16NO REPLY-21-12-13-20-15
@FLOW 12-11
@FLOW 16O.K.-6-7NO-17-11
@FLOW 7YES-11
@BOX 1.0
REMOTE FILE REQUEST (CMD.INDEX, FILENAME, VAR1, VAR2)
@BOX 4.0
DISCARD ANY MESSAGE ON CHANNEL 7
DEDICATE CHANNEL 7 FOR REPLY
@BOX 5.0
PREPARE THE
MESSAGE BUFFER
@BOX 6.0
WAIT FOR REPLY
@BOX 7.0
READ REPLY OK?
@BOX 11.0
END
@BOX 12.0
IDENTIFY THE NEW
"FILMAN" PROCESS
@BOX 13.0
RECORD THE NEW
SPN AND PID
@BOX 16.0
SEND MESSAGE TO THE
FILE MANAGER OF THE
SPECIFIED MACHINE
@BOX 17.0
LOAD REMOTE PW'S
@BOX 1.1
PROC REMOTE.FILE.REQUEST (REMOTE.DIR.NO, CMD.INDEX, FILENAME, VAR1, VAR2);
INTEGER REC.SEG, I, J, K, SEG.NUMBER, SEG.STATUS;
ADDR SEG.SIZE;
ADDR FILE.VARS C.FILE.VARS;
INTEGER [4] DESTIN;
LOGICAL8 [80] MESS;
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
@BOX 4.1
SELECT REMOTE.DIRS [REMOTE.DIR.NO];
1 +> DEST [3];
SET.CH.STATUS (7, 6, DEST [1], DEST [3]);
WHILE PW0 = 0 DO
   READ.MESSAGE (^MESS, ^DESTIN, 7, -1);
   IF PW0 = 0 AND PW1 /= 0 THEN
      RELEASE.SEGMENT (PW1);
   FI
OD
@BOX 5.1
6 => MESS [0];
56 => MESS [1];
0 => MESS [2] => MESS [3] => MESS [4]
   => MESS [5];
FOR J < 8 DO
   8 * J => K;
   U.NAME ->> K => MESS [J + 6];
   P.WORD ->> K => MESS [J + 14];
   DISC ->> K => MESS [J + 22];
   R.USER ->> K => MESS [J + 30];
   CMD.INDEX ->> K => MESS [J + 38];
   FILENAME ->> K => MESS [J + 46];
   VAR1 ->> K => MESS [J + 54];
   VAR2 ->> K => MESS [J + 62];
OD
IF CMD.INDEX /= 1 THEN
   VAR2 => REC.SEG;
   0 => VAR2;
   %1E => VAR1;
ELSE
   READ.SEGMENT.STATUS (VAR2);
   PW2 & %1F => VAR1;
FI
@BOX 6.1
WAIT (%80, 12000);
@BOX 7.1
IF CMD.INDEX /= 0 THEN
   -1 => REC.SEG;
FI
READ.MESSAGE (^MESS, ^DESTIN, 7, REC.SEG);
IF PW0 /= 0
@BOX 11.1
END
@BOX 12.1
LOOK.UP.PROCESS ("FILMAN", M.NAME);
IF PW0 /= 0
@BOX 13.1
PW1 => DEST [0];
PW2 => DEST [1];
SET.CH.STATUS (7, 6, DEST [1], DEST [3]);
@BOX 16.1
FOR I < 4 DO
   DEST [I] => DESTIN [I];
OD
SEND.MESSAGE (^MESS, ^DESTIN, %F, DEST [3], VAR2, VAR1);
IF PW0 /= 0
@BOX 17.1
PW1 => SEG.NUMBER;
PW2 => SEG.SIZE;
PW3 => SEG.STATUS;
FOR J < 4 DO
   PW0 <<- 8 ! MESS [9 - J] => PW0;
   PW1 <<- 8 ! MESS [13 - J] => PW1;
   PW2 <<- 8 ! MESS [17 - J] => PW2;
   PW3 <<- 8 ! MESS [21 - J] => PW3;
   PW4 <<- 8 ! MESS [25 - J] => PW4;
   PW5 <<- 8 ! MESS [29 - J] => PW5;
OD
IF CMD.INDEX = 0 THEN
   SEG.NUMBER => PW1;
   SEG.SIZE => PW2;
   SEG.STATUS => PW3;
ELSE
   IF CMD.INDEX = 4 OR CMD.INDEX = 6 THEN
      SEG.NUMBER => PW2;
   FI
FI
@END

@TITLE SYSCMD16.26(2,9)
@COL 1S-2R-3T-4R-5R-6F
@FLOW 1-2-3OK-4-5-6
@FLOW 3FAIL-5
@BOX 1.0
DELETE USER DIR (UID)
@BOX 2.0
CHECKIN
[SYS01]
@BOX 3.0
GET DIRECTORY FOR SPECIFIED USER
[SYSCMD16.20]
@BOX 4.0
RETURN FAULT IF USER HAS FILE(S)
@BOX 5.0
CHECKOUT
[SYS01]
@BOX 6.0
END
@BOX 1.1
PROC DELETE.USER.DIR (UID);
INTEGER OLD.DIR.SEG;
@BOX 2.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 3.1
UID => FILE.UID;
0 => FILE.DISC;
GET.DIR ();
IF PW0 /= 0
@BOX 4.1
PW1 => OLD.DIR.SEG;
IF NO.OF.FILES OF DIR^ [0] = 0 THEN
   0 => DELETE.USER.DIR;
ELSE
   -1 => DELETE.USER.DIR;
FI
@BOX 5.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@BOX 6.1
END
@END

@TITLE SYSCMD16.27(2,10)

@COL 1S-4T-5T-2R-3F
@COL 6R

@ROW 6-2

@FLOW 1-4PRIVILEGED-5NO-2-3
@FLOW 4UNPRIVILEGED-3
@FLOW 5YES-6-3

@BOX 1.0
INIT DISC (DISC NO, DISC NAME, MODE)
@BOX 2.0
NOTE NAME AND INITIALISATION
REQUEST
@BOX 3.0
END
@BOX 4.0
USER UNPRIVILEGED?
@BOX 5.0
DISC NUMBER OUT OF RANGE
@BOX 6.0
RETURN FAULT STATUS -51
(DISC NUMBER OUT OF RANGE)
@BOX 1.1
PROC INIT.DISC (DISC.NO, D.NAME, INIT.TYPE);
SELECT DISC.VARS [DISC.NO];
0 => PW0;
@BOX 2.1
DISC.INIT ! DISC.NAME.CHANGE & (INIT.TYPE <<- 2)
    ! TEMP.DISC.NAME !> DISC.STATE;
D.NAME => DISC.NAME;
@BOX 3.1
END
@BOX 4.1
SYS13.CHECK.PRIV ();
IF PW0 /= 0
@BOX 5.1
IF DISC.NO < 0 OR DISC.NO >= SYS03.NO.OF.DISCS
@BOX 6.1
-51 => PW0;
@END
@TITLE SYSCMD16.28(2,11)

@COL 1S-2T-3T-4R-7R-6F

@FLOW 1-2NO-3NO-4-7-6
@FLOW 2YES-7
@FLOW 3YES-7

@BOX 1.0
CREATE FILE SEGMENT (SEG NO., SEG SIZE, FILENAME, DIRECTORY NAME)
@BOX 2.0
REMOTE DIRECTORY?
@BOX 3.0
SYSTEM DIRECTORY?
@BOX 4.0
GET DISC NUMBER
[SYSCMD16.31]
@BOX 6.0
END
@BOX 7.0
CREATE SEGMENT
@BOX 1.1
PROC CREATE.FILE.SEGMENT (SEG.NO, SEG.SIZE, PATH.NAME, DIR.NAME);
INTEGER DISC.NO, SSN, TEMP;
LOGICAL64 FILE.NAME;
0 => PW0;
TRANSFORM.NAME (PATH.NAME) => FILE.NAME;
@BOX 2.1
0 => DISC.NO;
IF CHECK.REMOTE (DIR.NAME) >= 0
@BOX 3.1
IF CHECK.AUX (DIR.NAME) < 0
@BOX 4.1
GET.DISC.NO (PWW1) => DISC.NO;
IF PW0 /= 0 THEN
   0 => DISC.NO;
FI
@BOX 6.1
END
@BOX 7.1
SYS14.CREATE.DISC.SEGMENT (SEG.NO, SEG.SIZE, DISC.NO);
@END
@TITLE SYSCMD16.29(2,11)

@COL 1S-2T-3T-4R-7R-6F

@FLOW 1-2NO-3NO-4-7-6
@FLOW 2YES-7
@FLOW 3YES-7

@BOX 1.0
CREATE FILE X SEGMENT (SEG SIZE, FILENAME, DIRECTORY NAME)
@BOX 2.0
REMOTE DIRECTORY?
@BOX 3.0
SYSTEM DIRECTORY?
@BOX 4.0
GET DISC NUMBER
[SYSCMD16.31]
@BOX 6.0
END
@BOX 7.0
CREATE X SEGMENT
@BOX 1.1
PROC CREATE.FILE.X.SEGMENT (SEG.SIZE, PATH.NAME, DIR.NAME);
INTEGER DISC.NO, SSN, TEMP, SEG.TYPE;
LOGICAL64 FILE.NAME;
0 => PW0;
TRANSFORM.NAME (PATH.NAME) => FILE.NAME;
@BOX 2.1
0 => DISC.NO;
IF CHECK.REMOTE (DIR.NAME) >= 0
@BOX 3.1
IF CHECK.AUX (DIR.NAME) < 0
@BOX 4.1
GET.DISC.NO (PWW1) => DISC.NO;
IF PW0 /= 0 THEN
   0 => DISC.NO;
FI
@BOX 6.1
END
@BOX 7.1
SYS14.CREATE.DISC.X.SEGMENT (SEG.SIZE, DISC.NO);
@END
@TITLE SYSCMD16.30(2,10)

@COL 1S-2T-3T-4R-9N-5F
@COL 6T-7R-8N

@ROW 6-3
@ROW 8-9

@FLOW 1-2NO-3FOUND-4-9-5
@FLOW 2YES-6NO-7-4
@FLOW 3FAIL-9
@FLOW 6YES-8-9-5

@BOX 1.0
CHECK AUX (DIRECTORY NAME)
@BOX 2.0
CURRENT DIRECTORY REQUIRED?
@BOX 3.0
SEARCH FOR DIRECTORY NAME
@BOX 4.0
RETURN INDEX, UID AND
DISC NAME
@BOX 5.0
END
@BOX 6.0
WRONG DIRECTORY TYPE?
@BOX 7.0
NOTE AUXILIARY DIRECTORY NUMBER
@BOX 1.1
PROC CHECK.AUX (DIR.NAME);
INTEGER I, AUX.DIR.NO, TEMP;
ADDR FILE.VARS C.FILE.VARS;
MAKE (FILE.VARS, 0, SYS13.GET.PRB (-1, 16)) => C.FILE.VARS;
SELECT C.FILE.VARS^;
-1 => CHECK.AUX;
@BOX 2.1
IF DIR.NAME = 0
@BOX 3.1
-1 => I;
WHILE 1 +> I < NO.OF.AUX.DIRS AND
   AUX.TABLE [I] => AUX.DIR.NO >= 0 AND
   AUX.DIR.NAME OF AUX.DIR [AUX.DIR.NO] /= DIR.NAME DO OD
IF I = NO.OF.AUX.DIRS OR AUX.DIR.NO < 0
@BOX 4.1
AUX.DIR.NO => CHECK.AUX;
AUX.UID OF AUX.DIR [AUX.DIR.NO] => PW1;
AUX.DISC.NAME OF AUX.DIR [AUX.DIR.NO] => PWW1;
@BOX 5.1
END
@BOX 6.1
IF DIR.TYPE /= AUXIL.DIR
@BOX 7.1
DIR.UID => AUX.DIR.NO;
@END
@TITLE SYSCMD16.31(2,10)

@COL 1S-6T-2T-3R-4F
@COL 5R

@ROW 5-3

@FLOW 1-6NO-2OK-3-4
@FLOW 6YES-4
@FLOW 2FAIL-5-4
@BOX 1.0
GET DISC NO (DISC NAME)
@BOX 2.0
FIND DISC
@BOX 3.0
RETURN DISC NUMBER
@BOX 4.0
END
@BOX 5.0
RETURN FAULT STATUS -52
(DISC UNAVAILABLE)
@BOX 6.0
IS DISC NAME ZERO?
@BOX 1.1
PROC GET.DISC.NO (D.NAME);
INTEGER DISC.NO;
0 => PW0 => GET.DISC.NO;
@BOX 2.1
-1 => DISC.NO;
WHILE 1 +> DISC.NO < SYS03.NO.OF.DISCS AND
   [DISC.STATE OF DISC.VARS [DISC.NO] & DISC.ONLINE = 0
      OR DISC.NAME OF DISC.VARS [DISC.NO] /= D.NAME] DO OD
IF DISC.NO = SYS03.NO.OF.DISCS
@BOX 3.1
DISC.NO => GET.DISC.NO;
@BOX 4.1
END
@BOX 5.1
-52 => PW0;
@BOX 6.1
IF D.NAME = 0
@END
@TITLE SYSTSK16.1(2,10)

@COL 1S-11R-12T-13R-17R-16T-14R-2R-3R-4T-5R-6R-7R-8T-9R
@COL 15R-10F

@ROW 15-13

@FLOW 1-11-12FOUND-13-17-16NORMAL-2-3-4-5-6-7-8-9-8AT END-4AT END-12
@FLOW 12FINISHED-15-10
@FLOW 16INITIAL-14-12

@BOX 1.0
FILE TASK
@BOX 2.0
SELECT CURRENT MASTER BLOCK
@BOX 3.0
RESERVE DISC SPACE
FOR MASTER BLOCKS
[SYS03]
@BOX 4.0
FOR ALL USERS
@BOX 5.0
GET DIRECTORY
[SYSCMD16.20]
@BOX 6.0
RESERVE DISC SPACE
FOR DIRECTORY
[SYS03]
@BOX 7.0
RESERVE DISC SPACE FOR
PERMISSION FILE
[SYS03]
@BOX 8.0
FOR ALL FILES
IN DIRECTORY
@BOX 9.0
RESERVE DISC SPACE
FOR FILE
[SYS03]
@BOX 10.0
END
@BOX 11.0
CHECK IN
[SYS01]
@BOX 12.0
FIND DISC REQUESTING TASK
@BOX 13.0
CLEAR TASK REQUEST
@BOX 14.0
INITIALISE DISC
@BOX 15.0
CHECK OUT
[SYS01]
@BOX 16.0
NORMAL TASK?
(NO INITIALISATION)
@BOX 17.0
INITIALISE FILE DATA
STRUCTURES IF DISC 0
@BOX 1.1
PROC FILE.TASK;
INTEGER USER, FILE, FILE.IDENT, FILE.SIZES, DISC.NO, GENERATION;
@BOX 2.1
MAP (DISC.NO => FILE.DISC + FILE.SEG, FILE.MAPPED.SEG, 0);
MAKE (FILE.MB.ENTRY, 0, PW6 * SYS14.SEG.SIZE) => MB;
GET.MB (0, DISC.NO);
GEN.NO OF MB^ => GENERATION;
GET.MB (1, DISC.NO);
IF GEN.NO OF MB^ < GENERATION THEN
   GET.MB (0, DISC.NO);
FI
IF DISC.STATE & DISC.NAME.CHANGE /= 0 THEN
   DISC.NAME => MB.DISC.NAME OF MB^;
   1 +> GEN.NO OF MB^;
   1 -=> CURRENT.MB.ADDR => FILE.TRANSFER.ADDR;
   SYS13.ENTER.INT.LEVEL (^FILE.TRANSFER, 1, 0);
FI
IF DISC.STATE & TEMP.DISC.NAME = 0 THEN
   MB.DISC.NAME OF MB^ => DISC.NAME;
FI
@BOX 3.1
SYS03.RESERVE.DRUM.SPACE (DISC.NO, MB.START.ADDR [DISC.NO], 2);
-1 => USER => CURRENT.DIR.UID;
@BOX 4.1
IF 1 +> USER >= NO.OF.DIRS
@BOX 5.1
USER => FILE.UID;
GET.DIR ();
@BOX 6.1
SYS03.RESERVE.DRUM.SPACE (DISC.NO, CURRENT.DIR.ADDR, CURRENT.DIR.SIZE);
@BOX 7.1
SYS03.RESERVE.DRUM.SPACE (DISC.NO, PERMIT.ADDR OF DIR^ [0], PERMIT.SIZE OF DIR^
[0]);
NO.OF.FILES OF DIR^ [0] => FILE;
@BOX 8.1
IF FILE =< 0
@BOX 9.1
SYS14.RESERVE.SEG (DISC.ADDR OF DIR^ [FILE], DISC.NO,
   F.SIZE OF DIR^ [FILE], STATUS OF DIR^ [FILE]);
1 -> FILE;
@BOX 10.1
END
@BOX 11.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKIN, 0, 0);
@BOX 12.1
-1 => DISC.NO;
WHILE 1 +> DISC.NO < SYS03.NO.OF.DISCS AND
   DISC.STATE OF DISC.VARS [DISC.NO] & DISC.TASK.REQUEST = 0 DO OD
IF DISC.NO = SYS03.NO.OF.DISCS
@BOX 13.1
SELECT DISC.VARS [DISC.NO];
DISC.TASK.REQUEST -=> DISC.STATE;
@BOX 14.1
INIT.FILE.DISC (DISC.NO, DISC.NAME);
DISC.INIT -=> DISC.STATE;
@BOX 15.1
MAP (0, FILE.MAPPED.SEG, 0);
SYS13.ENTER.INT.LEVEL (^SYS01.CHECKOUT, 0, 0);
@BOX 16.1
IF DISC.STATE & DISC.INIT = 0
@BOX 17.1
IF DISC.NO = 0 THEN
   NO.OF.SYS.REMOTE.DIRS - 1 => REMOTE.FREE;
   -1 => REMOTE.LINK OF REMOTE.DIRS [REMOTE.FREE];
   WHILE REMOTE.FREE /= 0 DO
      REMOTE.FREE => REMOTE.LINK OF REMOTE.DIRS [1 -> REMOTE.FREE];
   OD
   NO.OF.SYS.AUX.DIRS - 1 => AUX.FREE;
   -1 => AUX.LINK OF AUX.DIR [AUX.FREE];
   WHILE AUX.FREE /= 0 DO
      AUX.FREE => AUX.LINK OF AUX.DIR [1 -> AUX.FREE];
   OD
FI
@END


@TITLE SYSTSK16.2(2,9)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
INIT FILE TASK
@BOX 2.0
INITIALISE SYSTEM DISC
@BOX 3.0
END
@BOX 1.1
PROC INIT.FILE.TASK;
@BOX 2.1
INIT.FILE.DISC (0, "SYSTEM");
@BOX 3.1
END
@END

@TITLE SYSTSK16.3(2,9)

@COL 1S-2R-3R-4T-5R
@COL 6F

@ROW 5-6

@FLOW 1-2-3-4-5-4AT END-6

@BOX 1.0
INIT FILE DISC (DISC NO., DISC NAME)
@BOX 2.0
INITIALISE MASTER BLOCK
@BOX 3.0
CREATE INITIAL DIRECTORY
@BOX 4.0
FOR ALL USERS
@BOX 5.0
SECURE DIRECTORY
[SYSCMD16.12]
@BOX 6.0
END
@BOX 1.1
PROC INIT.FILE.DISC (DISC.NO, D.NAME);
INTEGER USER;
ADDR FILE.SEG.ADDR;
@BOX 2.1
SELECT DISC.VARS [DISC.NO];
DISC.NO => FILE.DISC;
MAP (FILE.SEG + FILE.DISC, FILE.MAPPED.SEG, 0);
PW6 * SYS14.SEG.SIZE => FILE.SEG.ADDR;
MAKE (FILE.MB.ENTRY, 0, FILE.SEG.ADDR) => MB;
MAKE (DIR.ENTRY, 1, SYS14.PAGE.SIZE * 2 + FILE.SEG.ADDR) => DIR;
FOR USER < NO.OF.DIRS DO
   0 => DISC.ADDR [USER] OF MB^;
   0 => D.SIZE [USER] OF MB^;
OD
0 => GEN.NO OF MB^;
D.NAME => MB.DISC.NAME OF MB^;
MB.START.ADDR [DISC.NO] => CURRENT.MB.ADDR;
SYS03.RESERVE.DRUM.SPACE (DISC.NO, MB.START.ADDR [DISC.NO], 2);
@BOX 3.1
SELECT DIR^ [0];
0 => NO.OF.FILES => FILE.STORE.USED => NO.OF.PERMISSIONS => PERMIT.SIZE;
0 => PERMIT.ADDR;
-1 => USER => CURRENT.DIR.UID;
@BOX 4.1
IF 1 +> USER >= NO.OF.DIRS
@BOX 5.1
USER => CURRENT.DIR.UID;
0 => OLD.DIR.SIZE => OLD.DIR.ADDR;
1 => CURRENT.DIR.SIZE;
SECURE.DIR ();
@BOX 6.1
MAP (0, FILE.MAPPED.SEG, 0);
END
@END



