DIRECTORY BasicTime USING [ GMT, nullGMT ], Booting USING [ Boot, Switches ], DefaultRemoteNames USING [Get], Disk USING [ok], File USING [Delete, Error, FindVM, FP, GetVolumeName, Handle, Info, LogicalInfo, nullFP, Open, RC, SystemVolume, Volume, VolumeFile], FileBackdoor USING [GetRoot, IsDebugger, SetRoot], FileInternal USING [EnumeratePages, EnumeratePagesProc, FreeRun, GetBadPages, IsUsed, SetPageUsed, VolumeObject], FS USING [BytesForPages, Close, ComponentPositions, Copy, EnumerateForInfo, EnumerateForNames, Error, ExpandName, FileInfo, InfoProc, Lock, NameProc, Open, OpenFile, Rename, SetByteCountAndCreatedTime, SetKeep, SetDefaultWDir ], FSBackdoor USING [CreateFileProcs, CreateProcsOpenFile, EnumerateCacheForNames, Flush, GetFileHandle, NameProc, ScavengeDirectoryAndCache ], FSRemoteFile USING [ Retrieve ], GermSwap USING [ Switch ], IagoCommands, IagoOps --USING everything--, IO USING [ Close, Error, PutChar, PutF, PutF1, PutRope, RIS, RopeFromROS, ROS, SetIndex, STREAM, UnsafeGetBlock ], Loader USING [ Error, IRItem, Instantiate, Start], PhysicalVolume USING [ SetPhysicalRoot, SubVolumeDetails ], PrincOps USING [ ControlModule, NullControl], Rope USING [ Cat, Equal, Fetch, Find, Index, Length, ROPE, Run, Substr ], SimpleTerminal USING [TurnOff, TurnOn], UserCredentials USING [ChangeState, Login, LoginOptions], VM USING [PagesForBytes], VolumeFormat USING [Attributes, LogicalPage]; IagoCommands2Impl: CEDAR PROGRAM IMPORTS Booting, DefaultRemoteNames, File, FileBackdoor, FileInternal, FS, FSBackdoor, FSRemoteFile, IagoOps, IO, Loader, PhysicalVolume, Rope, SimpleTerminal, UserCredentials, VM EXPORTS IagoCommands, File SHARES File = { ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; myOpenFileRec: TYPE = RECORD [ strm: STREAM, created: BasicTime.GMT, bytes: INT, pages: INT ]; myOpenFile: TYPE = REF myOpenFileRec; Volume: TYPE = REF VolumeObject; -- File -- VolumeObject: PUBLIC TYPE = FileInternal.VolumeObject; FlushCache: PUBLIC PROC [in, out: STREAM] = { count: INT _ 0; DoName: FSBackdoor.NameProc = { count _ count+1; IO.PutF1[out, "\nFlushing %g ... ", [rope[fullGName]]]; { ENABLE FS.Error => { IO.PutRope[out, error.explanation]; CONTINUE }; FSBackdoor.Flush[fullGName: fullGName, volName: volName]; IO.PutRope[out, "done"]; }; RETURN[TRUE]; }; v: File.Volume = IagoOps.GetLogical[in, out, "On "]; volName: ROPE = File.GetVolumeName[v]; pattern: ROPE _ IagoOps.GetFile[in: in, out: out, pattern: TRUE]; IO.PutRope[out, " ... "]; FSBackdoor.EnumerateCacheForNames[DoName, volName, pattern]; IF count = 0 THEN IO.PutRope[out, "not found"] ELSE IO.PutF1[out, "\n%g files", [integer[count]] ]; }; InstallCredentials: PUBLIC PROC [in, out: STREAM] = { IO.PutRope[out, "\nDo you want to password-protect this disk? "]; [] _ UserCredentials.ChangeState[IF IagoOps.Confirm[in, out] THEN name ELSE nameHint]; }; InstallLogicalFile: PUBLIC PROC [in, out: STREAM, which: File.VolumeFile[checkpoint..bootFile]] = { v: File.Volume = IagoOps.GetLogical[in, out, "For "]; localVolume: ROPE = Rope.Cat["[]<", File.GetVolumeName[v], ">"]; createTime: BasicTime.GMT; name: ROPE = IagoOps.GetFile[ in: in, out: out, extension: IagoOps.ext[which], default: IagoOps.RemoteRootFileName[which], wDir: localVolume, check: TRUE ]; localName: ROPE _ name; fsFile: FS.OpenFile; file: File.Handle; PhysicalToo: PROC RETURNS[BOOL] = { IF which # bootFile THEN { IO.PutRope[out, "\nInstalling on the physical volume"]; RETURN[TRUE]; }; IF FileBackdoor.IsDebugger[v] THEN RETURN[FALSE]; IO.PutRope[out, "\nDo you want to use this file when you boot the physical volume? "]; RETURN[IagoOps.Confirm[in, out]] }; IO.PutRope[out, " ... "]; IF name.Length[] # 0 AND name.Fetch[0] = '[ AND Rope.Run[s1: name, s2: localVolume, case: FALSE] # localVolume.Length[] AND ( v # File.SystemVolume[] OR Rope.Run[s1: name, s2: "[]<>"] # 4 ) THEN { Help: PROC = { IO.PutRope[out, "? Please type the name of an FS local file such as \"a.b\""]; }; localName _ IagoOps.LocalRootFileName[which]; IO.PutRope[out, IF name.Length[] >=1 AND name.Fetch[1] = '] THEN "that file is on another volume ..." ELSE "that file is on a server ..."]; DO localName _ IagoOps.GetArg[ in: in, out: out, prompt: "\nCopy to local file name (please confirm or alter): ", default: localName, help: Help]; IF localName.Length[] = 0 OR localName.Fetch[0] = '[ THEN Help[] ELSE EXIT; ENDLOOP; IO.PutRope[out, " ... copying ... "]; [] _ FS.Copy[from: name, to: localName, wDir: localVolume]; }; createTime _ FS.FileInfo[name: localName, wDir: localVolume].created; fsFile _ FS.Open[name: localName, lock: write, wDir: localVolume]; file _ FSBackdoor.GetFileHandle[fsFile]; IF File.Info[file].volume # v THEN IO.PutRope[out, "I'm confused: the file is on the wrong volume"] ELSE { IO.PutRope[out, "installing ... "]; FileBackdoor.SetRoot[which, file]; FS.SetByteCountAndCreatedTime[file: fsFile, created: createTime]; IO.PutRope[out, "done"]; }; FS.Close[fsFile]; IF PhysicalToo[] THEN { PhysicalVolume.SetPhysicalRoot[v, which]; IO.PutRope[out, " ... done"] }; }; ListCache: PUBLIC PROC [in, out: STREAM] = { count: INT _ 0; DoName: FSBackdoor.NameProc = { count _ count+1; IO.PutF1[out, "\n %g", [rope[fullGName]]]; RETURN[TRUE]; }; v: File.Volume = IagoOps.GetLogical[in, out, "On "]; pattern: ROPE _ IagoOps.GetFile[in: in, out: out, pattern: TRUE]; IO.PutRope[out, " ... "]; FSBackdoor.EnumerateCacheForNames[DoName, File.GetVolumeName[v], pattern]; IF count = 0 THEN IO.PutRope[out, "not found"] ELSE IO.PutF1[out, "\n%g files", [integer[count]] ]; }; ListFileInfo: PUBLIC PROC [in, out: STREAM] = { count: INT _ 0; DoName: FS.InfoProc = { count _ count+1; IO.PutF[out, "\n %g, keep: %g, bytes: %g, created: %g", [rope[fullFName]], [cardinal[keep]], [integer[bytes]], [time[created]] ]; IF attachedTo # NIL THEN IO.PutF1[out, ", attached to %g", [rope[attachedTo]] ]; RETURN[TRUE]; }; pattern: ROPE _ IagoOps.GetFile[in: in, out: out, pattern: TRUE]; IO.PutRope[out, " ... "]; FS.EnumerateForInfo[pattern, DoName]; IF count = 0 THEN IO.PutRope[out, "not found"] ELSE IO.PutF1[out, "\n%g files", [integer[count]] ]; }; ListNames: PUBLIC PROC [in, out: STREAM] = { count: INT _ 0; prevFile: ROPE _ NIL; DoName: FS.NameProc = { newFile, newPrefix: ROPE; newPos: FS.ComponentPositions; count _ count+1; [fullFName: newFile, cp: newPos] _ FS.ExpandName[fullFName]; newPrefix _ fullFName.Substr[len: newPos.ver.start]; IF prevFile # NIL AND newPos.ver.length # 0 AND prevFile.Equal[newPrefix, FALSE] THEN IO.PutF1[out, ", %g", [rope[fullFName.Substr[start: newPos.ver.start, len: newPos.ver.length]]] ] ELSE { prevFile _ newPrefix; IO.PutF1[out, "\n%g", [rope[fullFName]]]; }; RETURN[TRUE]; }; pattern: ROPE _ IagoOps.GetFile[in: in, out: out, pattern: TRUE]; IO.PutRope[out, " ... "]; FS.EnumerateForNames[pattern, DoName]; IF count = 0 THEN IO.PutRope[out, "not found"] ELSE IO.PutF1[out, "\n%g files", [integer[count]] ]; }; Login: PUBLIC PROC [options: UserCredentials.LoginOptions] = { TurnOnProc: PROC RETURNS [in, out: STREAM] = { [in: in, out: out] _ SimpleTerminal.TurnOn[]; IO.PutRope[out, "\nPlease login ...\n"]; }; TurnOffProc: PROC [in, out: STREAM] = { SimpleTerminal.TurnOff[] }; UserCredentials.Login[startInteraction: TurnOnProc, endInteraction: TurnOffProc, options: options]; }; RecomputeVAM: PUBLIC PROC[in, out: STREAM] = { NowPage: FileInternal.EnumeratePagesProc = TRUSTED { attr: VolumeFormat.Attributes = LOOPHOLE[label.attributes]; SELECT TRUE FROM status # Disk.ok => { badStatus _ badStatus + 1; }; attr = header => { IF FileInternal.IsUsed[volume: volume, page: da] THEN headers _ headers + 1 ELSE { freeHeaders _ freeHeaders + 1; [] _ FileInternal.SetPageUsed[volume: volume, page: da, inUse: TRUE]; }; }; attr = data => { IF FileInternal.IsUsed[volume: volume, page: da] THEN datas _ datas + 1 ELSE { freeDatas_ freeDatas + 1; [] _ FileInternal.SetPageUsed[volume: volume, page: da, inUse: TRUE]; }; }; attr = freePage => { diskaddr: INT = LOOPHOLE[da]; IF label.filePage # diskaddr THEN { badFreeLabels _ badFreeLabels+1; IF lastBadFreeLabel+1 # diskaddr THEN { badFreeLabelRuns _ badFreeLabelRuns+1; IF listBadFreeLabels THEN out.PutRope["--"]; }; lastBadFreeLabel _ diskaddr; IF listBadFreeLabels THEN out.PutF[ "(%g)", [integer[diskaddr]] ]; IF fixBadFreeLabels THEN FileInternal.FreeRun[[da,1], volume, label] ELSE [] _ FileInternal.SetPageUsed[volume: volume, page: da, inUse: TRUE]; } ELSE IF FileInternal.IsUsed[volume: volume, page: da] THEN { freeMissings _ freeMissings + 1; [] _ FileInternal.SetPageUsed[volume: volume, page: da, inUse: FALSE]; } ELSE frees _ frees + 1; }; ENDCASE => { IF FileInternal.IsUsed[volume: volume, page: da] THEN others _ others + 1 ELSE { freeOthers_ freeOthers + 1; [] _ FileInternal.SetPageUsed[volume: volume, page: da, inUse: TRUE]; }; }; deltaPages _ deltaPages + 1; IF deltaPages >= 1000 THEN { thousandsCount _ thousandsCount + 1; IF thousandsCount >= 10 THEN { IO.PutRope[out, "!"]; thousandsCount _ 0; } ELSE IO.PutRope[out, "."]; deltaPages _ 0; }; exit _ FALSE; }; countBadPages: CARDINAL _ 0; badPageWorkProc: PROC [page: VolumeFormat.LogicalPage] = TRUSTED { IF NOT FileInternal.SetPageUsed[volume: volume, page: page, inUse: TRUE].wasInUse THEN countBadPages _ countBadPages+1; }; volume: File.Volume = IagoOps.GetLogical[in, out]; volumeFree: INT; volumeSize: INT; badStatus: INT _ 0; thousandsCount: INT _ 0; deltaPages: INT _ 0; headers, freeHeaders, datas, freeDatas, freeMissings, frees, others, freeOthers: INT _ 0; badFreeLabels, lastBadFreeLabel, badFreeLabelRuns: INT _ 0; fixBadFreeLabels, listBadFreeLabels: BOOL _ FALSE; [size: volumeSize, free: volumeFree] _ File.LogicalInfo[volume ! File.Error => { IO.PutRope[out, "LogicalInfo for volume error  "]; IO.PutRope[out, IagoOps.FileError[why]]; }; ]; IO.PutRope[out, "\nRepair bad labels on free pages? "]; fixBadFreeLabels _ IagoOps.Confirm[in,out]; IO.PutRope[out, "\nList pages with bad labels as they are encountered? "]; listBadFreeLabels _ IagoOps.Confirm[in,out]; IO.PutRope[out, "\n Scan started "]; TRUSTED { FileInternal.EnumeratePages[volume: volume, start: [0], skipBadPages: FALSE, work: NowPage]; }; TRUSTED { volumeAlias: Volume; volumeAlias _ volume; FOR sv: LIST OF PhysicalVolume.SubVolumeDetails _ volumeAlias.subVolumes, sv.rest UNTIL sv = NIL DO FileInternal.GetBadPages [subVolume: sv.first, work: badPageWorkProc] ; ENDLOOP; }; out.PutF["\n Volume has %s pages with %g pages free in the VAM\n", [integer[volumeSize]], [integer[volumeFree-countBadPages]] ]; IF badStatus > 0 THEN out.PutF[" %g pages had read errors\n", [integer[badStatus]]]; out.PutF["Statisitics on mismatches from scan:\n"]; out.PutF[" Header pages %g (%g free in VAM), Data pages %g (%g free in VAM) \n", [integer[headers]], [integer[freeHeaders]], [integer[datas]], [integer[freeDatas]] ]; out.PutF[" Other pages %g (%g free in VAM), Free pages %g (%g not free in VAM) \n", [integer[others]], [integer[freeOthers]], [integer[frees]], [integer[freeMissings]] ]; out.PutF[" Free pages with bad labels %g (in %g runs) which were %gfixed\n", [integer[badFreeLabels]], [integer[badFreeLabelRuns]], [rope[IF fixBadFreeLabels THEN "" ELSE "not "]] ]; }; Rename: PUBLIC PROC [in, out: STREAM] = { from: ROPE = IagoOps.GetFile[in: in, out: out, prompt: "From ", check: TRUE]; to: ROPE = IagoOps.GetFile[in: in, out: out, prompt: "To "]; IO.PutRope[out, " ... "]; FS.Rename[from: from, to: to]; IO.PutRope[out, "done"]; }; Rollback: PUBLIC PROC [in, out: STREAM] = { v: File.Volume = IagoOps.GetLogical[in, out]; reject: ROPE; mySwitches: Booting.Switches _ ALL[FALSE]; mySwitches[r] _ TRUE; reject _ Booting.Boot[[logical[v]], mySwitches]; IF reject # NIL THEN { IO.PutRope[out, " ... couldn't: "]; IO.PutRope[out, reject] }; }; RunDiagnosticBCD: PUBLIC PROC [in, out: STREAM] = { loadedOK: BOOL _ TRUE; fName: ROPE; cp: FS.ComponentPositions; fsFile: FS.OpenFile; strm: STREAM _ NIL; tryNoCache: BOOL _ FALSE; remoteOnly: BOOL _ FALSE; cm: PrincOps.ControlModule; unboundImports: LIST OF Loader.IRItem; default: ROPE _ Rope.Cat[DefaultRemoteNames.Get[].current, "Iago>ExtraIago.bcd"]; IO.PutRope[out, "\nAvoid using the local disk for caching the bcd file? "]; remoteOnly _ IagoOps.Confirm[in, out]; fName_ IagoOps.GetFile[in: in, out: out, prompt: "FileName ", default: default, check: ~remoteOnly]; IF ~remoteOnly THEN fsFile_ FS.Open[fName ! FS.Error => { IF error.code = $noCache OR error.code = $badBTree THEN { tryNoCache _ TRUE; CONTINUE; }; IO.PutRope[out, error.explanation]; GOTO noFile; }; ]; IF tryNoCache OR remoteOnly THEN { fullFName: ROPE; bytesOnServer: INT; pagesOnServer: INT _ 0; createdTime: BasicTime.GMT; myfsFile: myOpenFile; ProduceStream: PROC[fullGName: ROPE, bytes: INT, created: BasicTime.GMT] RETURNS [STREAM] = { pagesOnServer_ VM.PagesForBytes[bytes]; bytesOnServer _ bytes; createdTime _ created; RETURN[strm_ IO.ROS[]]; }; [fullFName, cp, ]_ FS.ExpandName[fName]; FSRemoteFile.Retrieve[fullFName.Substr[cp.server.start, cp.server.length], fullFName.Substr[cp.dir.start-1], BasicTime.nullGMT, ProduceStream ! FS.Error => { out.PutChar['\n]; out.PutRope[error.explanation]; GO TO noFile}]; IF strm = NIL THEN {out.PutRope["\n Can't retreive file"]; GO TO noFile}; strm_ IO.RIS[IO.RopeFromROS[strm], strm]; myfsFile _ NEW [myOpenFileRec _ [strm, createdTime, bytesOnServer, pagesOnServer]]; fsFile _ FSBackdoor.CreateProcsOpenFile[clientFile: myfsFile, fileProcs: FSBackdoor.CreateFileProcs[GetInfo: streamInfo, Read: streamReader] ]; }; out.PutRope[" ... "]; TRUSTED { [cm, unboundImports]_ Loader.Instantiate[fsFile ! Loader.Error => { IO.PutRope[out, message]; loadedOK _ FALSE; cm_ PrincOps.NullControl; CONTINUE; }; ]; }; IF unboundImports#NIL THEN { IO.PutRope[out, "\nThere are unbound imports; confirm to start the code anyway? "]; IF ~IagoOps.Confirm[in, out] THEN RETURN; }; TRUSTED { IF cm # PrincOps.NullControl THEN Loader.Start[cm ! ABORTED => { loadedOK _ FALSE; IO.PutRope[out, "Loader.Start was ABORTED"]; CONTINUE; }; ]; }; IF loadedOK THEN IO.PutRope[out, "Loaded and Started\n"]; FS.Close[fsFile ! FS.Error => CONTINUE]; IF strm # NIL THEN strm.Close[ ! IO.Error => CONTINUE]; EXITS noFile => NULL; }; Scavenge: PUBLIC PROC [in, out: STREAM] = { v: File.Volume = IagoOps.GetLogical[in, out]; volumeFreePages: INT; rootStatus: File.RC; fsRootFP: File.FP; fsRootSize: INT _ 900; [rootStatus: rootStatus, free: volumeFreePages] _ File.LogicalInfo[v]; SELECT rootStatus FROM ok => NULL; nonCedarVolume => { IO.PutRope[out, "\nVolume is not a Cedar Volume"]; RETURN; }; wentOffline => { IO.PutRope[out, "\nVolume went offline"]; RETURN; }; inconsistent => { IO.PutRope[out, "\nRoot page is inconsistent (wrong version?)"]; RETURN; }; software => { IO.PutRope[out, "\nCan't find the volume root page (label-check)"]; RETURN; }; hardware => { IO.PutRope[out, "\nHard disk error reading the volume root page"]; RETURN; }; ENDCASE => ERROR File.Error[rootStatus]; fsRootFP _ FileBackdoor.GetRoot[v, client].fp; -- client is the client file system: FS IF fsRootFP # File.nullFP THEN { file: File.Handle _ File.Open[v, fsRootFP ! File.Error => GO TO nope]; fsRootSize _ File.Info[file ! File.Error => CONTINUE].size; EXITS nope => {}; }; IF (fsRootSize + 200) > volumeFreePages THEN { checkpointFP: File.FP; checkpointFile: File.Handle _ NIL; checkpointFP _ FileBackdoor.GetRoot[v, checkpoint].fp; checkpointFile _ File.Open[v, checkpointFP ! File.Error => CONTINUE]; IF checkpointFile = NIL THEN { IO.PutRope[out, "\nThere appears not to be enough room to scavenge and there is not a checkpoint to delete. Continue? "]; IF NOT IagoOps.Confirm[in, out] THEN RETURN; } ELSE { IO.PutRope[out, "\nThere appears not to be enough room to scavenge. OK to delete checkpoint? "]; IF IagoOps.Confirm[in, out] THEN { status: File.RC _ ok; File.Delete[checkpointFile ! File.Error => { status _ why; CONTINUE;}]; IO.PutRope[out, IF status = ok THEN "\nCheckpoint file has been deleted" ELSE "\nError in delete. Checkpoint file has NOT been deleted."]; }; }; checkpointFile _ NIL; }; IO.PutRope[out, " Scavenging ... "]; [] _ File.FindVM[]; FSBackdoor.ScavengeDirectoryAndCache[File.GetVolumeName[v]]; IO.PutRope[out, "done"]; }; SetKeep: PUBLIC PROC [in, out: STREAM] = { count: INT _ 0; DoName: FS.NameProc = { count _ count+1; fullFName _ fullFName.Substr[start: 0, len: fullFName.Index[0, "!"]]; IO.PutF1[out, "\nSetting %g ... ", [rope[fullFName]]]; { ENABLE FS.Error => { IO.PutRope[out, error.explanation]; CONTINUE }; FS.SetKeep[fullFName, k]; IO.PutRope[out, "done"]; }; RETURN[TRUE]; }; pattern: ROPE _ IagoOps.GetFile[ in: in, out: out, pattern: TRUE, prompt: "For "]; k: INT = IagoOps.GetNumber[ in, out, 1, LAST[CARDINAL]-1, "\nNumber of versions to keep: ", "? Type how many versions of each file should be kept (excess versions will be deleted)"]; IF Rope.Find[pattern, "!"] < 0 THEN pattern _ pattern.Cat["!H"]; IO.PutRope[out, " ... "]; FS.EnumerateForNames[pattern, DoName]; IF count = 0 THEN IO.PutRope[out, "not found"] ELSE IO.PutF1[out, "\n%g files", [integer[count]] ]; }; SetPhysicalFile: PUBLIC PROC [in, out: STREAM, which: File.VolumeFile[checkpoint..bootFile]] = { v: File.Volume = IagoOps.GetLogical[in, out, "From "]; IO.PutRope[out, " ... "]; PhysicalVolume.SetPhysicalRoot[v, which]; IO.PutRope[out, "done"]; }; SetWDir: PUBLIC PROC [in, out: STREAM] = { Help: PROC = { IO.PutRope[out, "? Type the prefix of a file name, such as \"[]\""]; }; name: ROPE = IagoOps.GetArg[ in: in, out: out, prompt: "\nWorking directory: ", default: IF IagoOps.clientVolName.Length[] # 0 THEN Rope.Cat["[]<", IagoOps.clientVolName, ">"] ELSE NIL, help: Help]; FS.SetDefaultWDir[name]; }; streamInfo: PROC [clientFile: REF] RETURNS [keep: CARDINAL, pages, bytes: INT, created: BasicTime.GMT, lock: FS.Lock] = { myfsFile: myOpenFile = NARROW[clientFile, myOpenFile]; keep _ 1; pages _ myfsFile.pages; bytes _ myfsFile.bytes; created _ myfsFile.created; lock _ read; }; streamReader: UNSAFE PROC [clientFile: REF, from, nPages: INT, to: LONG POINTER] = TRUSTED { strm: STREAM = NARROW[clientFile, myOpenFile].strm; strm.SetIndex[FS.BytesForPages[from]]; [] _ strm.UnsafeGetBlock[[base: LOOPHOLE[to], startIndex: 0, count: FS.BytesForPages[nPages]]]; }; }. IagoCommands2Impl.mesa - Iago commands implementation Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Andrew Birrell December 7, 1983 4:07 pm Levin, September 22, 1983 1:32 pm Willie-Sue, May 10, 1985 4:34:28 pm PDT Bob Hagmann October 14, 1985 1:01:12 pm PDT Russ Atkinson (RRA) July 22, 1985 7:16:05 pm PDT Carl Hauser, November 18, 1985 5:42:30 pm PST ******** The command subroutines (alphabetic order) ******** "name" is a canonicalized FS name. See what local name the user would like PROC[status: Disk.Status, da: VolumeFormat.LogicalPage, label: POINTER TO Disk.Label] RETURNS[exit: BOOL _ FALSE]; Bad pages may have been marked FREE in the VAM. Make sure they are marked InUse. check to see if there is (probably) enough room for a new FS BTree not enough room - see if checkpoint exists, and ask if we can delete it Utilities Bob Hagmann April 30, 1985 12:07:30 pm PDT add "Fake FS" inside of RunDiagnosticBCD; new command RecomputeVAM changes to: RunDiagnosticBCD, RecomputeVAM Bob Hagmann June 13, 1985 8:15:25 am PDT changed Scavenge to try to delete checkpoint if there is not enough room for a new FS BTree Bob Hagmann October 14, 1985 12:59:57 pm PDT changes to: RunDiagnosticBCD, ProduceStream (local of RunDiagnosticBCD) Κ:˜codešœ5™5Kšœ Οmœ7™BKšœ(™(K™!K™'K™+K™0K™-—K™šΟk ˜ Kšœ žœžœ ˜!Kšœžœ˜!Kšœžœ˜Kšœžœ˜Kšœžœžœ:žœ$˜…Kšœ žœ ˜2Kšœ žœ_˜qKšžœžœά˜δKšœ žœ|˜ŒKšœ žœ˜ Kšœ žœ ˜K˜ KšœΟcœ˜Kš žœžœ0žœžœ žœ˜rKšœžœ&˜2Kšœžœ'˜;Kšœ žœ˜-Kšœžœ+žœ˜IKšœžœ˜'Kšœžœ$˜9Kšžœžœ˜Kšœ žœ˜-—K˜šœžœž˜ Kšžœ@žœ%žœAž˜³Kšžœ˜Kšžœ ˜K˜Kšžœžœžœ˜Kšžœžœžœžœ˜K˜šœžœžœ˜Kšœžœ˜ Kšœžœ˜Kšœžœ˜ Kšœž˜ K˜—Kšœ žœžœ˜%Icode1šœžœžœ˜ LšŸ œžœžœ˜AK˜—˜K˜—šœJ™JK˜šΟn œžœžœ žœ˜-Kšœžœ˜šœ˜Kšœ˜Kšžœ5˜7šœ˜Kšžœžœ žœ"žœ˜DKšœ9˜9Kšžœ˜Kšœ˜—Kšžœžœ˜ Kšœ˜—K˜4Kšœ žœ˜&Kšœ žœ.žœ˜AKšžœ˜Kšœ<˜<šžœ ˜ Kšžœžœ˜!Kšžœžœ-˜4—Kšœ˜—K˜š œžœžœ žœ˜5šžœ ˜Kšœ1˜1—Kšœ!žœžœžœ ˜VKšœ˜—K˜š œžœžœ žœ3˜cK˜5Kšœ žœ/˜@Kšœžœ˜šœžœ˜Kšœ0˜0Kšœ+˜+Kšœž˜K˜—Kšœ žœ˜Kšœžœ ˜K˜š  œžœžœžœ˜#šžœžœ˜Kšžœ5˜7Kšžœžœ˜ Kšœ˜—Kšžœžœžœžœ˜1KšžœT˜VKšžœ˜ Kšœ˜—Kšœ"™"Kšžœ˜šžœ˜Kšžœ˜Kšžœ+žœ˜KKšžœžœ%˜Ešžœ˜š œžœ˜KšžœL˜NKšœ˜—Kšœ-˜-šžœžœžœ˜;Kšžœ%˜)Kšžœ!˜%—Kšœ'™'šž˜šœ˜K˜K˜ K˜@K˜K˜ —Kš žœžœžœžœžœ˜K—Kšžœ˜Kšžœ#˜%Kšœžœ4˜;Kšœ˜——Kšœ žœ6˜EKšœ žœ7˜BKšœ(˜(šžœ˜Kšžœžœ>˜Ešžœ˜Kšžœ!˜#Kšœ"˜"Kšžœ?˜AKšžœ˜Kšœ˜——Kšžœ˜šžœžœ˜Kšœ)˜)Kšžœ˜—Kšœ˜—K˜š  œžœžœ žœ˜,Kšœžœ˜šœ˜Kšœ˜Kšžœ)˜+Kšžœžœ˜ Kšœ˜—K˜4Kšœ žœ.žœ˜AKšžœ˜KšœJ˜Jšžœ ˜ Kšžœžœ˜!Kšžœžœ-˜4—Kšœ˜—K˜š  œžœžœ žœ˜/Kšœžœ˜šœžœ ˜Kšœ˜Kšžœ€˜‚Kšžœžœžœžœ5˜PKšžœžœ˜ Kšœ˜—Kšœ žœ.žœ˜AKšžœ˜Kšžœ#˜%šžœ ˜ Kšžœžœ˜!Kšžœžœ-˜4—Kšœ˜—K˜š  œžœžœ žœ˜,Kšœžœ˜Kšœ žœžœ˜šœžœ ˜Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ#žœ˜š  œžœžœ žœ˜.Kšœ-˜-Kšžœ&˜(K˜—š  œžœ žœ˜'Kšœ˜Kšœ˜—šœP˜PKšœ˜—Kšœ˜—K˜š  œžœžœ žœ˜.šΟbœ$žœ˜4Lš žœ;žœžœ žœžœžœ™rLšœ žœ˜;šžœžœž˜Jšœ3˜3šœ˜šžœ.˜0Jšžœ˜šžœ˜Jšœ˜Jšœ?žœ˜EJ˜——Jšœ˜—šœ˜šžœ.˜0Jšžœ˜šžœ˜Jšœ˜Jšœ?žœ˜EJ˜——Jšœ˜—šœ˜Jšœ žœžœ˜šžœžœ˜#K˜ šžœžœ˜'Kšœ&˜&Kšžœžœ˜,K˜—Kšœ˜Kšžœžœ)˜BKšžœžœ,˜DKšžœ@žœ˜JKšœ˜—šžœ.˜5šžœ˜Jšœ ˜ Jšœ?žœ˜FJ˜—Jšžœ˜—Jšœ˜—šžœ˜ šžœ.˜0Jšžœ˜šžœ˜Jšœ˜Jšœ?žœ˜EJ˜——Jšœ˜——Lšœ˜šžœžœ˜Lšœ$˜$šžœ˜šžœ˜Lšžœ˜Lšœ˜L˜—Lšžœžœ˜—Lšœ˜L˜—Lšœžœ˜ L˜L˜—Kšœžœ˜š‘œžœ$žœ˜BKšžœžœ=žœ žœ!˜wK˜K˜—Lšœ2˜2Lšœ žœ˜Lšœ žœ˜Lšœ žœ˜Lšœžœ˜Lšœ žœ˜LšœQžœ˜YLšœ;˜;Lšœ%žœž˜2šœP˜PLšžœ1˜3Kšžœ&˜(Lšœ˜—Lšœ˜Kšžœ5˜7Kšœ+˜+KšžœH˜JKšœ,˜,Lšžœ"˜$šžœ˜ LšœFžœ˜\L˜L˜—Lšœžœžœ#™Qšžœ˜ Kšœ˜Lšœ˜š žœžœžœCžœžœž˜cKšœG˜GKšžœ˜—K˜K˜—šœC˜CLšœ=˜=—Lšžœžœ@˜ULšœ3˜3šœQ˜QLšœU˜U—šœT˜TLšœV˜V—˜MLšœ=žœžœžœ ˜i—Kšœ˜—K˜š œžœžœ žœ˜)Kšœžœ>žœ˜NKšœžœ5˜=Kšžœ˜Kšžœ˜Kšžœ˜Kšœ˜—K˜š œžœžœ žœ˜+Kšœ-˜-Kšœžœ˜ Kšœžœžœ˜*Kšœžœ˜Kšœ0˜0Kš žœ žœžœžœ"žœ˜UKšœ˜—K˜š œžœžœ žœ˜3Kšœ žœžœ˜Kšœžœ˜ Kšœžœ˜Kšœžœ ˜Kšœžœžœ˜Kšœ žœžœ˜Kšœ žœžœ˜Kšœ˜Kšœžœžœ˜&Kšœ žœE˜RKšžœI˜KKšœ&˜&KšœWžœ ˜dšžœ žœ žœ ˜)šœžœ ˜šžœžœžœ˜9Kšœ žœ˜Kšžœ˜ K˜—Kšžœ!˜#Kšžœ˜ Kšœ˜—Kšœ˜—šžœ žœ žœ˜"Kšœ žœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ˜š  œžœ žœ žœžœžœžœ˜]Kšœžœ˜'Kšœ˜Kšœ˜Kšžœžœžœ˜Kšœ˜—Kšœžœ˜(šœ˜šœžœ ˜ Kšœ4žœžœ ˜C——Kš žœžœžœ)žœžœ ˜IKšœžœžœžœ˜)Kšœ žœE˜SKšœ˜K˜—Kšœ˜šžœ˜ šœ/˜/šœ˜Kšžœ˜Kšœ žœ˜Kšœ˜Kšžœ˜ Kšœ˜—Kšœ˜—Kšœ˜—šžœžœžœ˜KšžœQ˜SKšžœžœžœ˜)Kšœ˜—šžœ˜ šžœžœžœ˜AKšœ žœ˜Kšžœ*˜,Kšžœ˜ K˜—Kšœ˜Kšœ˜—Kšžœ žœžœ&˜9Kšžœžœ žœ˜(Kš žœžœžœžœ žœ˜7šž˜Kšœ žœ˜—Kšœ˜—K˜š œžœžœ žœ˜+Kšœ-˜-Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ˜K˜KšœF˜Fšžœ ž˜Kšœžœ˜ šœ˜Kšžœ0˜2Kšžœ˜Kšœ˜—šœ˜Kšžœ'˜)Kšžœ˜Kšœ˜—šœ˜Kšžœ>˜@Kšžœ˜Kšœ˜—šœ ˜ KšžœA˜CKšžœ˜Kšœ˜—šœ ˜ Kšžœ@˜BKšžœ˜Kšœ˜—Kšžœžœ˜(—Kšœ0Ÿ'˜Wšžœžœ˜ Kšœ:žœžœ˜FKšœ,žœ˜;Kšžœ ˜K˜—K™Bšžœ&žœ˜.KšœG™GKšœžœ˜Kšœžœ˜"Kšœ6˜6Kšœ;žœ˜Ešžœžœžœ˜Kšžœx˜zKšžœžœžœžœ˜,K˜—šœžœ˜Kšžœ_˜ašžœžœ˜"Kšœ žœ˜Kšœ;žœ˜Gšžœžœ ˜Kšžœ%˜)Kšžœ>˜B—Kšœ˜—K˜—Kšœžœ˜K˜—Kšžœ"˜$Kšœ˜Kšœ<˜