예제 #1
0
파일: rt11fs.py 프로젝트: NF6X/pyRT11
    def deSetData(self, data):
        """Set contents of data blocks.

        Length of data must be deLength * rt11util.rtBlockSize."""

        rt11util.assertError(
            len(data) == (self.deLength * rt11util.rtBlockSize), "deSetData() received invalid data length."
        )
        self.deData = data
예제 #2
0
파일: rad50.py 프로젝트: NF6X/pyRT11
def rad50ToFilename(inRad50):
    """Returns ASCII string of filename represented by list of Radix-50 words (inRad50).

    inRad50 must be exactly 3 words long, with the first two words representing the
    filename and the final word representing the extension. Filename and extension
    will be trimmed of trailing spaces."""

    rt11util.assertError(len(inRad50) == 3, "rad50ToFilename() requires 3-word list.")
    fname = rad50ListToAsc(inRad50[0:2]).rstrip(' ')
    fext  = rad50ValToAsc(inRad50[2]).rstrip(' ')
    return fname + '.' + fext
예제 #3
0
파일: tu58.py 프로젝트: NF6X/pyRT11
    def __init__(self, port, speed=9600, blocks=512):
        """Initialize the class and connect to the drive.

        Caller must specify path to serial port device.
        Optionally specify baud rate.
        Optionally specify length of tape in blocks if connecting to an
        emulated drive with a nonstandard tape length."""

        rt11util.assertError(speed > 0, "Baud rate must be positive.")
        rt11util.assertError(blocks > 0, "Block count must be positive.")
        rt11util.assertError(blocks <= 65536, "Block must not exceed 65536.")

        self._blocks = blocks
        try:
            self._port = serial.Serial(port, speed, timeout=0)
        except:
            rt11util.assertError(False, 'Could not open serial port "{:s}".'.format(port))

        self.init()
예제 #4
0
파일: tu58.py 프로젝트: NF6X/pyRT11
 def readblock(self, unit, block):
     rt11util.assertError(block >= 0, "Block number must not be negative.")
     rt11util.assertError(block < self._blocks, "Block number is too large.")
     pass
예제 #5
0
파일: rt11fs.py 프로젝트: NF6X/pyRT11
    def fsAddFile(self, hostFilename, rtFilename="", dateWord=None, statusWord=deEPERM):
        """Read file and add it to the RT-11 filesystem.

        hostFilename refers to a local file on the host's filesystem.
        If rtFilename is not specified, filename on RT-11 filesystem will
        be derived from hostFilename.
        If host file size is not a multiple of rtBlockSize, it will be
        padded with zeroes.
        Negative dateWord will be replaced with today's date."""

        # Use host filename if RT-11 name not specified
        if rtFilename == "":
            rtFilename = hostFilename

        rad50Filename = rad50.filenameToRad50(rtFilename)
        rtFilename = rad50.rad50ToFilename(rad50Filename)

        if dateWord is None:
            dateWord = rt11util.todayWord(self.fsThisYear)

        # Read host file, pad if necessary
        f = open(hostFilename, "rb")
        buf = f.read()
        f.close
        pad = rt11util.rtBlockSize - (len(buf) % rt11util.rtBlockSize)
        if pad != 512:
            buf += "\000" * pad
        fileLen = len(buf) / rt11util.rtBlockSize

        # Delete existing file with same name
        self.fsDeleteFile(rtFilename)

        # Search for first empty block large enough to hold file
        addedFile = False
        for idx, de in enumerate(self.fsFileList):
            if (de.deStatus & deEMPTY) and (de.deLength >= fileLen):
                addedFile = True

                # If empty block is larger than new file, split it.
                if de.deLength > fileLen:
                    ede = dirEntry(
                        name=rad50.filenameToRad50(" EMPTY.FIL"),
                        length=de.deLength - fileLen,
                        start=de.deStart + fileLen,
                        status=deEMPTY,
                        date=rt11util.todayWord(self.fsThisYear),
                    )
                    ede.deEmptyData()
                    self.fsFileList.insert(idx + 1, ede)

                de.deStatus = statusWord
                de.deName = rad50Filename
                de.deLength = fileLen
                de.deJobChan = 0
                de.deDate = dateWord
                de.deSetData(buf)

                self.fsFileList[idx] = de
                break

        rt11util.assertError(addedFile, "Could not find space for " + rtFilename)
예제 #6
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)
예제 #7
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
예제 #8
0
파일: rt11fs.py 프로젝트: NF6X/pyRT11
 def fsValidate(self):
     """Sanity-check filesystem parameters."""
     rt11util.assertError(self.fsSize > 9, "Filesystem is too small.")  # ?
     rt11util.assertError(self.fsSize < 65536, "Filesystem is too large.")
     rt11util.assertError(self.fsNumDirSegs > 0, "No directory segments.")
     rt11util.assertError(self.fsNumDirSegs < 32, "Too many directory segments.")
     rt11util.assertError(self.fsExtraWords >= 0, "Negative extra dir entry byte count.")
     rt11util.assertWarn(self.fsFirstDirSeg == 6, "Unexpected first directory segment block number.")
     rt11util.assertWarn(
         self.fsDataStart == (self.fsFirstDirSeg + (self.fsNumDirSegs * 2)),
         "Data blocks do not start immediately after directory segments.",
     )
     rt11util.assertError(
         self.fsDataStart + self.fsDataBlocks + self.fsResBlocks == self.fsSize, "Invalid block counts."
     )
     rt11util.assertError(self.fsResBlocks >= 0, "Negative reserved block count.")