<> <> <> <> <> <> <<>> <> <<>> DIRECTORY BasicTime USING [GMT], File USING [FP, Handle, Volume], FS USING [ComponentPositions, InfoProc, Lock, OpenFile], Rope USING [ROPE, Text]; FSBackdoor: CEDAR DEFINITIONS = BEGIN ROPE: TYPE = Rope.ROPE; <> <> FileProcs: TYPE; CreateFileProcs: PROC [ GetClass: PROC [clientFile: REF] RETURNS [ATOM] _ NIL, SameFile: PROC [clientFile1, clientFile2: REF] RETURNS [BOOLEAN] _ NIL, GetName: PROC [clientFile: REF] RETURNS [fullFName, attachedTo: Rope.ROPE] _ NIL, GetInfo: PROC [clientFile: REF] RETURNS [keep: CARDINAL, pages, bytes: INT, created: BasicTime.GMT, lock: FS.Lock] _ NIL, SetPageCount: PROC [clientFile: REF, pages: INT] _ NIL, SetByteCountAndCreatedTime: PROC [clientFile: REF, bytes: INT, created: BasicTime.GMT] _ NIL, Read: UNSAFE PROC [clientFile: REF, from, nPages: INT, to: LONG POINTER] _ NIL, Write: PROC [clientFile: REF, to: INT, nPages: INT, from: LONG POINTER] _ NIL, Close: PROC [clientFile: REF] _ NIL ] RETURNS [REF FileProcs]; <<>> <> <<>> <> <> CreateProcsOpenFile: PROC [clientFile: REF, fileProcs: REF FileProcs] RETURNS [FS.OpenFile]; <<>> <> <<>> <> <> GetClientFileAndProcs: PROC [file: FS.OpenFile] RETURNS [clientFile: REF, fileProcs: REF FileProcs]; <<>> <> <<>> <> <> <<>> <<>> ErrorCode: TYPE = {ok -- used internally-- , inconsistent, software, badFP, wentOffline, hardware, volumeFull, fragmented, noMoreVersions, serverInaccessible, connectionRejected, connectionTimedOut, badCredentials, accessDenied, quotaExceeded, invalidPropertyPage, badBTree, lockConflict, fileBusy, noCache, wrongLock, globalWriteLock, zeroKeep, badByteCount, unknownPage, invalidOpenFile, notImplemented, nonCedarVolume, unknownServer, unknownVolume, unknownFile, unknownCreatedTime, illegalName, patternNotAllowed, versionSpecified, globalCreation, badWorkingDir, noKeeps, cantUpdateTiogaFile}; ProduceError: PROC [code: ErrorCode, explanation: Rope.ROPE]; <<>> <> <<>> <> <> SetFreeboard: PROC [freeboard: INT]; <<>> <> <> <<>> <<>> VolumePages: PROC [volName: ROPE _ NIL] RETURNS [size, free, freeboard: INT]; <<>> <<"volName" = NIL means the system volume.>> <<>> <> <> <<>> <> InfoProc: TYPE = PROC [ fullGName: ROPE, created: BasicTime.GMT, bytes: INT, keep: CARDINAL ] RETURNS [continue: BOOLEAN]; EnumerateCacheForInfo: PROC [proc: InfoProc, volName, pattern: ROPE _ NIL]; NameProc: TYPE = PROC [fullGName: ROPE] RETURNS [continue: BOOLEAN]; EnumerateCacheForNames: PROC [proc: NameProc, volName, pattern: ROPE _ NIL]; <> <<>> <> <> Flush: PROC [fullGName: ROPE, volName: ROPE _ NIL]; <> <<>> <> <> <<>> <> <> <<>> <" prefix. Thus the nameBody for the LName "[]<>foo.mesa!5" will be "foo.mesa", and the nameBody for the GName "[indigo]Top>FS.df!47" will be "[indigo]Top>FS.df". The version part is represented as a scalar. The version for a GName that includes no version is "noVersion", which value otherwise will not occur.>> <<>> Version: TYPE = RECORD [CARDINAL]; noVersion: Version = [LAST[CARDINAL]]; highestVersion: Version = noVersion; lowestVersion: Version = [0]; <<>> <<"highestVersion" and "lowestVersion" are used internally as the representation of !L and !H.>> <<>> <> <<>> <<*******************************************************************************>> <> <<*******************************************************************************>> EntryType: TYPE = {local, attached, cached, notFound}; -- notFound is for internal use only EntryPtr: TYPE = LONG BASE POINTER TO Entry; TextRP: TYPE = EntryPtr RELATIVE POINTER TO TextRep; TextRep: TYPE = MACHINE DEPENDENT RECORD [PACKED SEQUENCE length: CARDINAL OF CHAR]; Entry: TYPE = MACHINE DEPENDENT RECORD [ size(0): CARDINAL, -- size in words of entire entry, including TextRep's at end version(1): Version, -- version part of FName nameBody(2): TextRP, -- FName w/o version rest(3): SELECT type(3): EntryType FROM local => [ keep(4): CARDINAL, fp(5): File.FP ], attached => [ keep(4): CARDINAL, created(5): BasicTime.GMT, attachedTo(5+SIZE[BasicTime.GMT]): TextRP -- includes version part ], cached => [ used(4): BasicTime.GMT, fp(4+SIZE[BasicTime.GMT]): File.FP ] ENDCASE -- here follows the TextRep for nameBody and possibly for attachedTo ]; Enumerate: PROC [volName: ROPE, nameBodyPattern: Rope.Text, localOnly, allVersions: BOOLEAN, version: Version, matchProc: UNSAFE PROC [entry: EntryPtr] RETURNS [accept, stop: BOOLEAN], acceptProc: PROC RETURNS [stop: BOOLEAN] ]; <<>> <<"volName" is the name of a disk volume. A NIL "volName" means the system volume. The directory/cache is enumerated. The order of enumeration is lexical by nameBody (lower case letters are mapped to upper case) then numerical by version. Because LNames in the directory/cache do not have the "[]<>" prefix, and because of the constraints on the characters allowed in FNames, all LNames appear in the directory/cache earlier in the enumeration order than all GNames. The scope of the enumeration is constrained by the "localOnly" argument: if TRUE then only the LNames are enumerated; otherwise the enumeration spans all entries in the directory/cache. If "allVersions" is TRUE then the enumeration includes all versions of entries; otherwise it includes on the version specified by "version". The name body pattern is applied literally, without consideration of any working directories. If you want to enumerate only global names, then be sure the "nameBodyPattern" starts with "[". "matchProc" is called for each entry that matches the "pattern". A NIL "pattern" means to start at the beginning of the directory/cache and match everything. If "stop" is returned as TRUE then the enumeration terminates. Otherwise, if "accept" is returned as TRUE then "acceptProc" is called. The "acceptProc" can also stop the enumeration. The directory/cache is read locked while "matchProc" is called, so other operations on the directory/cache and tasks involving indefinite waits should not be done from this procedure. Do these from the "acceptProc" instead.>> <<>> <> <> <<>> TextFromTextRep: PROCEDURE [nameBody: LONG POINTER TO TextRep] RETURNS [Rope.Text]; <<>> <> <<>> <> <> <<>> <<>> MakeFName: PROCEDURE [nameBody: ROPE, version: Version _ noVersion, prefix: ROPE _ NIL] RETURNS [ROPE]; <<>> <" should be supplied. If a prefix is needed and NIL is supplied, then "[]<>" is used. For use in converting the "attachedTo" name from a directory entry to a ROPE, just leave "version" and "prefix" defaulted, since "attachedTo" already starts with "[" and includes the version part.>> <<>> <> <> <<>> <> ScavengeDirectoryAndCache: PROC [ volName: ROPE _ NIL ]; <> <<>> <> <> <<>> <> CloseVolume: PROC [v: File.Volume]; <> <<>> <> <> <<>> <<>> GetFileHandle: PROC [file: FS.OpenFile] RETURNS [File.Handle]; <> <<>> <> <> <<>> CreateVMBacking: PROC [name: ROPE, setPages: BOOLEAN _ TRUE, pages: INT _ 0, setKeep: BOOLEAN _ FALSE, keep: CARDINAL _ 1, wDir: ROPE _ NIL] RETURNS [FS.OpenFile]; <> <> FNameFromHandle: PROC [file: File.Handle] RETURNS [ROPE]; <> <<>> <> <> RemoteOp: TYPE = {startRetrieving, endRetrieving, startStoring, endStoring, startDeleting, endDeleting, startRenaming, endRenaming, startFlushing, endFlushing}; RemoteEvent: TYPE = RECORD [ op: RemoteOp, -- remote operation that has occurred fName: Rope.ROPE, -- full GName of the remote file operated upon chain: REF RemoteEvent -- used internally to chain events together ]; NextRemoteEvent: PROC [REF READONLY RemoteEvent _ NIL] RETURNS [REF READONLY RemoteEvent]; <> <> <> CreateOp: TYPE = {writeClose, renameTo, copyTo}; CreateEvent: TYPE = RECORD [ op: CreateOp, -- creation operation that has occurred fName: Rope.ROPE, -- full LName of the local file that has been created chain: REF CreateEvent -- used internally to chain events together ]; NextCreateEvent: PROC [REF READONLY CreateEvent _ NIL] RETURNS [REF READONLY CreateEvent]; <> <> <> <<>> <> GuestProcsRec: TYPE = RECORD [ IsGuestProcess: PROC [] RETURNS [isGuest: BOOL], SetDefaultWDir: PROC [dir: ROPE _ NIL], GetDefaultWDir: PROC RETURNS [ROPE], ExpandName: PROC[name: ROPE, wDir: ROPE ] RETURNS [useDefault: BOOL, fullFName: ROPE, cp: FS.ComponentPositions, dirOmitted: BOOLEAN], FileInfo: PROC [name: ROPE, wantedCreatedTime: BasicTime.GMT, remoteCheck: BOOLEAN, wDir: ROPE] RETURNS [fullFName, attachedTo: ROPE, keep: CARDINAL, bytes: INT, created: BasicTime.GMT], EnumerateForInfo: PROC [pattern: ROPE, proc: FS.InfoProc, wDir: ROPE], EnumerateForNames: PROC [pattern: ROPE, proc: NameProc, wDir: ROPE], Open: PROC [name: ROPE, lock: FS.Lock, wantedCreatedTime: BasicTime.GMT, remoteCheck: BOOLEAN, wDir: ROPE] RETURNS [FS.OpenFile], Create: PROC [name: ROPE, setPages: BOOLEAN, pages: INT, setKeep: BOOLEAN, keep: CARDINAL, wDir: ROPE] RETURNS [FS.OpenFile], Copy: PROC [from, to: ROPE, setKeep: BOOLEAN, keep: CARDINAL, wantedCreatedTime: BasicTime.GMT, remoteCheck: BOOLEAN, attach: BOOLEAN, wDir: ROPE] RETURNS [toFName: ROPE], Delete: PROC [name: ROPE, wantedCreatedTime: BasicTime.GMT, wDir: ROPE], Rename: PROC [from, to: ROPE, setKeep: BOOLEAN, keep: CARDINAL, wantedCreatedTime: BasicTime.GMT, wDir: ROPE], SetKeep: PROC [name: ROPE, keep: CARDINAL, wDir: ROPE] ]; RegisterGuestProcs: PROC [newProcs: REF GuestProcsRec]; <<>> <> GuestProcs: REF GuestProcsRec ; <> <<>> END. <> <> <> <<>>