-- VultureDriver.mesa -- Scavanger for Mail Archive files. -- Maurice Herlihy August 7, 1982 -- Mike Schroeder April 8, 1983 10:21 am DIRECTORY BodyDefs, CIFS, File, IO, IOExtras, Menus, Process, Rope, Space, UserExec, ViewerClasses, ViewerIO, ViewerOps, VMDefs, VultureDefs, VultureOps; VultureDriver: MONITOR IMPORTS CIFS, File, IO, IOExtras, Menus, Process, Rope, Space, UserExec, ViewerIO, ViewerOps, VultureOps = { ROPE: TYPE = Rope.ROPE; Vulture: PROC[fileName: Rope.ROPE, inTS, outTS: IO.STREAM] = { msgIndex, msgsDeleted, directoriesFixed, badMessages: INT _ 0; itemStream: VultureOps.ItemStream; dirStream: VultureOps.DirStream _ NIL; directory: VultureDefs.Directory _ NIL; file: CIFS.OpenFile; fc: File.Capability ; filePages: INT; start, size: INT; oldStart, oldSize: INT; space: Space.Handle; outTS.PutRope[IO.PutFR["\nOpening %g ... ", IO.rope[fileName]]]; file _ CIFS.Open[name: fileName, mode: CIFS.read+CIFS.write]; fc _ CIFS.GetFC[file]; filePages _ File.GetSize[fc] - 1; -- don't mess with the header page outTS.PutRope[IO.PutFR[" %g pages", IO.int[filePages]]]; IF filePages = 0 THEN {outTS.PutRope["Ignoring empty file\n"]; RETURN}; space _ Space.Create[size: filePages, parent: Space.virtualMemory]; Space.Map[space: space, window: Space.WindowOrigin[file: fc, base: 1]]; Space.CreateUniformSwapUnits[parent: space]; {ENABLE {VultureOps.EndOfStream => GOTO Done}; itemStream _ VultureOps.OpenItemStream[space]; dirStream _ VultureOps.OpenDirStream[space]; DO messageBad, dirBad, alreadyDeleted: BOOL _ FALSE; directory _ VultureOps.NextDirectory[dirStream]; [start, size] _ ReadMessage[itemStream -- make sure that the last directory entry is deleted -- ! VultureOps.EndOfStream => directory.bodyStart _ 0]; oldStart _ directory.bodyStart; oldSize _ directory.bodyLength; -- say something informative. messageBad _ (start = 0); alreadyDeleted _ (oldStart = 0 AND size = oldSize); dirBad _ (~alreadyDeleted AND (oldSize # size OR oldStart # start)); IF messageBad OR dirBad THEN outTS.PutRope[IO.PutFR["\n\tMessage %g:\t", IO.int[msgIndex]]]; IF messageBad AND alreadyDeleted THEN { badMessages _ badMessages + 1; outTS.PutRope[IO.PutFR["message is bad, but already deleted. "]]; }; IF messageBad AND ~alreadyDeleted THEN { msgsDeleted _ msgsDeleted + 1; outTS.PutRope["message is bad, deleting. "]; }; IF dirBad THEN { directoriesFixed _ directoriesFixed + 1; outTS.PutRope["Fixing directory."]; }; directory.bodyStart _ start; directory.bodyLength _ size; msgIndex _ msgIndex+1; ENDLOOP; EXITS Done => { outTS.PutRope[IO.PutFR["\n%g messages found, ", IO.int[msgIndex]]]; outTS.PutRope[IO.PutFR["%g messages deleted, ", IO.int[msgsDeleted]]]; outTS.PutRope[IO.PutFR["%g directories fixed.\n", IO.int[directoriesFixed]]]; }; }; -- mark other directories deleted. VultureOps.CloseDirStream[dirStream]; -- write out changes Space.ForceOut[space]; -- give back the space Space.Delete[space]; CIFS.Close[file]; };-- Vulture; ReadMessage: PROC [itemStream: VultureOps.ItemStream] RETURNS [start, size: INT] -- raises EndOfStream -- -- If message is good, returns start and size. -- If message is bad, returns 0 and size. = { item: VultureOps.Item; start _ VultureOps.Current[itemStream]; {ENABLE VultureOps.BadFormat => GOTO BadFormat; item _ VultureOps.NextItem[itemStream]; -- resignals EndOfStream WHILE item.type # BodyDefs.ItemType[LastItem] DO item_ VultureOps.NextItem[itemStream]; ENDLOOP; size _ VultureOps.Current[itemStream] - start; EXITS BadFormat => { VultureOps.Reset[itemStream, start]; size _ VultureOps.FindPostmark[itemStream] - start; RETURN [start: 0, size: size]; }; }; }; Init: UserExec.CommandProc = TRUSTED {Process.Detach[FORK MakeViewer[]]}; MakeViewer: PROC [] = { viewer: ViewerClasses.Viewer _ ViewerOps.CreateViewer[ flavor: $Typescript, info: [name: "Vulture"] ]; viewer.menu _ Menus.CreateMenu[]; Menus.AppendMenuEntry[ menu: viewer.menu, entry: Menus.CreateEntry[name: "Directory", proc: ScavangeDirectory] ]; Menus.AppendMenuEntry[ menu: viewer.menu, entry: Menus.CreateEntry[name: "File", proc: ScavangeFile] ]; }; -- MakeViewer ScavangeDirectory: ENTRY Menus.MenuProc = TRUSTED { viewer: ViewerClasses.Viewer = NARROW [parent]; inTS, outTS: IO.STREAM; pattern, directory: ROPE; eproc: CIFS.EProc = TRUSTED { fileName: ROPE _ Rope.Cat[ directory, "/", IO.PutFR["%g", IO.text[name]] ]; Vulture[fileName, inTS, outTS]; RETURN [FALSE]; }; [in: inTS, out: outTS] _ ViewerIO.CreateViewerStreams[name: "", viewer: viewer]; outTS.PutRope["Enter directory: " ]; directory _ IOExtras.GetLine[inTS]; outTS.PutRope["Enter pattern: "]; pattern _ IOExtras.GetLine[inTS]; CIFS.Enumerate[directory, pattern, eproc ! CIFS.Error => TRUSTED {outTS.PutRope[error]; CONTINUE;} ]; outTS.PutRope["\nDone.\n"]; }; --ScavangeDirectory ScavangeFile: ENTRY Menus.MenuProc = TRUSTED { viewer: ViewerClasses.Viewer = NARROW [parent]; inTS, outTS: IO.STREAM; fileName: ROPE; [in: inTS, out: outTS] _ ViewerIO.CreateViewerStreams[name: "", viewer: viewer]; outTS.PutRope["Enter file name: "]; fileName _ IOExtras.GetLine[inTS]; Vulture[fileName, inTS, outTS ! CIFS.Error => TRUSTED {outTS.PutRope[error]; CONTINUE;}; ]; outTS.PutRope["\nDone.\n"]; }; -- ScavangeFile -- Start code UserExec.RegisterCommand["Vulture", Init]; [] _ Init[NIL, UserExec.GetExecHandle[]]; }. Κa– "Mesa" style˜IprocšΟc†œΟk œ žœ žœ•žœžœžœžœZžœžœžœΠbnœžœžœžœžœ=žœOžœ'žœ žœ0žœžœžœ,žœžœžœžœžœžœ2#œžœžœžœžœ*žœΘžœžœmžœ(žœžœf8œˆœ?žœ/žœžœžœ žœžœžœžœžœ žœžœ9žœ<žœ žœžœdžœžœΌžœžœžœ žœ$žœ žœ'žœ"žœ)#œ*œœžœ ˜θ˜KšΟn œžœ%žœžœœ/œ+œHžœžœ6œžœ)žœ.žœ5žœržœ'˜ΑJ˜—šΟbœžœžœ˜IKš  œžœ˜Jšœœ˜Jš%‘œžœžœ$žœžœžœžœ žœ žœžœ'žœ žœBžœžœςžœ+žœ žœžœ.˜μJš‘ œžœžœ%žœžœžœžœΔžœ žœžœ,œ˜ΕJšœœ\˜l——…—B©