-- 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.