-- DFDiskImpl.Mesa, last edit March 8, 1983 12:41 pm -- Pilot 6.0/ Mesa 7.0 DIRECTORY CWF: TYPE USING [FWF1, SetWriteProcedure, WF0, WF1, WF2, WFCR], DFSubr: TYPE USING [AllocateDFSeq, DF, DFSeq, FreeDFSeq, InsertCRs, NextDF, SortByCap, SortByFileName, StripLongName, WriteOut], File: TYPE USING [Capability, Unknown], FileStream: TYPE USING [NoLeaderPage], IO: TYPE USING[Handle, PutChar, PutF, ResetUserAbort, rope, string, UserAbort, UserAborted], LongString: TYPE USING [EquivalentString], Rope: TYPE USING[ROPE, Text], Stream: TYPE USING [Delete, Handle, PutChar], String: TYPE USING [EquivalentString], Subr: TYPE USING [AbortMyself, CheckForModify, CopyString, EndsIn, EnumerateDirectory, errorflg, GetCreateDate, GetRemoteFilenameProp, MakeTTYProcs, NewStream, PrintGreeting, SubrStop, TTYProcs, Write], Time: TYPE USING [Current], UserExec: TYPE USING[AcquireResource, AskUser, CommandProc, ExecHandle, GetStreams, RegisterCommand, ReleaseResource], ViewerClasses: TYPE USING[Viewer], ViewerOps: TYPE USING[CreateViewer, FindViewer, RestoreViewer], WindowManager: TYPE USING[WaitCursor, UnWaitCursor]; DFDiskImpl: PROGRAM IMPORTS CWF, DFSubr, File, FileStream, IO, LongString, Stream, String, Subr, Time, UserExec, ViewerOps, WindowManager = { -- MDS usage!! stdout: IO.Handle; -- end of mds MAXFILES: CARDINAL = 1500; Main: UserExec.CommandProc = TRUSTED { ENABLE UNWIND => [] ← UserExec.ReleaseResource[$DFDisk]; h: Subr.TTYProcs; in, out: IO.Handle; [in, out] ← UserExec.GetStreams[exec]; [] ← UserExec.AcquireResource[$DFDisk, "DFDisk", exec]; h ← Subr.MakeTTYProcs[in, out, exec, MyConfirm]; DFDiskUsingProcs[h]; [] ← UserExec.ReleaseResource[$DFDisk]; }; DFDiskUsingProcs: PROC[h: Subr.TTYProcs] = { dfseq: DFSubr.DFSeq ← NIL; starttime: LONG CARDINAL; sh: Stream.Handle; viewer: ViewerClasses.Viewer; Cleanup: PROC = { DFSubr.FreeDFSeq[@dfseq]; Subr.SubrStop[]; }; WFSH: PROC[ch: CHAR] = { Stream.PutChar[sh, ch]; }; { ENABLE { UNWIND => Cleanup[]; Subr.AbortMyself, IO.UserAborted => { h.out.ResetUserAbort[]; CWF.WF0["\nDFDisk Aborted.\n"L]; GOTO leave; }; }; starttime ← Time.Current[]; stdout ← h.out; [] ← CWF.SetWriteProcedure[MyPutChar]; Subr.PrintGreeting["DFDisk"L]; dfseq ← DFSubr.AllocateDFSeq[maxEntries: MAXFILES, zoneType: shared]; ConstructDF[dfseq]; IF NOT Subr.CheckForModify["Disk.DF"L, h] THEN SIGNAL Subr.AbortMyself; FillInCreateDates[dfseq, h]; sh ← Subr.NewStream["Disk.DF"L, Subr.Write]; CWF.FWF1[WFSH, "// Contents of entire volume on %lt\n"L, @starttime]; IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself; DFSubr.SortByFileName[dfseq, 0, dfseq.size-1]; DFSubr.InsertCRs[dfseq]; DFSubr.WriteOut[dfseq, NIL, sh, FALSE]; Stream.Delete[sh]; IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself; CWF.WF0["Listing created on file 'Disk.DF'\n"L]; viewer ← ViewerOps.FindViewer["Disk.DF"]; IF viewer ~= NIL THEN { IF viewer.newVersion THEN CWF.WF0["Warning - you are already editing Disk.DF.\n"L] ELSE ViewerOps.RestoreViewer[viewer]; } ELSE CreateANewViewer["Disk.DF", h.out]; starttime ← Time.Current[] - starttime; CWF.WF1["\nTotal elapsed time for DFDisk %lr."L,@starttime]; IF Subr.errorflg THEN CWF.WF0["\tErrors logged.\n"L]; CWF.WFCR[]; GOTO leave; EXITS leave => Cleanup[]; }}; CreateANewViewer: PROC [name: Rope.Text, out: IO.Handle] = { viewer: ViewerClasses.Viewer; WindowManager.WaitCursor[]; viewer ← ViewerOps.CreateViewer[flavor: $Text, info: [name: name, file: LOOPHOLE[name], iconic: FALSE, column: left]]; out.PutF["Created Viewer: %s\n", IO.rope[name]]; WindowManager.UnWaitCursor[]; }; ConstructDF: PROC[dfseq: DFSubr.DFSeq] = { AddDir: PROC[cap: File.Capability, name: STRING] RETURNS[BOOL] = { df: DFSubr.DF; IF ThrowAwayThisFile[name] THEN RETURN[FALSE]; df ← DFSubr.NextDF[dfseq]; IF df = NIL THEN RETURN[TRUE]; -- too big df.shortname ← Subr.CopyString[name, dfseq.dfzone]; df.presentonlocaldisk ← TRUE; df.cap ← cap; RETURN[FALSE]; }; Subr.EnumerateDirectory[AddDir]; }; FillInCreateDates: PROC[dfseq: DFSubr.DFSeq, h: Subr.TTYProcs] = { df: DFSubr.DF; host: STRING ← [30]; directory: STRING ← [100]; fullname: STRING ← [125]; short: STRING ← [100]; time: LONG CARDINAL; FillDefs: PROC = { IF df.host = NIL THEN df.host ← Subr.CopyString["Unknown"L, dfseq.dfzone]; IF df.directory = NIL THEN df.directory ← Subr.CopyString["Unknown"L, dfseq.dfzone]; }; DFSubr.SortByCap[dfseq, 0, dfseq.size-1]; time ← Time.Current[]; FOR i: CARDINAL IN [0..dfseq.size) DO df ← @dfseq[i]; IF h.in.UserAbort[] THEN SIGNAL Subr.AbortMyself; IF NOT df.presentonlocaldisk THEN LOOP; [create: df.createtime] ← Subr.GetCreateDate[df.cap ! FileStream.NoLeaderPage => { FillDefs[]; LOOP }; File.Unknown => { h.out.PutF["ERROR File.Unknown for %s\n", IO.string[df.shortname]]; FillDefs[]; LOOP }]; Subr.GetRemoteFilenameProp[df.cap, fullname]; IF fullname.length = 0 THEN { FillDefs[]; LOOP }; [] ← DFSubr.StripLongName[fullname, host, directory, short]; IF NOT LongString.EquivalentString[short, df.shortname] THEN { FillDefs[]; LOOP }; IF host.length > 0 AND directory.length > 0 THEN { df.host ← Subr.CopyString[host, dfseq.dfzone]; df.directory ← Subr.CopyString[directory, dfseq.dfzone]; } ELSE FillDefs[]; ENDLOOP; time ← Time.Current[] - time; CWF.WF2["Took %lu seconds to read %u leader pages.\n"L, @time, @dfseq.size]; }; -- don't record these files in the df file ThrowAwayThisFile: PROC[p: STRING] RETURNS[bool: BOOL] ={ transferFileList: ARRAY [0.. 5) OF STRING ← [ "disk.df"L, "Executive.DontDeleteMe"L, "FileTool.logD"L, "line.cm"L, "SimpleExec"L ]; bool ← Subr.EndsIn[p,".outload"L] OR Subr.EndsIn[p,"$"L] OR Subr.EndsIn[p,".errlog"L] OR Subr.EndsIn[p,".log"L] OR Subr.EndsIn[p,".pgslog"L] OR Subr.EndsIn[p,".echo"L] OR Subr.EndsIn[p,".tipc"L] OR Subr.EndsIn[p,".dontdeleteme"L] OR Subr.EndsIn[p,".tmp"L]; IF NOT bool THEN { FOR i: CARDINAL IN [0.. LENGTH[transferFileList]) DO IF String.EquivalentString[p, transferFileList[i]] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; } }; MyConfirm: PROC[in, out: IO.Handle, data: REF ANY, msg: Rope.ROPE, dch: CHAR] RETURNS[CHAR] = { value: ATOM; value ← UserExec.AskUser[msg: msg, exec: NARROW[data], keyList: LIST[$Yes, $No]]; -- order is important SELECT value FROM $No => RETURN['n]; $Yes => RETURN['y]; ENDCASE => ERROR; }; MyPutChar: PROC[ch: CHAR] = { stdout.PutChar[ch]; }; -- start code UserExec.RegisterCommand["DFDisk", Main]; }.