DIRECTORY BasicTime USING [GMT], File USING [FP, Handle, Volume], FS USING [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]; 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]; Version: TYPE = RECORD [CARDINAL]; noVersion: Version = [LAST[CARDINAL]]; highestVersion: Version = noVersion; lowestVersion: Version = [0]; 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: PROCEDURE [ volName: ROPE, nameBodyPattern: Rope.Text, localOnly, allVersions: BOOLEAN, version: Version, matchProc: UNSAFE PROC [entry: EntryPtr] RETURNS [accept, stop: BOOLEAN], acceptProc: PROC RETURNS [stop: BOOLEAN] ]; TextFromTextRep: PROCEDURE [nameBody: LONG POINTER TO TextRep] RETURNS [Rope.Text]; MakeFName: PROCEDURE [nameBody: ROPE, version: Version _ noVersion, prefix: ROPE _ NIL] RETURNS [ROPE]; ScavengeDirectoryAndCache: PROC [ volName: ROPE _ NIL ]; CloseVolume: PROC [v: File.Volume]; GetFileHandle: PROC [file: FS.OpenFile] RETURNS [File.Handle]; FNameFromHandle: PROC [file: File.Handle] RETURNS [ROPE]; EventOp: TYPE = {startRetrieving, endRetrieving, startStoring, endStoring, startFlushing, endFlushing}; EventHandle: TYPE = REF EventObject; EventObject: TYPE; NextEvent: PROC [last: EventHandle _ NIL] RETURNS [fName: ROPE, event: EventOp, this: EventHandle] ; END... pFSBackdoor.mesa Backdoors to the Cedar File System Created by M. D. Schroeder Last Edited by: Schroeder, September 15, 1983 1:56 pm CLIENT-PROVIDED OPEN FILES FS provides a way for clients to implement objects with the TYPE FS.OpenFile. The client provides procedures that implement the operations on an FS.OpenFile. Refer to FS.mesa for the semantics of these procedures. The client procedures should raise FS.Error as appropriate. Client procedures can generate code ATOM's used by FS and can produce additional code ATOM's if needed. FS.Error's with existing code ATOM's should be generated using FSBackdoor.ProduceError (see below). The client is responsible for associating any new code ATOM's with the appropriate FS.ErrorGroup. Note that no locking is done by FS on client-provided FS.OpenFile's. FS produces FS.Error[client, $notImplemented] when an attempt is make to use any client procedures that are NIL. SameFile will only get called for two clientFile's with equal "REF FileProcs". Client errors: none User errors: none Whenever any of the procedures above are called for the FS.OpenFile returned by FSBackdoor.CreateProcsOpenFile, the "clientFile" argument to CreateProcsOpenFile is passed on as the identification of the open file that is to be operated upon. Client errors: none User errors: none If "file" is a client-provided FS.OpenFile then the "clientFile" and "fileProcs" are returned, otherwise NIL is returned for both results. Client errors: $invalidOpenFile User error: none Raises FS.Error for the code ATOM that corresponds lexically to the "code". The FS.ErrorGroup in the error is properly set. The error will contain "explanation". Clients should use this procedure to generate FS.Error's for existing codes to avoid spelling the ATOM's wrong and getting the wrong FS.ErrorGroup. VOLUME SPACE MANAGEMENT FS provides access to the File package procedures for setting the volume freeboard on the system volume and reading the size, free and freeboard counts from a named volume. Client errors: none User errors: $unknownVolume "volName" = NIL means the system volume. Client errors: none User errors: $nonCedarVolume, $unknownVolume MANUAL CACHE MANAGEMENT Like FS.EnumerateForInfo and FS.EnumerateForNames, except that only cached GNames in the named volume are enumerated. "volName" = NIL means the system volume. "pattern" = NIL means to match all names. Client errors: $noCache User errors: $nonCedarVolume, $unknownVolume, $illegalName The specified GName is removed from the directory/cache on the named volume and any associated file on that volume is deleted. "volName" = NIL means the system volume. Locking is done only for the system volume. In this case FS.Error[lock, $lockConflict] is generated when a "write" lock connot be obtained. Flushing a cached file from other than the system volume is done independent of any locks that may be set, so BE SURE YOU KNOW WHAT YOU ARE DOING. No FS.Error occurs if the "fullGName" is not in the cache on the indicated volume Client errors: none User errors: $nonCedarVolume, $unknownVolume DIRECT ACCESS TO THE DIRECTORY/CACHE ON ANY VOLUME The directory of LNames and the cache for GName are implemented together as a BTree on a local volume. The following procedures and TYPES allow direct access to this BTree. A "nameBody" is an FName without a version part. LNames are recorded in the directory/cache without the "[]<>" 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. "highestVersion" and "lowestVersion" are used internally as the representation of !L and !H. An entry in the directory/cache can be gotten at directly via FSBackdoor.Enumerate and the following TYPEs. ******************************************************************************* WARNING: You should treat Entry's as READONLY, though the compiler won't let me say it. ******************************************************************************* "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. Client errors: none User errors: $nonCedarVolume, $unknownVolume If "e" is an "EntryPtr", and "e.t" is a contained "TextRP", then "@e[e.t]" is a "LONG POINTER TO TextRep". Client errors: none User errors: none Makes an FName out of a "nameBody" and "version", and a "prefix". Does not do a syntax check. The prefix is prepended if the nameBody does not start with the character "[". If the nameBody comes from the directory of some named volume other than the system volume, then a prefix of "[]" 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. Client errors: none User errors: none DIRECTORY/CACHE RECONSTRUCTION The directory/cache BTree for the named volume is rebuilt by enumerating the leader pages of all files on the volume and merging in any attached LNames that can be recovered from an existing BTree. "volName" = NIL means the system volume. While scavenging is occuring all FS operations that access the directory will wait. DO NOT call FSBackdoor.CloseVolume first. Client errors: none User errors: $nonCedarVolume, $unknownVolume MISCELLANEOUS OPERATIONS For experts only!!! Tells FS to close any directory/cache BTree it has open for the volume. May cause FS operations in progress to raise various strange BTree and File ERROR's. After CloseVolume returns, new FS operations will try to reopen a directory/cache BTree for the volume. Should be called AFTER a volume is erased. Client errors: none User errors: none For experts only!!! Returns the File.Handle that goes with an FS.OpenFile. Client errors: $invalidOpenFile, $notImplemented (for client-provided FS.OpenFile's) User errors: none Returns the full FName of the named "file". Will raise FS.Error[environment, $invalidPropertyPage] if the handle is not for an FS file. Client errors: none User errors: none An event is the start or conclusion of retrieving, storing, or flushing a global file. A call on NextEvent returns the FName and EventOp for the next event to occur after the "last" event. When "last" is NIL then the next event in time is returned. Will WAIT if necessary. Storing, retrieving and flushing of several files can occur simultaneously. Client errors: none User errors: none Κ "– "cedar" style˜J˜šœ™J˜Jšœ"™"J˜Jšœ™J™J™5J˜—J˜JšΟk œ˜ J˜Jšœ œœ˜Jšœœœ˜ Jšœœ˜šœœœ˜J˜J˜—J˜Jšœ œ ˜Jš˜J˜Jšœœœ˜J˜J™J™™J™J™Jš$œ:œœOœœQœ<œ œ!œœœyœœ.œœœ œ^œ™όJ˜—J˜Jšœ œ˜J˜š|Οnœœž œœœœœœž œœœœœœžœœœœœœžœœœœœœœœ œž œœœ œœžœœœ œœœžœœœœœœœœžœœœœ œœœœžœœœœœœ ˜ΦJ™Jšœ?œ ™NJ™Jšœ™Jšœ™J˜—J˜š žœœœ œ œœ ˜\J™Jšœ8œ·™ρJ™Jšœ™Jšœ™J˜—J˜š žœœœ œœ œ ˜dJ™JšœœHœ™ŠJ™Jšœ ™ Jšœ™J™—J™Iunitšœ œΟcœ©˜ΤK˜šž œœ%œ˜=J™Jš œœœ0œ€œ2œœ™»—J™J™J™™J™J™Jšœ¬™¬—J˜šž œœ œ˜$J™Jšœ™Jšœ™J™—J™š ž œœ  œœœ˜MJ™Jšœ œ™(J™Jšœ™JšœŸœ™-—J™J˜J˜šœ™J˜—J˜Jšžœœœ œœ œœœ œ˜xJ˜šžœœ$œœ˜KJ˜—J˜Jš žœœœ œœ œ˜DJ˜šžœœ$œœ˜LJ˜Jš œœœdœ'œ™ΚJ™Jšœ™JšœŸœŸœ ™;J˜—J˜š žœœ œ œœ˜3J˜JšœŒœUœΐœœœœœœœœœM™žJ™Jšœ™JšœŸœ™-—J™J™J™™2J™J™J™­J™Jšœ³™΄J™—J™Jšœ œœœ˜"Jšœœœ˜&Jšœ$˜$šœ˜J™Jšœ\™\—˜J™J™J™kJ™J™OJ™XJ™O—J™Jšœ œ(Ÿ$˜[J˜Jš œ œœœœœ˜,J˜Jš œœ œœœ ˜4Jšœ œœ œœœœ œœœ˜TJ˜Jš0œœœ œœ  œŸ<œœŸœŸœ œœœœœœœ œ Ÿœ%œœ œ œŸEœ˜ΝK˜šž œ œ œ7œœœœœœœœ˜λJ™Jšœ)œœτœœψœœrœIœ°™™ J™Jšœ™JšœŸœ™-J™—K˜š žœ œ œœœ œ ˜SJ™JšœQœœœ ™jJ™Jšœ™Jšœ™J™—J™šž œ œ œ(œœœœ˜gJ™Jšœέœlœx™ΘJ™Jšœ™Jšœ™—J™J™J™™J™—J˜šžœœ œœ˜8J˜Jš œΣœ<œ2œœ#™οJ™Jšœ™Jšœ-™-—J™J™J™šœ™J™—J˜šž œœ˜#J˜Jš œœKœ@œ$œYœ™ΘJ™Jšœ™Jšœ™J™—J™šž œœœ œ˜>J˜Jšœ?œ ™KJ™Jšœ Ÿœ%œ ™UJšœ™J™—J˜šžœœœœ˜9J˜Jšœ8œFœ™ˆJ™Jšœ™Jšœ™J˜—J˜Jšœ œZ˜gJšœ œœ ˜$Jšœ œ˜J˜š ž œœœœ œ&˜dJ˜JšœXœuœ0œ\™αJ™Jšœ™Jšœ™J˜—J˜Jšœ˜J˜J˜J˜—…—’:4