// IFSCreate2.bcpl -- code for creating an Interim File System // This portion need not be in the resident initialization // Copyright Xerox Corporation 1979, 1980, 1981 // Last modified November 19, 1981 9:19 AM by Taft get "ifs.decl" get "ifsfiles.decl" get "ifsdirs.decl" get "streams.d" external [ // Outgoing procedures CreateIFS; CreateIFSPart2; CreateSystemEntries; // Incoming procedures CreateIFSPart1; OpenIFSPart1; OpenIFSPart2; CloseIFS OpenIFSTree; CloseBTree TFSDiskModel; OpenDisk; OpenSystemFile; CreateIFSDisk CreateOFT; DestroyOFT; CreateUser; TransferLeaderPage CreateFD; DestroyFD; LookupIFSFile; GetBufferForFD; LockDirFD; UnlockDirFD CreateDirectoryEntry; UpdateDIFRec; UpdatePageUsage Lock; Unlock; ExtendStackCall; IFSError CopyString; CreateStringStream; PutTemplate DefaultArgs; SysAllocate; SysFree; MoveBlock; Zero OpenFile; KsHintLastPageFa; Closes; ReadBlock; WriteBlock // Incoming statics driveTab; openLock ] //--------------------------------------------------------------------------- let CreateIFS(cPar, lvError) = ExtendStackCall(3000, DoCreate, cPar, lvError) //--------------------------------------------------------------------------- // Creates and opens an IFS using the parameters supplied in cPar. // id and name are strings to insert into the home block. // numUnits is the number of disk units in the file system. // lpMap is a vector describing the logical-to-physical unit // number map. ifsType is one of ifsTypePrimary or ifsTypeBackup. // If successful, returns the ifs structure. If unsuccessful, // stores an error code in @lvError and returns zero. //--------------------------------------------------------------------------- and DoCreate(cPar, lvError) = valof //--------------------------------------------------------------------------- [ @lvError = CreateIFSPart1(cPar) if @lvError ne 0 resultis 0 Lock(openLock, true) let ifs = OpenIFSPart1(cPar>>CPar.id, lvError) if ifs ne 0 then [ CreateIFSPart2(ifs) ifs = OpenIFSPart2(ifs, lvError) ] Unlock(openLock) resultis ifs ] //--------------------------------------------------------------------------- and CreateIFSPart2(ifs) be //--------------------------------------------------------------------------- // Performs the second part of IFS creation, given the ifs structure // returned by OpenIFSPart1. It initializes the directory B-tree, // enters all system files into it, and closes it. [ // initialize the B-tree let fp = vec lFP TFSNameToFP("IFS.Dir", ifs>>IFS.lpdt↑0, fp) ifs>>IFS.dirBTree = OpenIFSTree(fp, ifs, 0, 0, true, 1000) CreateOFT(ifs, 8) // make initial Directory Information Files manifest capWheel = #100000 rshift offset Capabilities.wheel CreateUser("System", "ifs", 10000, 0, capWheel, true, ifs) ZeroWriteDate(ifs, "<System>!1") if ifs>>IFS.type eq ifsTypePrimary then [ CreateUser("Default-User", "*n", 1000, 0, 0, true, ifs) CreateUser("Mail", "*n", 10000, "System", 0, false, ifs) ZeroWriteDate(ifs, "<Default-User>!1") ZeroWriteDate(ifs, "<Mail>!1") ] // make directory entries in <System> for all system files CreateSystemEntry(ifs, 0, "IFS.Dir") if ifs>>IFS.type eq ifsTypePrimary then [ CreateSystemEntry(ifs, 0, "IFS.Swap") CreateSystemEntry(ifs, 0, "IFS.Errors", 0, ftText, true) CreateSystemEntry(ifs, 0, "IFS.Syms", 0, 0, true) ] for i = 0 to ifs>>IFS.numUnits-1 do CreateSystemEntries(ifs, i) CloseBTree(ifs>>IFS.dirBTree) ifs>>IFS.dirBTree = 0 unless DestroyOFT(ifs) do IFSError(ecCantDestroyOFT) ] //--------------------------------------------------------------------------- and ZeroWriteDate(ifs, name) be //--------------------------------------------------------------------------- // The purpose of this exercise is to cause the file to be very old // and hence eligible for restoration by the backup system. This is necessary // for <System>!1 and <Default-User>!1, since these are created by // CreateIFS with dummy information and the real stuff must be restored // from the backup system. [ let fd = LookupIFSFile(name, lcVExplicit, 0, ifs) if fd eq 0 then IFSError(ecTridentFile, name) let buf = GetBufferForFD(fd) TransferLeaderPage(fd, buf) Zero(lv buf>>ILD.written, 2) TransferLeaderPage(fd, buf, true) SysFree(buf) DestroyFD(fd) ] //--------------------------------------------------------------------------- and TFSNameToFP(name, disk, fp) = valof //--------------------------------------------------------------------------- // Looks up the TFS file on the specified disk and stores the // file's FP in the structure pointed to by fp. // Returns the size of the file in pages. [ Zero(fp, lFP) let str = OpenFile(name, ksTypeReadOnly, 0, 0, fp, 0, 0, 0, disk) if str eq 0 then IFSError(ecTridentFile, name) let pages = KsHintLastPageFa(str)>>FA.pageNumber+1 Closes(str) resultis pages ] //--------------------------------------------------------------------------- and CreateSystemEntries(ifs, unit) be //--------------------------------------------------------------------------- [ CreateSystemEntry(ifs, unit, "IFS.Home", true) CreateSystemEntry(ifs, unit, "SysDir", true) CreateSystemEntry(ifs, unit, "DiskDescriptor", true) ] //--------------------------------------------------------------------------- and CreateSystemEntry(ifs, unit, name, append, fileType, world; numargs na) be //--------------------------------------------------------------------------- // Creates an IFS directory entry for the TFS file "name" // on logical unit "unit". If "append" is false or not supplied, // the IFS name for TFS file "foo" is "<System>foo!1". // If unit is supplied, the name is "<System>foo.u!1". // "world" should be true if the file is to be readable by the world. // Also fixes up the leader page to have all correct IFS stuff. [ DefaultArgs(lv na, -3, false, ftBinary, false) // lookup the supplied TFS name let fp = vec lFP let pages = TFSNameToFP(name, ifs>>IFS.lpdt↑unit, fp) fp>>IFP.unit = unit // construct IFS name and build FD let ifsName = SysAllocate(lenPathName) MakeIFSName(ifsName, name, (append? unit, -1)) let fd = CreateFD(ifsName, lcCreate+lcVNext, 0, ifs) if fd eq 0 then IFSError(ecIllegalExistingName, ifsName) // make IFS directory entry LockDirFD(fd, lockWrite) MoveBlock(lv fd>>FD.dr>>DR.fp, fp, lFP) CreateDirectoryEntry(fd) // fix up the leader page let buf = GetBufferForFD(fd) TransferLeaderPage(fd, buf) manifest lLD = offset ILD.pathName/16 Zero(buf+lLD, ifs>>IFS.pageLength-lLD) CopyString(lv buf>>ILD.pathName, ifsName) buf>>ILD.readProt.owner = true // only owner can read buf>>ILD.readProt.world = world CopyString(lv buf>>ILD.author, "System") buf>>ILD.type = fileType buf>>ILD.byteSize = 8 buf>>ILD.undeletable = true buf>>ILD.noBackup = true TransferLeaderPage(fd, buf, true) SysFree(buf) UnlockDirFD(fd) UpdateDIFRec(fd, UpdatePageUsage, pages) DestroyFD(fd) SysFree(ifsName) ] //--------------------------------------------------------------------------- and MakeIFSName(ifsName, tfsName, unit) be //--------------------------------------------------------------------------- [ let s = CreateStringStream(ifsName, maxPathNameChars) PutTemplate(s, (unit ge 0? "<System>$S.$O!1", "<System>$S!1"), tfsName, unit) Closes(s) ]