// IfsScavDump.bcpl
// Copyright Xerox Corporation 1979, 1980, 1981
// Last modified June 2, 1981 2:50 PM by Taft
get "Streams.d"
get "IfsFiles.decl"
get "BTree.decl"
external
[
// outgoing procedures
DumpLPT; DumpTree
// incoming procedures
GetLpteIfsName; GetLpteIfp; GetLpteDIFRec; GetLptFa
OpenLPT; EnumerateLPT; CloseLPT; GetLptHome; GetLpteType
OpenDisk; CloseDisk; Scratch; DirEntryLength
OpenFile; Closes; Resets; Puts
Ws; Wss; PutTemplate; ReadBlock; GetCurrentFa
Allocate; CallSwat; TruePredicate; Zero
OpenFPTree; CloseIFSTree; MapTree
InitCmd; GetFile; Confirm
UNPACKDT; WRITEUDT
// incoming statics
sysZone; scratchDisk
]
static [ onlyDIFs; printTreeStructure; printFileIDs ]
structure String [ length byte; char↑1,1 byte ]
// These routines dump the contents of Scavenger.lpt and Ifs.dir.
// They are mostly useful for debugging the scavenger, but may be
// of use in getting an independant opinion on the contents of the
// system directory.
//----------------------------------------------------------------------------
let DumpLPT() be
//----------------------------------------------------------------------------
[
if scratchDisk eq 0 then unless Scratch(nil) return
let ok, list, lpt = true, 0, 0
if ok then
[
lpt = OpenLPT("IfsScavenger.lpt", false)
Resets(lpt)
GetCurrentFa(lpt, GetLptFa(lpt))
]
if ok then
[
let cs = InitCmd(100, 5); if cs ne 0 then
[
Ws("*NWhat shall I call the output file on DP0? ")
list = GetFile(cs, ksTypeWriteOnly, charItem)
onlyDIFs = Confirm(cs, "*NDo you want just page usage info? ")
printFileIDs = not onlyDIFs
Puts(cs, $*N)
Closes(cs)
]
if cs eq 0 then ok = false
]
if ok then
[
PrintHome(list, GetLptHome(lpt))
EnumerateLPT(lpt, InterpretLPT, list)
]
if lpt ne 0 then CloseLPT(lpt, false)
if list ne 0 then Closes(list)
]
//----------------------------------------------------------------------------
and InterpretLPT(lpt, lpte, list) be
//----------------------------------------------------------------------------
if GetLpteType(lpte) eq dvTypeFile then
unless onlyDIFs & GetLpteDIFRec(lpte) eq 0 do
PrintInfo(list, GetLpteIfsName(lpte), GetLpteIfp(lpte),
GetLpteDIFRec(lpte))
//----------------------------------------------------------------------------
and DumpTree() be
//----------------------------------------------------------------------------
[
let ok, disk, tree, list = true, 0, 0, 0
disk = OpenDisk("*NWhich disk is it on? ")
if disk eq 0 then ok = false
if ok then
[
let fp = vec lFP; Zero(fp, lFP)
let ifsDir = OpenFile("Ifs.dir", ksTypeReadOnly, 0, 0,
fp, 0, 0, 0, disk)
test ifsDir ne 0
ifso Closes(ifsDir)
ifnot
[
Ws("*NI can't open *"Ifs.dir*"")
ok = false
]
if ok then
tree = OpenFPTree(fp, disk, CallSwat, DirEntryLength, false)
]
if ok then
[
let cs = InitCmd(200, 5); if cs ne 0 then
[
Ws("*NWhat shall I call the output file on DP0? ")
list = GetFile(cs, ksTypeWriteOnly, charItem)
onlyDIFs = Confirm(cs, "*NDo you want just page usage info? ")
printTreeStructure = onlyDIFs? false,
Confirm(cs,"*nShow the tree structure? ")
printFileIDs = onlyDIFs? false,
Confirm(cs,"*nShow the file IDs? ")
Closes(cs)
]
if cs eq 0 then ok = false
]
if ok then
[
let home = OpenFile("Ifs.home", ksTypeReadOnly, 0, 0, 0, 0, 0, 0, disk)
test home eq 0
ifso
[
Ws("*NI can't open *"Ifs.home*"")
ok = false
]
ifnot
[
let h = vec lenHome
test ReadBlock(home, h, lenHome) eq lenHome
ifso PrintHome(list, h)
ifnot
[
Ws("*NMalformed home block")
ok = false
]
Closes(home)
]
]
if ok then MapTree(tree, 0, InterpretTree, list, TruePredicate, true)
if list ne 0 then Closes(list)
if tree ne 0 then CloseIFSTree(tree)
if disk ne 0 then CloseDisk(disk, true)
]
//----------------------------------------------------------------------------
and InterpretTree(dr, list, pathStk) = valof
//----------------------------------------------------------------------------
[
unless onlyDIFs & dr>>DR.type ne drTypeDIF do
[
if printTreeStructure then
[
let pse = lv pathStk>>PS.PSE↑(pathStk>>PS.PathStkTop)
let indentString = selecton pathStk>>PS.PathStkTop into
[
case 1: ""
case 2: " "
case 3: " "
default: " " // never happens
]
if pse>>PSE.Offset eq Rec1Offset then
PutTemplate(list, "$S[Page $OB, $OB words free]*n",
indentString, pse>>PSE.PageNo,
(dr - offset BTE.Record/16 - Rec1Offset)>>BTP.FreeWords)
Wss(list, indentString)
]
PrintInfo(list, lv dr>>DR.pathName, lv dr>>DR.fp,
(dr>>DR.type eq drTypeDIF? dr+dr>>DR.length-lenDIFRec, 0))
]
resultis true
]
//----------------------------------------------------------------------------
and PrintHome(stream, home) be
//----------------------------------------------------------------------------
[
PutTemplate(stream, "*NFile system name *"$S*", ID *"$S*"",
lv home>>Home.name, lv home>>Home.id)
PutTemplate(stream, "*Ntype $S, num units $D, created ",
selecton home>>Home.type into
[
case ifsTypePrimary: "primary"
case ifsTypeBackup: "backup"
default: "unknown"
], home>>Home.numUnits)
let utv = vec 10
UNPACKDT(lv home>>Home.created, utv)
WRITEUDT(stream, utv, true)
Wss(stream, "*n*n")
]
//----------------------------------------------------------------------------
and PrintInfo(stream, pathName, fp, difRec) be
//----------------------------------------------------------------------------
// I recommend an 8pt fixed pitch font when listing this output
[
test onlyDIFs
ifnot Wss(stream, pathName)
ifso for i = 2 to pathName>>String.length-3 do
Puts(stream, pathName>>String.char↑i)
if printFileIDs % onlyDIFs then
[
let padding = onlyDIFs? 20,45
test pathName>>String.length gr padding
ifso Wss(stream, " ")
ifnot for i = pathName>>String.length to padding do Puts(stream, $*S)
]
if printFileIDs then
PutTemplate(stream, "$EUO;$UO, un $UO vda $UO", lv fp>>IFP.serialNumber,
fp>>IFP.version, @lv fp>>IFP.unit, fp>>IFP.page)
if difRec ne 0 then
PutTemplate(stream, " $5EUD pages used out of $5EUD",
lv difRec>>DIFRec.diskPageUsage, lv difRec>>DIFRec.diskPageLimit)
Puts(stream, $*N)
]