-- DFDiskImpl.Mesa
-- last edit March 8, 1983 12:41 pm
-- last edit May 22, 1983 4:54 pm, Russ Atkinson
-- last edit August 1, 1983 2:02 pm, Doug Wyatt
-- Pilot 6.0/ Mesa 7.0
DIRECTORY
Commander: TYPE USING [CommandProc, Register],
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],
IOMisc: TYPE USING[AskUser],
LongString: TYPE USING [EquivalentString],
Resource: TYPE USING[Acquire, Release],
Rope: TYPE USING[ROPE, Text],
Stream: TYPE USING [Delete, Handle, PutChar],
Subr: TYPE USING [AbortMyself, CheckForModify, CopyString, EndsIn, EnumerateDirectory,
errorflg, GetCreateDate, GetRemoteFilenameProp, MakeTTYProcs,
NewStream, PrintGreeting, SubrStop, TTYProcs, Write],
Time: TYPE USING [Current],
ViewerClasses: TYPE USING[Viewer],
ViewerOps: TYPE USING[CreateViewer, FindViewer, RestoreViewer],
WindowManager: TYPE USING[WaitCursor, UnWaitCursor];
DFDiskImpl: PROGRAM
IMPORTS Commander, CWF, DFSubr, File, FileStream, IO, IOMisc, LongString, Resource, Stream,
Subr, Time, ViewerOps, WindowManager = {
-- MDS usage!!
stdout: IO.Handle;
-- end of mds
MAXFILES: CARDINAL = 1500;
Main: Commander.CommandProc = TRUSTED {
ENABLE UNWIND => [] ← Resource.Release[$DFDisk];
h: Subr.TTYProcs;
[] ← Resource.Acquire[resource: $DFDisk, waitForIt: TRUE, owner: "DFDisk"];
h ← Subr.MakeTTYProcs[cmd.in, cmd.out, NIL, MyConfirm];
DFDiskUsingProcs[h];
[] ← Resource.Release[$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: LONG 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: LONG STRING] RETURNS[bool: BOOL] ={
transferFileList: ARRAY [0.. 4) OF STRING ← [
"disk.df"L,
"line.cm"L,
"SimpleExec"L,
"Swatee"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,".logD"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 LongString.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 ← IOMisc.AskUser[msg: msg, in: in, out: out,
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
Commander.Register["DFDisk", Main, "Make a DF file describing files on the local disk"];
}.