-- CreateCedarVM.Mesa
-- last edited 2-Dec-81 1:09:36 by Paul Rovner
DIRECTORY
Ascii USING[CR],
Directory USING[InsertFile, Lookup],
Exec USING[w],
File USING[nullCapability, Capability, ShowCapability, Create, Delete, MakePermanent, GetSize, PageCount],
FileInternal USING[PageGroup, Descriptor],
FileTypes USING[tUntypedFile],
LogicalVolume USING[Handle, VolumeAccessProc],
Runtime USING[CallDebugger],
TTY USING[PutLine, GetNumber, PutDecimal, PutString, Rubout, GetChar, PutChar],
VolFileMapImpl USING[GetPageGroup],
Volume USING[GetAttributes, systemID, ID],
VolumeImpl USING[VolumeAccess];
CreateCedarVM: PROGRAM
IMPORTS Directory, Exec, File, TTY, Runtime, VolFileMapImpl, Volume, VolumeImpl
SHARES Directory, VolFileMapImpl, VolumeImpl
= BEGIN
filePages: NAT ← 4096;
Bug: SIGNAL = CODE;
OutOfDisk: PROC[pagesNeeded: NAT] RETURNS[BOOLEAN] =
{RETURN[Volume.GetAttributes[Volume.systemID].freePageCount < pagesNeeded]};
FileIsContiguousOnDisk: PROC[file: File.Capability] RETURNS[BOOLEAN] =
{ pageGroup: FileInternal.PageGroup;
contiguous: BOOLEAN ← FALSE;
problem: BOOLEAN ← FALSE;
v: Volume.ID ← Volume.systemID;
fpgs: File.PageCount = File.GetSize[file];
d: FileInternal.Descriptor ← [fileID: File.ShowCapability[file].fID,
volumeID: Volume.systemID,
body: local[immutable: FALSE,
temporary: TRUE,
size: fpgs,
type: FileTypes.tUntypedFile]];
p: LogicalVolume.VolumeAccessProc =
{[contiguous, pageGroup] ← VolFileMapImpl.GetPageGroup[volume, @d, 0];
problem ← NOT contiguous;
IF problem THEN RETURN[FALSE];
contiguous ← pageGroup.nextFilePage - pageGroup.filePage = fpgs;
RETURN[FALSE]};
IF VolumeImpl.VolumeAccess[@v, p, FALSE] # ok OR problem
THEN ERROR Bug
ELSE RETURN[contiguous];
};
Main: PROC =
{ success: BOOLEAN ← FALSE;
file: File.Capability ← File.nullCapability;
fileArrayMaxLength: NAT = 40;
a: ARRAY [0..fileArrayMaxLength) OF File.Capability ← ALL[File.nullCapability];
x: NAT ← 0;
TTY.PutLine[Exec.w, ""];
IF Directory.Lookup["CedarVM.DontDeleteMe" ! ANY => CONTINUE] # File.nullCapability
THEN {TTY.PutLine[Exec.w, "CedarVM.DontDeleteMe already exists. You might want to delete it and try again."];
RETURN};
TTY.PutString[Exec.w, "Please type desired file size in pages..."];
filePages ← TTY.GetNumber[h: Exec.w, default: filePages, radix: 10];
IF filePages < 1000 THEN filePages ← 1000 ELSE IF filePages > 16384 THEN filePages ← 16384;
TTY.PutLine[Exec.w, ""];
TTY.PutString[Exec.w, "Using "];
TTY.PutDecimal[Exec.w, filePages];
TTY.PutLine[Exec.w, " for filePages "];
IF NOT Confirm[] THEN RETURN;
TTY.PutLine[Exec.w, "This takes a while (small number of minutes, maybe). Hang in there..."];
IF OutOfDisk[filePages]
THEN {TTY.PutLine[Exec.w, "Failure. Not enough free disk pages."];
RETURN};
file ← File.Create[Volume.systemID, 1000, FileTypes.tUntypedFile];
TTY.PutChar[Exec.w, 'n];
DO IF FileIsContiguousOnDisk[file]
THEN {a[x] ← file;
x ← x + 1;
IF x >= fileArrayMaxLength OR OutOfDisk[filePages] THEN EXIT;
file ← File.Create[Volume.systemID, filePages, FileTypes.tUntypedFile];
TTY.PutChar[Exec.w, 'N];
IF FileIsContiguousOnDisk[file]
THEN {success ← TRUE; EXIT}
ELSE {a[x] ← file;
x ← x + 1;
IF x >= fileArrayMaxLength OR OutOfDisk[filePages] THEN EXIT;
file ← File.Create[Volume.systemID, 1000, FileTypes.tUntypedFile];
TTY.PutChar[Exec.w, 'n]}};
a[x] ← file;
x ← x + 1;
IF x >= fileArrayMaxLength OR OutOfDisk[filePages] THEN EXIT;
file ← File.Create[Volume.systemID, 1000, FileTypes.tUntypedFile];
TTY.PutChar[Exec.w, 'n];
ENDLOOP;
FOR i: NAT IN [0..x)
DO {TTY.PutChar[Exec.w, IF File.GetSize[a[i]] = 1000 THEN 'd ELSE 'D];
File.Delete[a[i]]}
ENDLOOP;
TTY.PutLine[Exec.w, ""];
IF success
THEN {File.MakePermanent[file];
Directory.InsertFile["CedarVM.DontDeleteMe", file];
TTY.PutLine[Exec.w,
"Success. CedarVM.DontDeleteMe has been created."]}
ELSE TTY.PutLine[Exec.w,
"Failure. The volume is fragmented enough that you'll have to erase it and start from fresh to create the CedarVM file."];
};
UpperCase: PROC[ch: CHARACTER] RETURNS[CHARACTER] =
{SELECT ch FROM
IN ['a..'z] => RETURN[ch - 'a + 'A];
ENDCASE => RETURN[ch]};
Confirm: PROC RETURNS[BOOLEAN] =
{ ENABLE TTY.Rubout => GOTO rubout;
ch: CHARACTER;
TTY.PutString[Exec.w, "[Confirm] "];
ch ← UpperCase[TTY.GetChar[Exec.w]];
SELECT ch FROM
Ascii.CR, 'Y =>
{ TTY.PutLine[Exec.w, "(Yes)"];
RETURN[TRUE]};
ENDCASE =>
{ TTY.PutLine[Exec.w, "(No)"];
RETURN[FALSE]};
EXITS rubout =>
{ TTY.PutLine[Exec.w, "(No)"];
RETURN[FALSE]}};
-- START HERE
Main[! ANY => {Runtime.CallDebugger["CreateCedarVM failed in some wierd way. Either call Paul Rovner at x4465 or Proceed to forget the whole thing."];
CONTINUE}];
END.