Пример #1
0
    def ds_open(self,extent):
        assert isinstance(extent,Extent),\
            "%s 'extent' argument must be a fbadscb.Extent object: %s" \
                % (eloc(self,"ds_open",module=this_module),extent)
        if self.extent:
            raise NotImplementedError("%s extent already open: %s" \
                % (eloc(self,"ds_open",module=this_module),self.extent))

        self._ck_extent(extent)

        self.extent=extent      # Remember the physical extent
        self.lower=extent.lower # The first physical sector of the extent
        self.upper=extent.upper # The last physical sector of the extent
        self.ds_sector=0        # The next logical sector to be accessed
        self.ds_sectors=extent.sectors()  # Calculate the number of sectors
        self.ds_last=self.ds_sectors-1    # The last logical sector in the extent

        # Trace the data set open if tracing is enabled
        if __debug__:
            if self._trace:
                print("%s DS_OPEN: extent:%s  sectors:%s  logical sectors:0-%s" \
                    % (eloc(self,"ds_open",module=this_module),\
                        extent,self.ds_sectors,self.ds_last))

        self.seek(self.lower)   # Position at start of the extent   
Пример #2
0
    def seek(self,sector):
        # Determine the position in the file for a physical sector access
        if sector>self.last:
            raise ValueError("%s FBA sector %s is beyond last sector %s" \
                % (eloc(self,"seek",module=this_module),sector,self.last))
        sector_loc=sector*512
        if sector_loc>self.filesize:
            raise IOError("%s FBA sector %s file position %s is beyond EOF: %s" \
                % (eloc(self,"seek",module=this_module),sector,sector_loc,\
                    self.filesize))

        # Perform the positioning by physical sector number in this object and
        # position the file object accordingly
        try:
            self.fo.seek(sector_loc)
        except IOError:
            raise IOError("%s IOError while positioning to FBA sector: %s" \
                % (eloc(self,"seek",module=this_module),self.sector))

        self.sector=sector

        # Trace the seek if physical tracing is enabled
        if __debug__:
            if self._trace:
                print("%s SEEK: sector: %s  file pos: %s" \
                    % (eloc(self,"seek",module=this_module),sector,self.fo.tell()))
Пример #3
0
    def ds_tell(self):
        if not self.extent:
            raise NotImplementedError("%s no open extent for logical sector position" \
                % (eloc(self,"ds_tell",module=this_module)))

        if __debug__:
            if self._trace:
                print("%s returning: %s" \
                    % (eloc(self,"ds_tell",module=this_module),self.ds_sector))

        return self.ds_sector
Пример #4
0
    def _to_physical(self,sector,sectors=1):
        assert sector >=0,"%s 'sector' argument must be >= 0: %s" \
            % (eloc(self,"_to_physical",module=this_module),sector)
        assert sectors >=1,"%s 'sectors' argument must be >= 1: %s" \
            % (eloc(self,"_to_physical",module=this_module),sectors)

        l_last=sector+sectors-1
        if l_last > self.upper:
            raise ValueError(\
                "%s end of operation beyond end of extent (%s): %s" \
                    % (eloc(self,"_to_physical",module=this_module),\
                        self.upper,l_last))

        return (self.lower+sector,self.lower+l_last,l_last)
Пример #5
0
    def ds_erase(self,sector=0,sectors=1,fill=0):
        assert isinstance(sector,int) and sector>=0,\
            "%s 'sector' argument must be an integer >= 0: %s"\
                % (eloc(self,"ds_erase",module=this_module),sector)
        if self.ro:
            raise NotImplementedError("%s can not erase a read-only image file: %s"\
                % (eloc(self,"ds_erase",module=this_module),self.filename))
        if not self.extent:
            raise NotImplementedError("%s no open extent for erasing" \
                % (eloc(self,"ds_erase",module=this_module)))

        # Create the content for an erased sector
        if isinstance(fill,str):
            if len(fill)>0:
                f=ord(fill[0])
            else:
                raise ValueError("%s 'fill' argument must not be an empty string"\
                    % eloc(self,"ds_erase",module=this_module))
        elif isinstance(fill,int):
            if fill<0 or fill >255:
                raise ValueError("%s 'fill' argument out of range (0-255): %s" \
                    % eloc(self,"ds_erase",module=this_module),fill)
            f=fill
        byts=bytes([f,]*512)

        # Determine the physical sectors of erased area
        if sectors == True:
            secs=self.ds_sectors
        else:
            assert isinstance(sectors,int) and sectors>=1,\
               "%s 'sectors' argument must be True or an integer >= 1: %s" \
                   % (eloc(self,"ds_erase",module=this_module),sectors)
            secs=sectors

        p_first,p_last,l_last = self._to_physical(sector,sectors=secs)

        # Erase the requested sectors' content
        self.seek(p_first)
        sec=sector
        if __debug__:
            if self._trace:
                if secs == 1:
                    s="%s DS_ERASING: logical sector:%s  physical sector: %s"\
                        "file pos:%s  with:%02X" \
                            % (eloc(self,"ds_read",module=this_module),\
                                sector,p_first,self.fo.tell(),f)
                else:
                    s="%s DS_ERASING: logical sectors:%s-%s  physical sectors: %s-%s" \
                        "  sectors:%s  file pos:%s  with:0x%02X" \
                            % (eloc(self,"ds_read",module=this_module),\
                                sector,l_last,p_first,p_last,secs,self.fo.tell(),\
                                    f)
                print(s)

        # Erase the requested sectors' content
        for n in range(secs):
            self._write(byts)
            self.sector+=1
            self.ds_sector+=1
Пример #6
0
    def _ck_extent(self,extent):
        if extent.notused:
            raise ValueError("%s Extent object must be used: %s" \
                % (eloc(self,"_ck_extent",module=this_module),extent))

        lower=extent.lower
        if lower>self.last:
            raise ValueError(\
                "%s extent lower boundary is not within the FBA image (0-%s): %s"\
                    % (eloc(self,"_ck_extent",module=this_module),self.last,lower))
        upper=extent.upper
        if upper>self.last:
            raise ValueError(\
                "%s extent upper boundary is not within the FBA image (0-%s): %s"\
                    % (eloc(self,"_ck_extent",module=this_module),self.last,upper))
Пример #7
0
    def read(self,sector=None,array=False):
        # Position the image file if requested to do so.
        if sector is not None: 
            self.seek(sector)

        # Trace the read if physical tracing is enabled
        if __debug__:
            if self._trace:
                sec=self.sector
                fpos=self.fo.tell()

        # Read the physical sector using the low-level routine
        data=self._read(512)
        self.sector+=1

        # Trace the read if physical tracing is enabled
        if __debug__:
            if self._trace:
                print("%s READ: sector: %s  file pos: %s" \
                    % (eloc(self,"read",module=this_module),sec,fpos))
                if self._tdump:
                    dump(data,indent="    ")

        # Return the information is the requested sequence type
        if array:
            return bytearray(data)
        return data
Пример #8
0
    def ds_write(self,byts,sector=None):
        if self.ro:
            raise NotImplementedError("%s can not write to a read-only image file: %s"\
                % (eloc(self,"ds_write",module=this_module),self.filename))
        if not self.extent:
            raise NotImplementedError("%s no open extent for writing" \
                % (eloc(self,"ds_write",module=this_module)))
          
        # Validate there is enough data to write entire sectors
        try:
            sectors=bytes2sectors(byts)
        except ValueError:
            raise ValueError("%s 'byts' argument not full sectors, length: %s" \
                % (eloc(self,"ds_write",module=this_module),len(byts))) from None
            
        # Locate where the write operation begins
        if sector is None:
            sec=self.ds_sector
        else:
            sec=sector

        p_first,p_last,l_last=self._to_physical(sec,sectors=sectors)

        # Position to the starting sector
        self.seek(p_first)
        self.ds_sector=sec

        # Perform tracing if requested.
        if __debug__:
            if self._trace:
                if sectors == 1:
                    s="%s DS_WRITE: logical sector:%s  physical sector: %s"\
                        "file pos: %s" % (eloc(self,"ds_write",module=this_module),\
                            sector,p_first,self.fo.tell())
                else:
                    s="%s DS_WRITE: logical sectors:%s-%s  physical sectors: %s-%s" \
                        "sectors:%s  file pos:%s" \
                            % (eloc(self,"ds_write",module=this_module),sector,\
                                l_last,p_first,p_last,sectors,self.fo.tell())
                print(s)
                if self._tdump:
                    dump(byts,indent="    ")

        # Write the sector' or sectors' content
        self._write(byts)
        self.sector+=sectors
        self.ds_sector+=sectors
Пример #9
0
 def trace(self,state,dump=False):
     if state:
         self._trace=True
         self._tdump=dump
         if __debug__:
             print("%s set tracing:%s, dump:%s" \
                 % (eloc(self,"trace",module=this_module),self._trace,self._tdump))
     else:
         if __debug__:
             was_tracing=self._trace
         self._trace=False
         self._tdump=False
         if __debug__:
             if was_tracing:
                 print("%s set tracing:%s, dump:%s" \
                     % (eloc(self,"trace",module=this_module),\
                         self._trace,self.dump))
Пример #10
0
    def detach(self):
        if __debug__:
            if self._trace:
                print("%s detaching image file: %s" \
                    % (eloc(self,"detach",module=this_module),self.filename))

        if self.extent:
            self.ds_close()
        try:
            self.fo.flush()
            self.fo.close()
        except IOError:
            raise IOError(\
                "%s IOError detaching %s FBA image: %s" \
                    % (eloc(self,"detach",module=this_module),self.filename))

        self.pending=False
Пример #11
0
    def ds_read(self,sector=None,sectors=1,array=False):
        if not self.extent:
            raise NotImplementedError("%s no open extent for reading" \
                % eloc(self,"ds_read",module=this_module))

        if sector is None:
            sec=self.ds_sector
        else:
            sec=sector

        p_first,p_last,l_last=self._to_physical(sec,sectors=sectors)

        # Position to the starting sector
        self.seek(p_first)
        self.ds_sector=sec

        # Perform tracing if requested
        if __debug__:
            if self._trace:
                if sectors == 1:
                    s="%s DS_READ: logical sector:%s  physical sector: %s"\
                    "  file pos:%s" % (eloc(self,"ds_read",module=this_module),\
                            sec,p_first,self.fo.tell())
                else:
                    s="%s DS_READ: logical sectors:%s-%s  physical sectors: %s-%s" \
                        "  sectors:%s  file pos: %s"\
                            % (eloc(self,"ds_read",module=this_module),\
                                sec,l_last,p_first,p_last,sectors,self.fo.tell())
                print(s)

        # Read the sector' or sectors' content
        byts=self._read(sectors*512)
        self.sector+=sectors
        self.ds_sector+=sectors
        
        # Dump the content read from the file image if content tracing enabled
        if __debug__:
            if self._tdump:
                dump(byts,indent="    ")

        # Return the content read from the sector or sectors as bytes or bytearray
        # as requested.
        if array:
            return bytearray(byts)
        return byts
Пример #12
0
    def _read(self,size):
        # Force writing any pending writes before attempting to read the file
        # otherwise, the image file may have stale sector data.
        if self.pending:
            # By using this method we get to trace the flush operation
            self.flush()

        # Read the requested bytes
        try:
             byts=self.fo.read(size)
        except IOError:
            raise IOError("%s IOError while reading FBA physical sector: %s" \
                % (eloc(self,"_read",module=this_module),self.sector))

        # Ensure we actually read the number of expected bytes.
        if len(byts)!=size:
            raise ValueError(\
                "%s did not read requested bytes (%s) from image file: %s"
                    % (eloc(self,"_read",module=this_module),size,len(byts)))
        return byts
Пример #13
0
    def _write(self,data):
        # Ensure bytes sequence is being written not bytearray.  Python requires
        # a bytes sequence.  Sequence can not be bytearray.  This give the using
        # software the freedom to use either sequence.
        if isinstance(data,bytearray):
            byts=bytes(data)
        else:
            byts=data
        assert isinstance(byts,bytes),\
            "%s 'data' argument must be a bytes/bytearray sequence for sector %s: %s" \
                % (eloc(self,"_write",module=this_module),byts,self.sector)

        # Write the bytes
        try:
            self.fo.write(byts)
        except IOError:
            raise IOError(\
                "%s IOError while writing FBA physical sector: %s" \
                    % (eloc(self,"write",module=this_module),self.sector))

        self.pending=True        # Indicate the write might be pending
Пример #14
0
    def ds_extent(self,lower,upper):
        if upper is True:
            up=self.last
        else:
            up=upper

        ext=Extent(lower=lower,upper=up)
        if __debug__:
            if self._trace:
                print("%s returned: %s" % (eloc(self,"ds_extent"),ext))

        return ext
Пример #15
0
    def ds_close(self):
        # Trace the data set close if logical sector tracing is enabled
        if __debug__:
            if self._trace:
                print("%s DS_CLOSE: closing extent: %s" \
                    % (eloc(self,"ds_close",module=this_module),self.extent))

        if self.extent:
            self.flush()     # Write any pending sectors to the image file

        self.ds_sector=self.ds_last=self.extent=self.lower=self.upper=None
        self.ds_sectors=0
Пример #16
0
    def write(self,byts,sector=None,pad=False):
        if self.ro:
            raise NotImplementedError(\
                "%s can not write to read-only FBA image: %s" \
                    % (eloc(self,"write",module=this_module),self.filename))

        # Position the image file if requested to do so.
        if sector is not None:
            self.seek(sector)

        # Pad or detect truncated sector content
        data=byts
        if len(data)!=512:
            if pad:
               data=data+fba.pad
               data=data[:512]
            else:
                raise ValueError("%s FBA image sector must be 512 bytes: %s"\
                    % (eloc(self,"write",module=this_module),len(data)))

        # Trace the write operation if physical sector tracing is enabled
        if __debug__:
            if self._trace:
                if len(data)>len(byts):
                    padded="  pad: %s" % len(data) - len(byts)
                else:
                    padded=""
                print("%s WRITE: sector: %s  file pos: %s%s" \
                    % (eloc(self,"write",module=this_module),\
                        sector,self.fo.tell(),padded))
                if self._tdump:
                    dump(data,indent="    ")

        # Write to the sector using the low-level routine
        self._write(data)
        self.sector+=1
Пример #17
0
 def tell(self):
     if __debug__:
         if self._trace:
             print("%s returning: %s" % (eloc(self,"tell",module=this_module),\
                 self.sector))
     return self.sector
Пример #18
0
 def flush(self):
     if __debug__:
         if self._trace:
             print("%s forcing pending image file writes" \
                 % eloc(self,"flush",module=this_module))
     self._flush()   # Use the low-level method to actually force pending writes