示例#1
0
文件: rt11fs.py 项目: NF6X/pyRT11
    def _fsWriteDirSegs(self, f):
        """Write the directory segments."""

        # How many of the dir segments will we use? Need to
        # hold files in file list plus end of segment marker per dir seg
        dsNeeded = math.ceil((len(self.fsFileList) + self.fsNumDirSegs) / self.fsDirEntPerSeg)

        # Sanity check: Will the entries fit?
        rt11util.assertError(dsNeeded <= self.fsNumDirSegs, "Not enough directory segments to hold file list.")

        # Start constructing dir segs in memory. Represent as lists of 16-bit
        # word values for now.
        dirSegs = [None] * self.fsNumDirSegs
        for dsNum in range(self.fsNumDirSegs):
            dirSegs[dsNum] = [0] * rt11util.rtBlockSize

        # Fill in header info that we already know
        for dsNum in range(len(dirSegs)):
            dirSegs[dsNum][:rtDirSegHdrSize] = [self.fsNumDirSegs, 0, 0, self.fsExtraWords * 2, 0]

        # Fill in file information

        dsNum = 1
        deNum = 0
        highDs = 0
        blkNum = self.fsDataStart

        for de in self.fsFileList:

            # Fill in more directory entry header information
            if deNum == 0:
                dirSegs[dsNum - 1][1] = dsNum + 1
                dirSegs[dsNum - 1][4] = blkNum

            # Fill in one directory entry
            deOffset = rtDirSegHdrSize + (deNum * self.fsDirEntSize)

            dirSegs[dsNum - 1][deOffset : deOffset + rtDirEntSize] = [
                de.deStatus,
                de.deName[0],
                de.deName[1],
                de.deName[2],
                de.deLength,
                de.deJobChan,
                de.deDate,
            ]

            rt11util.assertError(blkNum == de.deStart, "Block number calculation error.")

            blkNum = blkNum + de.deLength

            if self.fsDirEntSize > rtDirEntSize:
                # Fill in extra bytes
                dirsegs[dsNum - 1][deOffset + rtDirEntSize : deOffset + self.fsDirEntSize] = de.deExtra

            deNum = deNum + 1
            if deNum == (self.fsDirEntPerSeg - 1):
                # Add end of segment marker
                deOffset = rtDirSegHdrSize + (deNum * self.fsDirEntSize)
                dirSegs[dsNum - 1][deOffset] = deEEOS
                deNum = 0
                dsNum = dsNum + 1

        if deNum != 0:
            # If deNum == 0, we should have just written an end of segment
            # marker. If not, add one now.
            deOffset = rtDirSegHdrSize + (deNum * self.fsDirEntSize)
            dirSegs[dsNum - 1][deOffset] = deEEOS

        # Next dir seg pointer = 0
        dirSegs[dsNum - 1][1] = 0

        # Now plug in high dir seg number
        highDs = dsNum
        for dsNum in range(len(dirSegs)):
            dirSegs[dsNum][2] = highDs

        # Write the constructed dir segs to disk
        blks = bytearray(0)
        for ds in dirSegs:
            blks += rt11util.wordsToBytes(ds)
        rt11util.writeBlocks(f, blks, self.fsFirstDirSeg, self.fsNumDirSegs * 2)
示例#2
0
文件: rt11fs.py 项目: NF6X/pyRT11
    def _fsReadDirSegs(self, f):
        """Parse the directory segments.

        Directory segments are 2 blocks long, start at block number
        fsFirstDirSeg, and are numbered 1 through 31.
        We ignore garbage in unused directory segments."""

        if self.fsVerbose:
            print "_fsReadDirSegs():"

        dsNum = 1
        while dsNum > 0:
            # Read directory segment, convert to 16-bit words
            bnum = self.fsFirstDirSeg + ((dsNum - 1) * 2)
            if self.fsVerbose:
                print "    blocks {:d},{:d}".format(bnum, bnum + 1)
            blk = rt11util.readBlocks(f, bnum, 2)
            wblk = rt11util.bytesToWords(blk)

            # Extract fields from directory segment header
            numDs, nextDs, highDs, xBytes, dStart = wblk[:rtDirSegHdrSize]

            if self.fsVerbose:
                print "        numDs  =", numDs
                print "        nextDs =", nextDs
                print "        highDs =", highDs
                print "        xBytes =", xBytes
                print "        dStart =", dStart

            rt11util.assertError((xBytes % 2) == 0, "Extra bytes count must be even.")

            if dsNum == 1:
                # Initialize stuff from first dir segment header
                self.fsNumDirSegs = numDs
                self.fsExtraWords = xBytes / 2
                self.fsDirEntSize = rtDirEntSize + self.fsExtraWords
                self.fsDirEntPerSeg = (rtDirSegSize - rtDirSegHdrSize) / self.fsDirEntSize
                self.fsDataStart = dStart
            else:
                # Sanity checks
                # Each segment should have matching number of dir segs count in header
                rt11util.assertWarn(
                    numDs == self.fsNumDirSegs, "Number of directory segments changed in segment " + str(dsNum)
                )

                # Each segment should have matching extra byte count in header
                rt11util.assertWarn(
                    xBytes / 2 == self.fsExtraWords, "Number of extra entry bytes changed in segment " + str(dsNum)
                )

                # Dir segments should point to contiguous sets of data blocks
                rt11util.assertWarn(dStart == dsDataBlock, "Non-contiguous data in directory segment " + str(dsNum))

            # Unpack remainder of directory segment into list of
            # directory entry tuples.
            # This line is so ugly, it ought to be in Perl.
            # Don't ask me how it works; I barely understood it when I wrote it.
            dsEntries = zip(*[iter(wblk[rtDirSegHdrSize:])] * self.fsDirEntSize)

            dsDataBlock = dStart

            for dsEntry in dsEntries:
                statWord, fn1, fn2, ext, fileLen, jobChan, fileDate = dsEntry[:7]

                if statWord & deEEOS:
                    # End of this directory segment
                    break

                entry = dirEntry(
                    name=[fn1, fn2, ext],
                    length=fileLen,
                    start=dsDataBlock,
                    status=statWord,
                    jobchan=jobChan,
                    date=fileDate,
                    extra=rt11util.wordsToBytes(dsEntry[7:]),
                )

                self.fsFileList.append(entry)
                self.fsDataBlocks += fileLen
                dsDataBlock = dsDataBlock + fileLen

            if nextDs > 0:
                rt11util.assertWarn(nextDs == dsNum + 1, "Non-sequential directory segments.")
            dsNum = nextDs