@NewPage @Section(LIST OF THE FILESTORES) @SeeAlso(Primary="Directory",Other="Filestores") @SeeAlso(Primary="Dictionary",Other="Filestores") The names (as known by EFTP and L) of the filestores are as below. @Begin(FileExample, LeftMargin +0) Name Ether Address @Index(Vax)@Index(Alpha)@Index(Bravo)@Index(Charlie)@Index(Portable) @SeeAlso(Primary="Vax",Other="Filestores") @SeeAlso(Primary="Charlie",Other="Filestores") @SeeAlso(Primary="Alpha",Other="Filestores") @SeeAlso(Primary="Portable",Other="Filestores") @SeeAlso(Primary="Bravo",Other="Filestores") @IndexSecondary(Primary="Filestores", Secondary="Portable") @IndexSecondary(Primary="Filestores", Secondary="Charlie") @IndexSecondary(Primary="Filestores", Secondary="Bravo") @IndexSecondary(Primary="Filestores", Secondary="Alpha") @IndexSecondary(Primary="Filestores", Secondary="Vax") Vax 72 ECSVAX running a FS server process. Bravo 15 APM with 1Mb of memory and a 300 Mb disk. Charlie 1B Portable 3F (the mini-filestore) @end(Fileexample) The names may be abbreviated to just one letter, e.g. B is the same as Bravo, V is the same as Vax, etc. @NewPage @Section(THE FILESTORE AND THE NETWORK) @SubSection(Hardware configuration) The filestores are based around a 1Mb APM, with the standard RS232 (control console) and ether interfaces, together with a purpose-built SMD disc interface. A mini-filestore has also been configured, using a small (16Mb) Winchester disc. All communication with clients proceeds via the ether. No provision is made in the hardware for lineprinter support, as it is assumed that any printers attached to a filestore will have sufficient intelligence to communicate in the same way as would any other client (software hooks are provided, however). @Begin(FileExample, Group, LeftMargin +2) < > < > _________________________________ < | | > | |_______ < | | | > | | ether | #< | APM | |- -|_| | |station| < | |_______| > | | < |_________________________________| > < > ___________________ > | | e.| #< | c l i e n t | s.|-----|_| |_______________|___| < > @End(FileExample) @NewPage @Section(OVERVIEW OF FACILITIES) @IndexSecondary(Primary="Filestores", Secondary="Facilities") @SubSection(Mode of operation) The other machines to which the filestore is connected are known as clients. Some clients are in the nature of wholesalers handling the file transfers of many users simultaneously. These are normally multi-user operating systems relying in whole, or in part, on the filestore for file capability. Other clients only support a single user. @IndexSecondary(Primary="Filestores", Secondary="Client") @IndexSecondary(Primary="Filestores", Secondary="User") Note the distinction between client and user: clients are machines and users are people. @IndexSecondary(Primary="Filestores", Secondary="Functions") The various functions that the filestore can perform have been broken down into atomic operations, each of which is invoked by a single request from a client. Every request provokes a response from the filestore which is directed to the requesting client. Once a request has been received, no further requests are accepted from that client until the related response has been transmitted, so that the request/response sequence forms the basic unit of client-filestore communication. Note that all activity is initiated by clients; the filestore is a passive server. @IndexSecondary(Primary="Filestores", Secondary="Request") Each request consists of a command line, followed, in the case of Write-block requests only, by a sequence of data bytes. The command line specifies the operation which the client requires and whatever parameters are needed for that operation. Responses are either successful responses or failure responses. A failure response is a line containing an error-code and a text message indicating the reason for the failure. A successful response consists of an acknowledgement line, followed, in the case of Read operations only, by a sequence of data bytes. In the simplest case the acknowledgement line is a blank line, since all that requires to be signalled is the satisfactory completion of the requested operation. In other cases it conveys a number of result values to the client. The characters making up command and acknowledgement lines are printable ISO characters, in the interests of ease of transmission and reproduction, but the formats of commands and responses are designed for machine generation and would not be particularly convenient for direct use. The characters occurring in sequences of data bytes are arbitrary 8-bit values. @SubSection(Organisation of disk space) @IndexSecondary(Primary="Filestores", Secondary="Disk space") The basic unit of disk space is the block of 512 bytes. The total available space on each disk (less a small amount used by the filestore system itself) is divided into fixed areas called partitions in such a way that they are no larger than can be addressed by 16 bits. All allocated disk space is in the form of files. Each allocated block is in exactly one file, and each file is totally contained in a single partition. The space allocated to a file consists of a number of areas of adjacent blocks called extents. Files are created by opening a file for sequential output (Openw) and writing data to it. An initial extent is allocated when the file is opened, and further extents are allocated as the need arises. Any unused blocks overallocated in the final extent are released when the file is closed. The data is always written into newly allocated blocks; any existing file of the same name is not overwritten, but is deleted when (and if) the new file is successfully closed. @SubSection(Owners and directories) @IndexSecondary(Primary="Filestores", Secondary="Owners") Most owners are simply the people who are entitled to keep files on the filestore, but some owners represent libraries of related files. It is not necessary to be an owner to use files (only to create them). Each owner is identified by a unique ownername and the filestore maintains a register of these ownernames and their quotas, fixed personal limits which their total allocation of disk space should not exceed. Each file is owned by exactly one owner. @IndexSecondary(Primary="Filestores", Secondary="Directory") For each owner the filestore maintains a directory giving details of all the files for that owner. There is a one-to-one correspondence between owners and directories. Note the distinction between owners and users; a user is anyone currently using the filestore and may or may not also be an owner. However, it is not possible to log on to the filestore except as one of the owners. @SubSection(Security and permissions) It is fundamental to the filestore design that it should in principle be possible for any user to have access to any file in the system, so that flexible sharing of data is possible. Equally it is essential that controls should be provided so that an owner may exclude or restrict access to some or all of their files by other users, and sometimes also, for peace of mind, by themselves. @IndexSecondary(Primary="Filestores", Secondary="Protection") The protection mechanism is based on two concepts: the level of authority exercised by a user and the access permissions associated with an individual file. Authority is established in only one way: by presenting a password to be matched against the password which is associated with each directory. This matching is performed whenever any use is to be made of a directory. If the match succeeds, the user involved is said to have owner-authority with respect to that directory; if not, to have only public-authority. Some operations require owner-authority in themselves, for example creating and deleting files in a directory and in particular logging-on as the owner, so that in these cases a failure in password matching results in rejection of the request. However access to individual files may or may not be permitted to all and sundry (users with public-authority), depending on the access permissions set for the files individually. Each file has associated with it two permissions corresponding to the two levels of authority. These can each be at one of three levels, though they are constrained so that the owner-permission is no stricter than the public-permission. The three levels of permission are Full, Read and None. Full permission allows the file to be read, modified, and, if the user has owner authority, deleted. Read permission allows the file to be read. None allows no access at all. The original permissions set on a new file are normally those established as the defaults for the directory in which it is created, but they may subsequently be altered (see Permit and Openw below). Only a user with owner-authority may alter the permissions of a file or the default permissions. By logging on successfully, a user establishes owner-authority with respect to their own directory. The logon password is set as the active password to be used in determining authority with respect to other directories, so that the user may also enjoy owner-authority with respect to these. There is a command (Quote) to alter the active password to something other than the user's own logon password; this does not involve loss of owner-authority with respect to the user's own directory. @IndexSecondary(Primary="Filestores", Secondary="Passwords") Passwords may consist of any sequence of characters whatsoever, with the exception of newline and comma. The parity bit is significant at present. Upper case and lower case 0-parity letters are deemed to be equivalent. Passwords are limited in length to about 245 characters. A null directory password does not match anything for login: a null password must be supplied. @SubSection(File naming and file types) @IndexSecondary(Primary="Filestores", Secondary="Filenames") @IndexSecondary(Primary="File", Secondary="Names") Owners give files filenames, which must be unique amongst their own files. Hence an ownername together with a filename completely identifies a file within the system. Ownernames and filenames are constructed form sequences of letters, digits, dots, underlines and dollars, with no restriction as to the order. Ownernames must be at least one and no more than six characters long. Ownernames are allocated administratively and are not chosen by the owner. The following are valid owner names: @Begin(FileExample) ABC _KLM2 MAIN.T IMP @End(FileExample) Filename must be no more then twelve characters long. In a number of client systems, the period may have the significance of separating an extension from a root filename, but the concept of extension has no meaning to the filestore. Also, some clients may in various ways restrict the range of filenames available to the user. Null filenames and filenames beginning with the special character ' ' will be uniquefied to guarantee that there are no other files of the same name currently in the directory. The following are valid filenames to the filestore: @Begin(FileExample) A LONGFILENAME .LAYOUT.XI CAT.DOG.COW $LIST $T $WORK.1 @End(FileExample) A full filename consists of an ownername, a colon and a filename. However there is always a default ownername in force for each user logged on to the filestore, so that in the majority of cases when a file is being identified, the ownername (and the colon) can be omitted. Typically the default is the ownername of the logged-on user, but it can be changed. The following are all valid full filenames: @Begin(FileExample) SYS:LOADER.B ABC:IMP030277 WILSON:DIRECTORY.D KLM2:$LIST KLM2: @End(FileExample) @IndexSecondary(Primary="File", Secondary="Temporary") @IndexSecondary(Primary="File", Secondary="Permanent") Files are either permanent or temporary, the choice being open to the user, as indicated by the form of filename selected. A temporary filename is beginning with a dollar-sign. Most files are permanent files; once in existence they remain until deleted. The space which they occupy is deducted from the owner's quota. Temporary files remain in existence only as long as the owner is logged-on to the filestore; they are deleted automatically on logoff. However, the space that they use is not deducted from the owner's quota and so there is an essentially unlimited amount of workspace available. Because temporary files only exist whilst their owners are logged-on to the filestore, only the owner may create them, although they are accessible to other users while they continue to exist. It is an important feature of the filestore design that an owner may be logged-on to the filestore several times over; temporary files are only deleted at the final logoff, when the owner ceases to be logged-on at all. @SubSection(Directory information) The directory associated with each owner contains details of each of the files belonging to that owner. These details are recorded in file-slots within the directory and details of each extent occupied by the file are recorded in extent-slots. The maximum number of files (F) and extents (E) is limited according to the formula: 4F + E <= 500. Thus for an average of two extents per file, the directory can accommodate about 80 files. @IndexSecondary(Primary="Filestores", Secondary="Directory information") Associated with each file-slot are the file-name, some usage information, the datestamp, and the attributes. The datestamp gives the date and time (to the nearest minute) when the file was last modified. The attributes comprise the file permissions (described above) and an archive-status which is either Archive or Vulnerable. Files with Archive set are automatically stored on archive if they have been altered since the last archiving period. Files which have not been used for a period (to be decided) will be automatically deleted. When attributes are specified in commands or in file-information responses, they are given in the order: Owner permission, Public permission and Archive status, using the initial letter of the appropriate attribute value (F,R,N for permissions and A,V for archive status). @Begin(FileExample) Example: "FRV" denotes: Owner permission - Full; Public permission - Read; Archive status - Vulnerable. @End(FileExample) @IndexSecondary(Primary="Filestores", Secondary="DIRECTORY") The special file DIRECTORY "contains" the names of all the files in a directory; either the Finfo ('F') or the Ninfo ('N') command should be used if more information is required. @SubSection(Transient and subliminal files) @IndexSecondary(Primary="Filestores", Secondary="Transient file") @IndexSecondary(Primary="Filestores", Secondary="Subliminal file") @IndexSecondary(Primary="File", Secondary="Transient") @IndexSecondary(Primary="File", Secondary="Subliminal") A file which is in the process of being created by sequential writing is termed a transient file. When and if written successfully, it ceases to be transient. If for any reason, such as a crash in the client system, writing is not completed normally but the transaction is abandoned, the file remains in the transient state, with the content being whatever data had been written to it before abandonment. A file in the transient state may be deleted or renamed only, but is otherwise inaccessible. A transient file never supersedes an existing file of the same name, so that the user's options are left open after a non-standard termination to retain either or both. The user is cautioned that in specifying a file for deletion or renaming, a transient file is not specially identified as such, the filename simply being that specified when the file was opened. When a transient and non-transient file of the same name are both in existence, the Delete and Rename operations are guaranteed to operate on the transient one, but beware the hazard of forgetting that a transient file has been deleted and giving the same command again. Note also that some utility programs like editors buffer several blocks of a file locally, so that a transient file may not contain as much data as might be assumed. While they are in the process of being created, transient files may not be accessed in any way, although it is still possible to read any old file of the same name. Except when written unsuccessfully, transient files should not normally concern the ordinary user. Subliminal files are files which are due for deletion. A file becomes subliminal if it is in use when it is deleted; a nameless file is subliminal throughout its existence. They are automatically destroyed when they cease being used. Subliminal files are inaccessible to anyone who is not already using the file. @SubSection(Spool devices) There are no spool devices directly attached to the filestores. Despoolers are expected to use the normal protocol to tranfer files from the filestore. @SubSection(Control terminal) @IndexSecondary(Primary="Filestores", Secondary="Control terminal") @SeeAlso(Primary="Filestores",Other="Terminal") The control terminal attached to the APM performs several functions. @Begin(Itemize) During booting it may be used to specify some alternative action to the default boot sequence. While the filestore is running significant events are logged on the control terminal, together with a periodic report on filestore activity: such reports include use of the system password, creation and deletion of users, and disc and ether failure conditions. If the keyboard is enabled it may be used to request more detailed information on the operation of the filestore or to change its mode of operation. The following (single-character) commands are available: @Begin(Description) @IndexSecondary(primary="Terminal", Secondary="Control-_") control-_@\(control-underline) Toggle the enable/disable state of the keyboard. It should normally be kept disabled. @IndexSecondary(primary="Terminal", Secondary="?") ?@\Report on the current filestore status. @IndexSecondary(primary="Terminal", Secondary="B") B@\Baud rates of any Qsart RS232 lines present. @IndexSecondary(primary="Terminal", Secondary="O") O@\Alter the open state of the filestore. A number should be given to indicate the desired state. The usual values of this are 0 to close the system entirely, 3 to close the system to anyone not using the system password, and -1 to open the system completely. @IndexSecondary(primary="Terminal", Secondary="Q") Q@\Qsart status. This is ignored if there is no Qsart. @IndexSecondary(primary="Terminal", Secondary="S") S@\System buffers. This gives a list of who owns them. @IndexSecondary(primary="Terminal", Secondary="T") T@\Set trace mode. The normal value for this is 0. @IndexSecondary(primary="Terminal", Secondary="W") W@\Set file system protection mode. The normal value for this is 1. Setting this to 0 disables any operations which would write to the disc. @End(Description) Note that while these commands are waiting for input the entire filestore is placed in a state of suspended animation, and hence they should be used with discretion, if at all. @End(Itemize) @NewPage @Section(PROTOCOL) @IndexSecondary(Primary="Filestores", Secondary="Protocol") This section presents the information needed to implement a client system or utility which communicates with the filestore. As already described, the filestore provides services on receipt of requests, and always produces a response. Although only ordinary ISO characters are used, the protocol is designed for convenience of implementation rather than readability and is intended to make available to the system designer a set of primitives from which a powerful filing system capability may be constructed and presented in an appropriate form to the system user. @IndexSecondary(Primary="Filestores", Secondary="Request") Requests may be regarded as falling into three categories, in terms of the context they pre-suppose; these will be distinguished as zero-level, user-level and transaction-level. @Begin(Enumerate) A command at zero level pre-supposes no context. There is no default ownername and no owner authority. This is the level at which someone who has not (yet) logged on to the filestore operates. Most requests which are valid at user level are also in principle valid at zero level, but the restrictions just noted mean that this level is normally used solely to issue a Logon request which, if successful, returns a user-number (uno). The user-number is a token for that logged-on owner which enables the user to operate at user level. At user level, all requests must be accompanied by the user-number of the user requesting service. Most requests belong to this level, such as Delete, Logoff and Quote. In particular, there are three requests, Openr, Openw and Openmod, which initiate a file transfer on a block-by-block basis (from now on, a transaction) and return a transaction-number (xno). The requests at transaction level are a specific set of commands (such as Readsq, Writeda and Close) which further or terminate a transaction opened by one of the Open commands just mentioned. Each request of this type must be accompanied by the transaction-number of the transaction to which the requested service relates. @End(Enumerate) A request and a response are both indivisible units for communication purposes and the sequence of the two is not interruptable by another interchange for the same client. All the data making up a request must be transmitted without significant delay and the client must be ready to accept the complete response, also without significant delay. The filestore times out any client which offends in this respect and abandons the operation. @SubSection(Syntax) @IndexSecondary(Primary="Filestores", Secondary="Syntax") Each request consists of a command-line, followed in the case of the Write-block commands only (Writesq, Writeda), by a sequence of data bytes. The command line consists of a command letter followed by a reference followed by at most two additional parameters separated by commas, the whole being terminated by a newline (linefeed) character. The command letter defines the operation requested. The reference is a single character code representing either a user-number (or zero) or a transaction-number, depending on the type of command as established by the command letter. The significance of the parameters depends on the specific command but each belongs to one of the following classes: @Begin(FileExample) ownername filename password attributes byte count block count block number @End(FileExample) Case distinctions are ignored for the command letter and for letters in names, passwords and permissions. The single symbol used for the reference is a character in the ISO set ranging from '0', representing zero, upwards. So, for example, ':' represents ten, '@' sixteen, 'A' seventeen, and 'a' forty-nine. Parameters which are numeric, such as byte and block counts, are represented in a special form of hexadecimal (high-density hex) which uses the same encoding of digits onto the ISO collate sequence as just described, and, although the radix remains 16, permits arbitrarily large digits (at least up to the limit of ISO printable characters). Hence 512 (decimal) is representable as P0 in high-density hex, although 200 is also a valid representation. In the narrative which follows (though not in example formats), any reference to a value in high-density hex is flagged with the symbol "#"; numeric values not so flagged are in decimal. The following are examples of correct commands: @Begin(FileExample) L0ABC,SHRDLU t7WILSON:FILENAME.B,90 X3 p3qwerty @End(FileExample) Successful responses always start with an acknowledgement line containing one or two high-density hex values (separated by a comma if two). In the case of data request commands only (Read and Finfo, for example) the acknowledgement is followed by a sequence of data bytes, the number of bytes being specified in the acknowledgement line. In the descriptions below, the term 'packet' is used as shorthand for a byte-count followed by a newline followed by the specified number of data bytes. @NewPage @IndexSecondary(Primary="Filestores", Secondary="Summary of commands") @SubSection(Summary of commands) @Begin(FileExample) Command let ref param 1 param 2 param3 response Logon L 0 ownername password --- uno Logoff M uno --- --- --- --- CDatestamp C uno usernumber filename date --- Status N usernumber filename --- --- Delete D uno filename --- --- --- Rename B uno filename filename --- --- Permit E uno filename permissions --- --- Finfo F uno ownername file-number --- PACKET Datime G uno --- --- --- PACKET Pass P uno password --- --- --- Pass P uno password username --- --- Quote Q uno password --- --- --- Setdir J uno ownername --- --- --- Copyfile O uno filename filename --- --- Readfile Z uno filename --- --- --- then FILE Openr S uno filename --- --- xno Openw T uno filename block-count --- xno Openmod A uno filename --- --- xno Reset U xno block-number --- --- --- Close K xno --- --- --- --- Uclose H xno --- --- --- --- Readsq X xno --- --- --- PACKET Writesq Y xno PACKET --- --- Readda R xno block-number --- --- PACKET Writeda W xno block-number PACKET --- --- Readback I xno --- --- --- PACKET remote control ] uno system-command --- PACKET command @End(FileExample) @SubSection(Description of individual commands) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Logon") Logon L 0 ownername , password uno @End(FileExample) This command logs "ownername" onto the filestore system. The password presented is checked against the directory password of the owner and must match. The successful response is a user-number ("uno") allocated to the user for the duration of the logged-on session. This must be quoted in subsequent commands, and is only accepted as valid in commands received from the same client as the Logon command was received. The default directory (see Setdir) is set to "ownername"; the quoted password (see Quote) is set to "password". For example: @Begin(Description, LeftMargin 20, Indent -16) L0PAUL,PASS @\Logs Paul on if his directory password is "pass". L0PAUL @\Logs on Paul if his directory password is null. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Logoff") Logoff M uno @End(FileExample) This command logs user "uno" off the filestore system. "uno" ceases to be valid and may be issued to someone else. A user is not allowed to log-off if they have any files open. If the logged-on owner is not logged-on elsewhere, then all temporary files are automatically deleted. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) M3 @\Logs user #3 off the filestore and deletes all temporary files if the same owner is not logged-on elsewhere. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="CDatestamp") CDatestamp C uno usernumber filename date @End(FileExample) The 'C' command may be used to alter the datestamp information associated with a file. This is useful when maintaining consistency between versions of a file held on several filestores, for example. The format of the command is C U filename, date where U is a valid user number, filename is the name of the file being changed and date is the new datestamp information in the form @w[dd/mm/yy hh.mm] (standard filestore date/time format). @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Status") Status N usernumber filename @End(FileExample) The command 'N' may be used to enquire about the status of a particular (named) file, with the reply being in the same format as that provided by Finfo ('F'). The format of this command is @w(N U filename) where U is a valid user number and filename is the name of the file being enquired about. @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) Delete D uno filename @IndexSecondary(Primary="Filestores", Secondary="Delete") @End(FileExample) This command deletes "filename". The user must have owner authority with respect to the directory in which the file is held and the file must have F permission for the owner. If the file is in use, it is deleted when all transactions using it are closed (see Close). The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) D3PROG1.L @\Delete PROG1.L in the default ownername's directory (i.e. usually that of the owner logged-on as user #3). D3WILSON:$DOC @\Delete $DOC from WILSON's directory. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Rename") Rename B uno filename , newname @End(FileExample) This command renames "filename" in the appropriate directory (either the ownername specified, or the default ownername) as "newname". The parameter "newname" must not be a name already present in the directory, nor must it have an explicit ownername since the file must remain in the same directory. If a temporary file is renamed as a permanent file, the owner must have sufficient quota. The user must have owner-authority with respect to the directory in which the file is held. The default response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) B3THIS,THAT @\Renames THIS in the default owner's directory as THAT. B3KL:TAP,$Tex @\Renames TAP as $Tex in KL's directory. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Permit") Permit E uno filename , attributes @End(FileExample) This command alters the attributes of "filename" as specified by "attributes". Either the two permissions or the archive status or both may be specified; if either is omitted, the relevant attribute is unchanged. The user must have owner-authority with respect to the directory in which the file is held. If a null filename is specified, the default attributes on the directory are altered. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) E7MYFILE,FFV @\Alters the permissions of MYFILE in the default ownername's directory to have Owner permission and Public permission both Full and makes the file vulnerable (so that it will not be automatically archived). E7SI:IL.XI,RR @\Gives read-only access to SI:IL.XI to anyone and leaves the archive-statusunchanged. E7SID:,FR @\Alters the default permissions on the directory SID so that files subsequently created in it will have permissions FR. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="General enquiry") General enquiry G uno , case packet @End(FileExample) This is a general-purpose command used to obtain various kinds of information from the filestore or select options, as determined by the value of "case". Most of the operations are concerned with system management and monitoring. Case=0: DATIME The data part of the response packet gives the current time and date in the form: @Begin(FileExample) 23/12/84 19.30 @End(FileExample) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Finfo") Finfo F uno ownername , file-number packet @End(FileExample) This command is used to obtain file information about a single file in the directory specified by "ownername" (default the logged-on owner). The file-number indicates which file, counting from the most recently created as 1 up to the total number of relevant files. For a user with owner-authority, all the file entries are relevant; for a user with public-authority, only those where some access to the file itself is permitted. The data part of the response packet takes the form of a single line of text specifying: filename, permissions, date, time and size of the file in blocks and extents. For example: @Begin(FileExample) NNTEST2.OBJ FN 25/12/81 09.45 56(3) @End(FileExample) A null response is provided for a file-number greater than the number of (relevant) file entries in the directory. By convention, file-number zero elicits information about the complete directory. The data part of the response packet takes the form of a single line specifying: ownername, partition and owner-number within partition, current time and date, the number of files and extents, and the total number of blocks occupied by the files, together with the quota. For example: @Begin(FileExample, LeftMargin +0) ABC (1.5) at 13.12 on 24/12/81 Files: 9 Extents: 15 Blocks: 212/500 @End(FileExample) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Pass") Pass P uno password @End(FileExample) This command alters the directory password of the logged-on user to "password". If no password is specified (null), it will be matched by a null password, making public-authority equivalent to owner-authority. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) P8QWERTY @\Sets the password in the logged-on owner's directory to QWERTY. P2 @\Sets the logged-on owner's password to null giving anyone access to all files at owner-authority. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Pass") Pass P uno password username @End(FileExample) It is possible to specify a username as the second parameter to the pass command: in this case the specified user's password is changed, rather than the logged-on user's. This extension is only available to privileged users. Note that it is not possible to quote one's own username to change its password unless privileged. @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Quote") Quote Q uno password @End(FileExample) This command sets the quoted password for the user to "password". This password is used to match against those in directories when accessing other owners' files. If "password" is omitted (null), it will match only null directory passwords. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) Q3SHRDLU @\Sets the quoted password to SHRDLU to gain authority with respect to directories with password set to SHRDLU. Q3 @\Sets the quoted password to null. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Setdir") Setdir J uno ownername @End(FileExample) This command sets the default directory name for the user to "ownername". The default ownername is used whenever a filename is presented by the user without an explicit ownername. If "ownername" is omitted in the command, then the default ownername is reset to that of the logged-on owner. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) J3ABC @\Sets the default ownername for user #3 to ABC, so that, for example, filename TEST3 means ABC:TEST3. J3 @\Resets the default ownername to that of the owner logged on as user #3. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Copy") Copy O uno filename-1 , filename-2 @End(FileExample) This causes a copy of "filename-1" to be made to "filename-2". The successful response is the null response. The response is sent when the filestore has determined that the copy operation is valid, but before the file has been copied. Thus errors occuring during the copying are not signaled. For example: @Begin(Description, LeftMargin +20, Indent -16) O3ABC:TEST,JIM @\Copy TEST owned by ABC (if permitted in read mode) into the directory of user #3. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Readfile") Readfile Z u filename block-count, pad-count then contents of file @End(FileExample) This command is used to read "filename" without protocol. The successful response consists of an acknowledgment line providing two values: the number of blocks in the file and the number of unused bytes in the last block. This is spontaneously followed by the content of the file. For example: @Begin(Description, LeftMargin +20, Indent -16) Z5MYFILE @\Reads MYFILE without further protocol. It is up to the client to decide when it has received the last byte of the file. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Openr") Openr S uno filename xno , block-count, pad-count @End(FileExample) This command is used to initiate a transaction to read "filename" on a block-by-block basis. The file must already exist and the permission at the appropriate authority level must be at least R. The successful response is the transaction-number ("xno") allocated to the transaction, and the size of the file (as number of blocks and number of unused bytes in last block). The "xno" returned must be quoted in all commands which further or terminate the transaction, and these are valid only from the client from which the file was opened. For example: @Begin(Description, LeftMargin +20, Indent -16) S4ODESSA @\Opens a transaction for reading of ODESSA. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Openw") Openw T uno filename , block-count xno @End(FileExample) This command is used to initiate a transaction to write "filename" sequentially on a block-by-block basis. The user must have owner-authority with respect to the directory involved, and, if a file of the same name already exists in that directory, the permission at owner level must be F. To write a temporary file the owner must be the logged on owner. The permissions set on the file being created are the default permissions for the directory, unless there is an existing file of the same name in which case the permissions are inherited from the old file. The block-count, if specified, indicates the known or estimated size of the file in blocks, which may be of assistance in allocating space for the file. The successful response is the transaction-number ("xno") of the transaction, which must be quoted in all commands which further or terminate the transaction. Commands quoting the "xno" returned are only accepted at the client from which the file was opened. For example: @Begin(Description, LeftMargin +20, Indent -16) T6DATA17 @\Opens a transaction to write DATA17. T8ABC:TEST,90 @\Opens a transaction to write ABC:TEST with initial allocation #90. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Openmod") Openmod A uno filename xno, block-count, pad-count @End(FileExample) This command is used to open an existing file for modification. Both read and write operations are permitted but the size of the file cannot be altered. The successful response is the transaction-number ("xno") allocated to the transaction and the size of the file (as for Openr). The transaction number must be quoted in all commands which further or terminate the transaction. Commands quoting the "xno" returned are accepted only from the client which opened the file. For example: @Begin(Description, LeftMargin +20, Indent -16) A4SORT.1 @\Opens a transaction for modification of SORT.1 @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Reset") Reset U xno block-number @End(FileExample) This command is used to reset transaction "xno" to the specified block-number, counting from zero as the first block. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) U4 @\Resets transaction #4 to the beginning of the file. U4A2 @\Resets transaction #4 to block #A2. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Close") Close K xno @End(FileExample) This command cancels the validity of the "xno" concerned. If the transaction had been sequential output then the file concerned becomes the permanent file and any other existing file of the same name is deleted. For example: @Begin(Description, LeftMargin +20, Indent -16) K4 @\Closes transaction #4. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Uclose") Uclose H xno @End(FileExample) This command is used to terminate a transaction unsuccessfully. It differs from Close only in the case of a transaction open for sequential writing. In this case an old file of the same name is not deleted and the destination file is left transient. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) H4 @\Closes transaction #4 unsuccessfully. @End(Description) @End(Group) There is no distinction between "SQ" files and "DA" files. SQ and DA operations may be freely mixed, although the user should realise that DA operations will reset the current block pointers for the file. Files may be extended one block at a time by WriteSQ and WriteDA. Files opened for reading and modification will never be made any shorter; files opened for writing only will be truncated to the current block position when they are closed. Null files will be deleted on closing. Multi-block ReadSQs will produce the required number of blocks or the remainder of the file, whichever is shorter, the latter condition being indicated by the transmission of a short block. @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Readda") Readda R xno blockno packet @End(FileExample) This command reads block "blockno" from transaction "xno", which must have been opened for reading or modification. The byte-count in a successful response is the value #P0; and this is followed by 512 bytes of data. If the command is unsuccessful then the data block is not transmitted. For example: @Begin(Description, LeftMargin +20, Indent -16) R9C1 @\Reads block #C1 from transaction #9. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Writeda") Writeda W xno blockno , packet @End(FileExample) This command writes block "blockno" to transaction "xno", which must have been opened for modification. Byte-count should be #P0, and the command line is followed immediately by 512 bytes of data. The successful response is the null response. For example: @Begin(Description, LeftMargin +20, Indent -16) W74,P0 @\Writes block #4 to transaction #7. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Readsq") Readsq X xno block-count packet @End(FileExample) This command requests the next sequential block or blocks from transaction "xno", which must have been opened for reading. The default for "block-count" is one. In the case of a request for one block, the acknowledgement line of a successful response gives the number of bytes of information to follow. This is 512 bytes, except for the last block in the file when it may be less. A request to read the next block when the end of the file has been reached, generates a byte-count of zero and no data. A request for multiple blocks causes For example. @Begin(Description, LeftMargin +20, Indent -16) XC @\Reads the next block from transaction #C. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Writesq") Writesq Y xno packet @End(FileExample) This command writes the next sequential block to transaction "xno", which must have been opened for writing or modification. A value of less than 512 for the byte-count implies that the last block in the file is being sent, prior to closing the file. After such a short block no further transfers are valid; only Close or Uclose. The successful response is the null response; for reasons of efficiency, this is sent as soon as the data has been received and the validity of the request checked, but before the block of data is written to disk. Any disk transfer errors are notified at the time the file is closed. For example: @Begin(Description, LeftMargin +20, Indent -16) YCP0 @\Writes the 512 bytes supplied as the next block on transaction #C. Y482 @\Writes the 130 bytes supplied as the first 130 bytes of the next block on transaction #4 and prevents further transfers to that transaction. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Readback") Readback I xno packet @End(FileExample) This command reads back the last block written to transaction "xno" which must be open for sequential writing. The block read back is removed from the file and subsequent Readback commands retrieve successively earlier blocks. This command is invalid once the final (short) block has been written to a sequential output file (see above Writesq). A request to read back the previous block when the file is empty generates a byte-count of zero and no data. For example: @Begin(Description, LeftMargin +20, Indent -16) I2 @\Reads the next block back from transaction #2. @End(Description) @End(Group) @Begin(Group) @Begin(FileExample, LeftMargin +0) @IndexSecondary(Primary="Filestores", Secondary="Remote control") remote control command ] uno system-command packet @End(FileExample) Commands of this form provide a method of injecting system control commands (see next section) from a client, rather than the filestore terminal. @End(Group) @IndexSecondary(Primary="Filestores", Secondary="Commands") @SubSection(Commands in alphabetic order of command letter) @Begin(FileExample) A Openda N Status B Rename O Copy C CDatestamp P Pass D Delete Q Quote E Permit R Readda F Finfo S Openr G Datime T Openw H Uclose U Reset I Readbk V unused J Setdir W Writeda K Close X Readsq L Logon Y Writesq M Logoff Z Readfile @End(FileExample) @NewPage @Section(SYSTEM CONTROL COMMANDS) @IndexSecondary(Primary="Filestores", Secondary="System control commands") The ']' command is available, with the following options (U indicates a user number, quoting the system password unless otherwise stated): @Begin(Description) ]U1,n@\Kill Uno. Kills user number n. U must be quoting the system password if the target Uno does not belong to the same owner. ]U2,n@\Kill Xno. Kills transaction number n. ]U3,n@\Kill port n. Not implemented yet. ]U4,n@\Set diagnostic mode. Same as the console 't' command. ]U5,n@\Set system availability. Same as the console 'o' command. ]U6,pass@\Sets the system password. This takes immediate effect. The new password will be written out to the disc, from whence it will be read during subsequent reboots. ]U7@\Reboot the filestore. @End(Description) @NewPage @Section(ERRORS) @IndexSecondary(Primary="Filestores", Secondary="Errors") In the event of an error, the filestore returns an errorcode and message instead of the successful response. All error responses consist of a line starting with a minus sign followed by one high-density hex digit. These two characters are followed by a space and an error message; the length of the error message is not fixed. A client system may use the errorcode for its own recovery but pass the error message onto its user as a readable indication of the error. @SubSection(Details of errors) @Begin(FileExample) Error Code Meaning 0 success -1 bad context -2 not implemented -3 illegal Xno -4 param error -5 no Xno -6 protocol error -7 illegal Uno -8 not logged on -9 directory corrupt -10 file in use -11 file not found -12 owner not found -13 no authority -14 no quota -15 no slot -16 no extent -17 disc full -18 system down -19 file exists -20 partition corrupt -21 disc error -22 illegal operation -23 no buffer -24 user exists -25 no Uno -26 refcount negative -27 size error -28 data address error -29 directory address error -30 logins disabled -31 not writeable -32 directory in use -33 directory not empty -34 no process -35 conflicting access @End(FileExample) @NewPage @Section(SPECIAL FILES) A number of pseudo-files "owned" by user '$' "contain" useful information about the state of the filestore's internal tables. These are: @Begin(Description) $:TRACE@\The filestore's trace buffer. This should be formatted by the appropriate command run on the client. $:BITMAP.@\The bitmap for partition . Again, this requires to be formatted to make it more digestible. $:UNOS@\The user number table. $:XNOS@\The transaction number table. $:DIRECTORIES@\The directory cache. $:PORTS@\The ether port table. $:BOOTAREA@\This special file gives access to the boot area at the start of the disc. Note that this area is not accessible as part of any user partition. This file must be accessed using OpenMod, ReadDA and WriteDA. For more information on these files see section @Ref(SystemFiles). @End(Description) @NewPage @Section(A QUICK TOUR THROUGH THE SYSTEM) The filestore system is based around a number of co-operating processes: @Begin(Itemize) ether receiver handler ether depacketiser command interpreter ether transmitter handler console log stamp @End(Itemize) Apart from the last of these, requests from clients pass through each process in turn. Processes perform their tasks and then place themselves onto one of the wait queues maintained by the scheduler. The processes are removed from their wait queues and given the CPU when the scheduler determines that there is something for them to do, either because some other process has requested that the first process on the queue should be awakened, or because the scheduler itself has detected that some event has occurred which requires a process to be resumed to handle it. Processes are scheduled strictly according to the priority of the wait queue on which they have placed themselves; however higher priority processes do not pre-empt lower priority ones, with the result that no complicated concurrency control is required. @IndexSecondary(Primary="Filestores", Secondary="Request") In detail, the sequence of events triggered by the arrival of a request from a client is as follows: @Begin(Enumerate) The arrival of the ether packet is detected by the ether driver in the kernel which sets the appropriate bit in the DTX bit-vector to indicate that the packet has arrived. This is detected by the scheduler, which causes the ether receiver handler to execute to read the packet into an internal buffer. The receiver handler then checks to see if there is another packet available, and if so it reads that in too. This filestore process is the only one which does not suspend itself when it has completed the task for which it was awakened. It is scheduled with the highest priority in order that packets are removed from the ether station as quickly as possible, the aim being to reduce the load on the ether station to a minimum. When it has read all the packets from currently available in the station it kicks the depacketiser process and suspends itself. The purpose of the depacketising process is to split apart the incoming requests from clients into their constituent text and data parts. This is necessitated by the filestore protocol, which considers requests as a (variable length) textual command part separated from any data by a NL character. This task is performed by a separate process from the ether receiver handler in order to keep the former as small and fast as possible. Having been depacketised, the request is queued to the interpreting processes. The interpreting process which dequeues the request determines what action to take on the basis of the command letter in the first byte of the text part. It calls one or more of the file system routines to perform this task, putting the resulting buffers onto the ether transmission queue. Finally one of the ether transmitter processes dequeues the reply buffer, transforms it into a single ether packet in a form acceptable to the client and sends it on its way. In order to ensure that the load imposed on the station is minimised, the process waits until the packet is either ACKed or NAKed before dequeueing the next buffer. @End(Enumerate) The purpose of the log stamp process is to generate and write out the console log information.