<> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> DIRECTORY BasicTime USING [GMT, nullGMT], IO USING [STREAM], Rope USING [ROPE]; FS: CEDAR DEFINITIONS = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; <> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> < IF error.group = user THEN { YourProcedureToShowRopeToUser[error.explanation]; CONTINUE }>> <<>> <> <<>> <> <<>> <> <> <> <> <> <> <> <<>> <> <<>> <> <> <> <<>> ErrorGroup: TYPE = { ok, -- initial group for a new FS.ErrorDesc bug, -- caused by an internal bug environment, -- something's wrong in the environment; human intervention required lock, -- conflict over locks client, -- illegal operation, probably due to bug in client program user -- illegal operation, probably due to user action }; <<>> <> <<>> ErrorDesc: TYPE = RECORD [group: ErrorGroup, code: ATOM, explanation: ROPE] _ [ok, NIL, NIL]; <<>> <> <<>> Error: ERROR [error: ErrorDesc]; <> <<>> <> <> <> maxFNameLength: CARDINAL = 126; <<>> <> <<>> <> <<>> <<[server]subDirectory>simpleName!version>> <> <<>> <", or "/". The non-structural characters allowed in the rest of an FName are all alphanumeric characters plus ".", "$", "-" and "+". The additional structural character "!" is used as the version part prefix. The rest of the version part can be a number in the range [1 .. 65534], or one of the letters "L" or "H". Case is not significant in FNames.>> <<>> <> <<>> <> <<>> <> <<>> <<[]<>FS.mesa!3>> <> <<[]Temp>DebugTool.bcd!12>> <> <<>> <> <<>> <> <<1. Certain remote servers, e.g., Gateways, Grapevine servers, do not have a directory structure or versions. Such servers require GNames of the form "[server]simpleName".>> <<2. XNS remote servers strongly recommend that file names not contain the characters: apostrophe ('), asterisk (*), sharp sign (#), comma (,), diagonal slash (/), or exclamation point (!). The name may not have a length of 0 or exceed 100 bytes in the Courier representation of its unescaped form. In addition the characters "(" and ")" should be avoided since they are used to define the server part of a full name in Filing pathnames. If these constraints are not met, FS will not be able to access the file.>> <<3. The root directory in an LName may also be identified by its unique VolumeID. The syntax for the root directory part in this case is "#" followed by a 20-digit hexadecimal string.>> <<4. The Cedar debugger interface makes a remote debuggee's disk available to a debugger as if its disks were attached to the debugger's machine. This is essentially transparent to FS; volumes of the debuggee's disk will appear to be part of the local server, i.e., files will be LNames, not GNames. This is entirely different from the situation in which the remote machine is operating normally and is running, say, an FTP server.>> <> <> <<>> <> <<>> <<1) the "wDir" argument;>> <<2) the value of the $WorkingDirectory property of the process property list;>> <<>> <" ("/") then a ">" ("/") is appended. If no other working directory can be found, "[]<>" is used.>> <> Position: TYPE = RECORD [start, length: CARDINAL]; ComponentPositions: TYPE = RECORD [server, dir, subDirs, base, ext, ver: Position]; ExpandName: PROC[name: ROPE, wDir: ROPE _ NIL] RETURNS [fullFName: ROPE, cp: ComponentPositions, dirOmitted: BOOL]; <> <<>> <". The "subDirs" is the all the subdirectory part without without surounding "> ... >" but including interior ">"s. The "base" is the portion of the simple name up to but not including the final "." The "ext" is the portion of the simple name following the final "." If there are no "."s in the simple name then it is all considered to be "base". The "ver" is everything after the "!".>> <<>> <"), then "dirOmitted" returns TRUE; otherwise it returns FALSE.>> <<>> <> <<>> <> <<>> <> <<>> <> <> <<>> ComponentRopes: TYPE = RECORD [server, dir, subDirs, base, ext, ver: ROPE _ NIL]; ConstructFName: PROC [cr: ComponentRopes, omitDir: BOOL _ FALSE] RETURNS [ROPE]; <" within the subdirectory component.>> <<>> <> <> <" ];>> < 0 THEN name _ Rope.Cat[ name, cr.subDirs, ">" ];>> <> < 0 THEN name _ Rope.Cat[ name, ".", cr.ext ];>> < 0 THEN name _ Rope.Cat[ name, "!", cr.ver ];>> <> <<>> <> <> <> <> <<>> <> FileType: TYPE = MACHINE DEPENDENT RECORD [CARD32]; tUnspecified: FileType = [0]; tDirectory: FileType = [1]; tText: FileType = [2]; <<>> <> <<>> <> <<>> <> <<>> WordsForPages: PROC[pages: INT] RETURNS [words: INT]; BytesForPages: PROC[pages: INT] RETURNS [bytes: INT]; PagesForWords: PROC[words: INT] RETURNS [pages: INT]; PagesForBytes: PROC[bytes: INT] RETURNS [pages: INT]; <> <> <<>> <> <<>> <> <> <<>> <> <<>> <> <> <<>> <> <> <> <> <> <> <> <> <> <> Lock: TYPE = {read, write}; <> <> <> <> <> FileInfo: PROC [ name: ROPE, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, remoteCheck: BOOL _ TRUE, wDir: ROPE _ NIL ] RETURNS [ fullFName, attachedTo: ROPE, keep: CARDINAL, bytes: INT, created: BasicTime.GMT, fileType: FileType ]; <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <> <<>> <> <> <> <<>> InfoProc: TYPE = PROC [ fullFName, attachedTo: ROPE, created: BasicTime.GMT, bytes: INT, keep: CARDINAL, fileType: FileType ] RETURNS [continue: BOOL]; EnumerateForInfo: PROC [pattern: ROPE, proc: InfoProc, wDir: ROPE _ NIL]; <<"proc" is called for each FName selected by the pattern. Returning "continue" as FALSE stops the enumeration. "fullFName" reports the complete FName including version part of each name encountered. The keep, byte length, created date, and file type of a local or global file are reported. When an LName attached to a GName is encountered, "fullFName" is the LName and "attachedTo" is the GName. In this case, the "keep" and "fileType" reported are those of the LName but the "bytes", "created" and "fileType" (if implemented) are that of the GName. If any FS.Error's are encountered when trying to determine the byte count of an attachment, they are suppressed and "bytes" is reported as -1. Whenever a valid byte count for an attachment is reported then the version part in an "attachedTo" name is the true version number that corresponds to the created-time for the attachment; otherwise this version part will be whatever was recorded by FS.Copy when the attachment was made.>> <<>> <> <> NameProc: TYPE = PROC [fullFName: ROPE] RETURNS [continue: BOOL]; EnumerateForNames: PROC [pattern: ROPE, proc: NameProc, wDir: ROPE _ NIL]; <> <<>> <> <> <> <> <<>> <> OpenFile: TYPE = RECORD[REF]; nullOpenFile: OpenFile = [NIL]; Open: PROC [name: ROPE, lock: Lock _ $read, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, remoteCheck: BOOL _ TRUE, wDir: ROPE _ NIL, verifyNow: BOOL _ FALSE, checkFileType: BOOL _ FALSE, fileType: FileType _ tUnspecified ] RETURNS [OpenFile]; <> <<>> <> <> Create: PROC [name: ROPE, setPages: BOOL _ FALSE, pages: INT _ 0, setKeep: BOOL _ FALSE, keep: CARDINAL _ 1, wDir: ROPE _ NIL, fileType: FileType _ tUnspecified ] RETURNS [OpenFile]; <> <<>> <> <> OpenOrCreate: PROC [name: ROPE, keep: CARDINAL _ 1, pages: INT _ 5, wDir: ROPE _ NIL, checkFileType: BOOL _ FALSE, fileType: FileType _ tUnspecified ] RETURNS [OpenFile]; <> <<>> <> <> <> GetClass: PROC [file: OpenFile] RETURNS [ATOM]; <> <<>> <> <> <<>> SameFile: PROC [file1, file2: OpenFile] RETURNS [BOOL]; <> <<>> <> <> GetName: PROC [file: OpenFile] RETURNS [fullFName, attachedTo: ROPE]; <> <<>> <> <> GetInfo: PROC [file: OpenFile] RETURNS [keep: CARDINAL, pages, bytes: INT, created: BasicTime.GMT, lock: Lock, fileType: FileType]; <> <<>> <> <> <<>> SetPageCount: PROC [file: OpenFile, pages: INT]; <> <<>> <> <> <<>> SetByteCountAndCreatedTime: PROC [file: OpenFile, bytes: INT _ -1, created: BasicTime.GMT _ BasicTime.nullGMT]; <> <<>> <> <> <<>> Read: UNSAFE PROC [file: OpenFile, from, nPages: INT, to: LONG POINTER]; <> <<>> <> <> Write: PROC [file: OpenFile, to: INT, nPages: INT, from: LONG POINTER]; <> <<>> <> <> Close: PROC [file: OpenFile]; <> <<>> <> <> <<>> <> <> <<>> <> <<>> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < fileLen. Set streamIndex _ index.>> <> <> <> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <> StreamOptions: TYPE = PACKED ARRAY StreamOption OF TrueBool; TrueBool: TYPE = BOOL _ TRUE; StreamOption: TYPE = { tiogaRead, <> truncatePagesOnClose, <> closeFSOpenFileOnClose <> }; defaultStreamOptions: StreamOptions = []; binaryStreamOptions: StreamOptions = [tiogaRead: FALSE]; <> <<>> StreamBufferParms: TYPE = RECORD [vmPagesPerBuffer: INT [1 .. 128], nBuffers: INT [1 .. 64]]; defaultStreamBufferParms: StreamBufferParms = [vmPagesPerBuffer: 8, nBuffers: 2]; minimumStreamBufferParms: StreamBufferParms = [vmPagesPerBuffer: 1, nBuffers: 1]; <> <<>> ByteCount: TYPE = INT; ExtendFileProc: TYPE = PROC [--current--ByteCount] RETURNS [--new--ByteCount]; <> AccessOptions: TYPE = {read, create, append, write}; StreamOpen: PROC [fileName: ROPE, accessOptions: AccessOptions _ $read, streamOptions: StreamOptions _ defaultStreamOptions, keep: CARDINAL _ 1, createByteCount: ByteCount _ 2560, streamBufferParms: StreamBufferParms _ defaultStreamBufferParms, extendFileProc: ExtendFileProc _ NIL, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, remoteCheck: BOOL _ TRUE, wDir: ROPE _ NIL, checkFileType: BOOL _ FALSE, fileType: FileType _ tUnspecified ] RETURNS [STREAM]; <<>> <> <<>> <<(1) If accessOptions = $read, perform FS.Open[name: fileName, wantedCreatedTime: wantedCreatedTime, remoteCheck: remoteCheck, wDir: wDir, checkFileType: checkFileType, fileType: fileType]. If accessOptions = $create, perform FS.Create[name: fileName, keep: keep, pages: FS.PagesForBytes[createByteCount], wDir: wDir, fileType: fileType]. If accessOptions = $append, perform FS.OpenOrCreate[name: fileName, keep: keep, pages: FS.PagesForBytes[createByteCount], wDir: wDir, checkFileType: checkFileType, fileType: fileType]. If accessOptions = $write, perform FS.Open[name: fileName, lock: $write, wantedCreatedTime: wantedCreatedTime, remoteCheck: remoteCheck, wDir: wDir, checkFileType: checkFileType, fileType: fileType]. Any FS.Error raised by a call to FS.Open, FS.Create, or FS.OpenOrCreate will propogate through FS.StreamOpen.>> <<>> <<(2) Perform FS.StreamFromOpenFile[ ... , streamOptions, streamBufferParms, extendFileProc] on the resulting FS.OpenFile. The value of accessOptions determines the set of operations allowed on the stream (disallowed operations raise IO.Error[$NotImplementedForThisStream, stream] when called), and the initial streamIndex, as follows:>> <> <> <> <> <<>> <> <> StreamFromOpenStream: PROC [self: STREAM] RETURNS [STREAM]; <> <> <> <<>> InitialPosition: TYPE = {start, end}; StreamFromOpenFile: PROC [openFile: OpenFile, accessRights: Lock _ $read, initialPosition: InitialPosition _ $start, streamOptions: StreamOptions _ defaultStreamOptions, streamBufferParms: StreamBufferParms _ defaultStreamBufferParms, extendFileProc: ExtendFileProc _ NIL ] RETURNS [STREAM]; <> <<>> <> <> OpenFileFromStream: PROC [self: STREAM] RETURNS [OpenFile]; <> ErrorFromStream: PROC [self: STREAM] RETURNS [ErrorDesc]; <> <> <> Copy: PROC [from, to: ROPE, setKeep: BOOL _ FALSE, keep: CARDINAL _ 1, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, remoteCheck: BOOL _ TRUE, attach: BOOL _ FALSE, wDir: ROPE _ NIL ] RETURNS [toFName: ROPE]; <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <<>> <> <> <<>> Delete: PROC [name: ROPE, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, wDir: ROPE _ NIL ]; <<>> <> <<>> <> <> Rename: PROC [from, to: ROPE, setKeep: BOOL _ FALSE, keep: CARDINAL _ 1, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, wDir: ROPE _ NIL ]; <> <<>> <> <> <<>> <<>> SetKeep: PROC [name: ROPE, keep: CARDINAL _ 1, wDir: ROPE _ NIL]; <> <<>> <> <> ChangeFileType: PROC [name: ROPE, newFileType: FileType, wDir: ROPE _ NIL]; <> <<>> <> <> <<>> SetClientProperty: PROC [name: ROPE, propertyName: ROPE, propertyValue: ROPE, wDir: ROPE _ NIL]; <> <<>> <> <> <<>> GetClientProperty: PROC [name: ROPE, propertyName: ROPE, wDir: ROPE _ NIL] RETURNS [propertyValue: ROPE]; <> <<>> <> <> <<>> PropProc: TYPE = PROC [ propertyName: ROPE, propertyValue: ROPE ] RETURNS [continue: BOOL]; EnumerateClientProperties: PROC [name: ROPE, proc: PropProc, wDir: ROPE _ NIL]; <<"proc" is called for each client property that has a non-NIL value. The enumeration is done over the properties and their values that existed when the call is made to EnumerateClientProperties, so updates to the properties will not be seen by the enumerator during the duration of the enumeration.>> <<>> <> <> <> <> <<>> <> <<$inconsistent -- a local volume's permanent data structures are inconsistent>> <<$software -- label check encountered while reading or writing pages on the local volume>> <<$badFP -- File.FP from directory/cache doesn't correspond to a file on a local volume>> <<>> <> <<$wentOffline -- local volume is no longer accessible>> <<$hardware -- hard error while reading or writing pages on a local volume>> <<$volumeFull -- no more free pages on a local volume>> <<$fragmented -- file required too many non-contiguous areas on a local volume>> <<$noMoreVersions -- next version number would be too big>> <<$serverInaccessible -- couldn't get a response from a remote server>> <<$connectionRejected -- remote server rejected the connection attempt>> <<$connectionTimedOut -- connection to a remote server timed out>> <<$badCredentials -- remote server rejected the user name or password>> <<$accessDenied -- remote server access controls succeeded>> <<$quotaExceeded -- disk space quota on remote server exceeded>> <<$invalidPropertyPage -- unrecognized property page format for a file on a local volume>> <<$badBTree -- directory/cache BTree is malformed and cannot be opened>> <<$outOfPropertySpace -- property space for this file has been exhausted>> <<>> <> <<$lockConflict -- required lock cannot be obtained>> <<$fileBusy -- remote file currently being used in an incompatible way>> <<>> <> <<$noCache -- couldn't operate on global file because there is no system volume or cache>> <<$wrongLock -- operation requires a write lock and only a read lock is held>> <<$globalWriteLock -- tried to open a GName with a write lock>> <<$zeroKeep -- keep of 0 was specified>> <<$badByteCount -- tried to set a byte count that is beyond end of file or negative>> <<$unknownPage -- tried to read or write a page that is beyond end of the file>> <<$invalidOpenFile -- FS.OpenFile is closed, is FS.nullOpenFile, or is an unrecognized TYPE>> <<$notImplemented -- called procedure not provided for this FS.OpenFile>> <<$fileTypeMismatch -- the file type of the file did not match the type specified.>> <<>> <> <<$nonCedarVolume -- named volume is not a cedar volume>> <<$unknownServer -- couldn't get the network address for the named server>> <<$unknownVolume -- named local volume cannot be found>> <<$unknownFile -- FName not in the implied directory>> <<$unknownCreatedTime -- no version of the given FName had the specified created-time >> <<$illegalName -- file name, directory name or pattern has illegal syntax or characters, or is too long, >> <<$patternNotAllowed -- name presented contained a "*" and procedure doesn't allow patterns>> <<$versionSpecified -- tried to create an FName with a specific version>> <<$globalCreation -- tried to create a GName>> <<$badWorkingDir -- default working directory specified is global or has no volume part>> <<$noKeeps -- tried to set the keep on a server that does not implement keeps>> <<$cantUpdateTiogaFile -- tried open a file stream to write on a .tioga file>> END. <> <> <> <<>> <<>> <> <> <<>> <> <> <<>> <> <> <<>>