// 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 BackupIFS.Dir // for controlled restore. let bName = "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 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 "*", // 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)