// IfsBackupCmd3.bcpl -- operator interface for backup system
// Copyright Xerox Corporation 1979, 1980, 1981
// Last modified November 17, 1981 8:36 PM by Taft
get "Ifs.decl"
get "IfsFiles.decl"
get "Disks.d"
get "IfsBackup.decl"
get "IfsDirs.decl"
get "Streams.d"
external
[
// outgoing procedures
BackupRestore; BackupReload
// incoming procedures
OpenIFS; CloseIFS; RestoreLoop; RestoreFile; CopyFile
LookupIFSFile; DestroyFD; GetDiskFromFD
IFSOpenFile; IFSDeleteFile; WriteBlock; TruncateDiskStream
OpenIFSFile; CloseIFSFile; DeleteFileFromFD
OpenIFSTree; CloseBTree
InitCmd; GetString; AbortCmd; TelnetAborting; TelnetConfirm; TerminatingChar
Ws; Wss; Gets; Puts; Endofs; Closes; Resets; PutTemplate
IFSPrintError; ConcatenateStrings
DefaultArgs; SysFree; FreePointer
// incoming statics
primaryIFS; dsp
]
//----------------------------------------------------------------------------
let BackupRestore(cs, lvOpenedFS) be
//----------------------------------------------------------------------------
// Command to restore individual files from backup system
[
Wss(cs, " (from backup pack) ")
let ec = nil
let backupFS = @lvOpenedFS
if backupFS eq 0 then
[
let name = GetString(cs, 0, Wss, "pack name")
backupFS = OpenIFS(name, lv ec)
SysFree(name)
if backupFS eq 0 then
[ Puts(dsp, $*n); IFSPrintError(dsp, ec); AbortCmd(cs) ]
PutTemplate(dsp, "*n$S ($S) mounted.", backupFS>>IFS.id,
backupFS>>IFS.name)
]
[
cs = InitCmd(maxPathNameChars+25, 1)
if cs ne 0 then
[
Wss(cs, "*nRestore file(s): ")
let name = GetString(cs, 0, Wss, "file name ('**' permitted)")
Closes(cs)
if name>>String.length eq 0 then [ SysFree(name); break ]
let ec = RestoreLoop(name, backupFS, primaryIFS)
if ec ne 0 then
[ Ws(" -- "); IFSPrintError(dsp, ec) ]
SysFree(name)
]
] repeatuntil TelnetAborting()
CloseIFS(backupFS)
@lvOpenedFS = 0
]
//----------------------------------------------------------------------------
and BackupReload(cs, lvOpenedFS) be
//----------------------------------------------------------------------------
// Command to reload entire file system from backup
[
if @lvOpenedFS ne 0 then
[ CloseIFS(@lvOpenedFS); @lvOpenedFS = 0 ]
Ws(" (file system)")
// Open temporary file on primaryIFS to hold latest <System>BackupIFS.Dir
// for controlled restore.
let bName = "<System>BackupIFS.Dir"
let ec = nil
let dirFD = LookupIFSFile(bName, lcVHighest+lcCreate, lv ec)
if dirFD eq 0 then [ CantOpen(bName, primaryIFS, ec); return ]
ec = OpenIFSFile(dirFD, modeReadWrite)
if ec ne 0 then [ CantOpen(bName, primaryIFS, ec); DestroyFD(dirFD); return ]
let tree = 0
let relDirSt = TelnetConfirm("*nReload entire file system?")? 0,
GetReloadDirectoryList()
Ws("*nImportant: mount the LAST backup pack first.")
until TelnetAborting() do
[ // repeat (for each backup file system)
cs = InitCmd(50, 1)
if cs ne 0 then
[
Wss(cs, "*nMount backup pack: ")
let name = GetString(cs, 0, Wss, "pack name")
let backupFS = OpenIFS(name, lv ec)
SysFree(name)
if backupFS eq 0 then
[ Puts(dsp, $*n); IFSPrintError(dsp, ec); AbortCmd(cs) ]
Closes(cs)
PutTemplate(dsp, "*n$S ($S) mounted.", backupFS>>IFS.id,
backupFS>>IFS.name)
if tree eq 0 then
[ //first file system mounted, copy its <System>BackupIFS.Dir
let backupFD = LookupIFSFile(bName, lcVHighest, lv ec, backupFS)
if backupFD eq 0 then
[ CantOpen(bName, backupFS, ec); CloseIFS(backupFS); loop ]
Ws("*nCopying backup directory...")
CopyFile(GetDiskFromFD(dirFD), lv dirFD>>FD.dr>>DR.fp,
GetDiskFromFD(backupFD), lv backupFD>>FD.dr>>DR.fp, 0, 0, true)
DestroyFD(backupFD)
tree = OpenIFSTree(lv dirFD>>FD.dr>>DR.fp, primaryIFS)
Ws("*nBeginning reload.")
]
//restore files from backup as appropriate.
test relDirSt eq 0
ifso RestoreLoop("<**", backupFS, primaryIFS, tree)
ifnot
[
Resets(relDirSt)
until TelnetAborting() do
[
let dirName = NextReloadDirName(relDirSt)
if dirName eq 0 break
RestoreLoop(dirName, backupFS, primaryIFS, tree)
SysFree(dirName)
]
]
CloseIFS(backupFS)
]
]
if relDirSt ne 0 then [ Closes(relDirSt); IFSDeleteFile("DirNames.temp") ]
if tree ne 0 then CloseBTree(tree)
CloseIFSFile(dirFD)
DeleteFileFromFD(dirFD)
DestroyFD(dirFD)
]
//----------------------------------------------------------------------------
and GetReloadDirectoryList() = valof
//----------------------------------------------------------------------------
// Inputs a list of directory names from the operator, puts them in a
// temporary file (opened in word mode), and returns the open stream.
// Returns zero if can't open the temporary file.
[
let dName = "DirNames.temp"
let ec = nil
let str = IFSOpenFile(dName, lv ec, modeReadWrite, wordItem)
if str eq 0 then [ CantOpen(dName, primaryIFS, ec); resultis 0 ]
Ws("*nEnter directory names, separated by spaces and terminated by Return.*n")
until TelnetAborting() do
[
let cs = InitCmd(50, 1)
if cs ne 0 then
[
Puts(cs, $*s)
let name = GetString(cs, 0, Wss, "directory name")
if name>>String.length ne 0 then
WriteBlock(str, name, name>>String.length rshift 1 +1)
SysFree(name)
let char = TerminatingChar(cs)
Closes(cs)
if char eq $*n break
]
]
TruncateDiskStream(str)
resultis str
]
//----------------------------------------------------------------------------
and NextReloadDirName(str) = valof
//----------------------------------------------------------------------------
// Returns next directory name from str in form "<dirName>*",
// or zero if list is exhausted.
[
if Endofs(str) resultis 0
let name = vec lenDirName
let i = 0
[ name!i = Gets(str); i = i+1 ] repeatuntil
i ge name>>String.length rshift 1 +1
resultis ConcatenateStrings(ConcatenateStrings("<", name), ">**", true)
]
//----------------------------------------------------------------------------
and CantOpen(name, fs, ec) be
//----------------------------------------------------------------------------
PutTemplate(dsp, "*nCan't open $S in $S:*n $P", name, fs>>IFS.id,
IFSPrintError, ec)