Ejemplo n.º 1
0
    def _bmap_file_end(self, mapped_cnt, block_size, blocks_cnt):
        """ A helper funstion which generates the final parts of the block map
        file: the ending tags and the information about the amount of mapped
        blocks. """

        xml = "\t</BlockMap>\n\n"

        size = misc.human_size(mapped_cnt * block_size)
        percent = (mapped_cnt * 100.0) / blocks_cnt
        xml += "\t<!-- Count of mapped blocks (%s or %.1f%% mapped) -->\n" \
                % (size, percent)
        xml += "\t<MappedBlocksCount> %u </MappedBlocksCount>\n" % mapped_cnt
        xml += "</bmap>"

        return xml
    def __init__(self, image, bmap):
        """ Initialize a class instance:
        * image - full path or a file-like object of the image to create bmap
                  for
        * bmap  - full path or a file object to use for writing the resulting
                  bmap to """

        self.image_size = None
        self.image_size_human = None
        self.block_size = None
        self.blocks_cnt = None
        self.mapped_cnt = None
        self.mapped_size = None
        self.mapped_size_human = None
        self.mapped_percent = None

        self._mapped_count_pos1 = None
        self._mapped_count_pos2 = None
        self._sha1_pos = None

        self._f_image_needs_close = False
        self._f_bmap_needs_close = False

        if hasattr(image, "read"):
            self._f_image = image
            self._image_path = image.name
        else:
            self._image_path = image
            self._open_image_file()

        if hasattr(bmap, "read"):
            self._f_bmap = bmap
            self._bmap_path = bmap.name
        else:
            self._bmap_path = bmap
            self._open_bmap_file()

        self.fiemap = Fiemap.Fiemap(self._f_image)

        self.image_size = self.fiemap.image_size
        self.image_size_human = human_size(self.image_size)
        if self.image_size == 0:
            raise Error("cannot generate bmap for zero-sized image file '%s'" \
                        % self._image_path)

        self.block_size = self.fiemap.block_size
        self.blocks_cnt = self.fiemap.blocks_cnt
Ejemplo n.º 3
0
    def __init__(self, image, bmap):
        """ Initialize a class instance:
        * image - full path or a file-like object of the image to create bmap
                  for
        * bmap  - full path or a file object to use for writing the resulting
                  bmap to """

        self.image_size = None
        self.image_size_human = None
        self.block_size = None
        self.blocks_cnt = None
        self.mapped_cnt = None
        self.mapped_size = None
        self.mapped_size_human = None
        self.mapped_percent = None

        self._mapped_count_pos1 = None
        self._mapped_count_pos2 = None
        self._sha1_pos = None

        self._f_image_needs_close = False
        self._f_bmap_needs_close = False

        if hasattr(image, "read"):
            self._f_image = image
            self._image_path = image.name
        else:
            self._image_path = image
            self._open_image_file()

        if hasattr(bmap, "read"):
            self._f_bmap = bmap
            self._bmap_path = bmap.name
        else:
            self._bmap_path = bmap
            self._open_bmap_file()

        self.fiemap = Fiemap.Fiemap(self._f_image)

        self.image_size = self.fiemap.image_size
        self.image_size_human = human_size(self.image_size)
        if self.image_size == 0:
            raise Error("cannot generate bmap for zero-sized image file '%s'" \
                        % self._image_path)

        self.block_size = self.fiemap.block_size
        self.blocks_cnt = self.fiemap.blocks_cnt
Ejemplo n.º 4
0
    def _bmap_file_start(self, block_size, image_size, blocks_cnt):
        """ A helper function which generates the starting contents of the
        block map file: the header comment, image size, block size, etc. """

        xml = "<?xml version=\"1.0\" ?>\n\n"
        xml += "<!-- This file contains block map for an image file. The block map\n"
        xml += "     is basically a list of block numbers in the image file. It lists\n"
        xml += "     only those blocks which contain data (boot sector, partition\n"
        xml += "     table, file-system metadata, files, directories, extents, etc).\n"
        xml += "     These blocks have to be copied to the target device. The other\n"
        xml += "     blocks do not contain any useful data and do not have to be\n"
        xml += "     copied to the target device. Thus, using the block map users can\n"
        xml += "     flash the image fast. So the block map is just an optimization.\n"
        xml += "     It is OK to ignore this file and just flash the entire image to\n"
        xml += "     the target device if the flashing speed is not important.\n\n"

        xml += "     Note, this file contains commentaries with useful information\n"
        xml += "     like image size in gigabytes, percentage of mapped data, etc.\n"
        xml += "     This data is there merely to make the XML file human-readable.\n\n"

        xml += "     The 'version' attribute is the block map file format version in\n"
        xml += "     the 'major.minor' format. The version major number is increased\n"
        xml += "     whenever we make incompatible changes to the block map format,\n"
        xml += "     meaning that the bmap-aware flasher would have to be modified in\n"
        xml += "     order to support the new format. The minor version is increased\n"
        xml += "     in case of compatible changes. For example, if we add an attribute\n"
        xml += "     which is optional for the bmap-aware flasher. -->\n"
        xml += "<bmap version=\"1.1\">\n"
        xml += "\t<!-- Image size in bytes (%s) -->\n" \
                % misc.human_size(image_size)
        xml += "\t<ImageSize> %u </ImageSize>\n\n" % image_size

        xml += "\t<!-- Size of a block in bytes -->\n"
        xml += "\t<BlockSize> %u </BlockSize>\n\n" % block_size

        xml += "\t<!-- Count of blocks in the image file -->\n"
        xml += "\t<BlocksCount> %u </BlocksCount>\n\n" % blocks_cnt

        xml += "\t<!-- The block map which consists of elements which may either\n"
        xml += "\t     be a range of blocks or a single block. The 'sha1' attribute\n"
        xml += "\t     is the SHA1 checksum of the this range of blocks. -->\n"
        xml += "\t<BlockMap>\n"

        return xml
Ejemplo n.º 5
0
    def generate(self, include_checksums=True):
        """
        Generate bmap for the image file. If 'include_checksums' is 'True',
        also generate checksums for block ranges.
        """

        # Save image file position in order to restore it at the end
        image_pos = self._f_image.tell()

        self._bmap_file_start()

        # Generate the block map and write it to the XML block map
        # file as we go.
        self.mapped_cnt = 0
        for first, last in self.filemap.get_mapped_ranges(0, self.blocks_cnt):
            self.mapped_cnt += last - first + 1
            if include_checksums:
                chksum = self._calculate_chksum(first, last)
                chksum = " chksum=\"%s\"" % chksum
            else:
                chksum = ""

            if first != last:
                self._f_bmap.write("        <Range%s> %s-%s </Range>\n"
                                   % (chksum, first, last))
            else:
                self._f_bmap.write("        <Range%s> %s </Range>\n"
                                   % (chksum, first))

        self.mapped_size = self.mapped_cnt * self.block_size
        self.mapped_size_human = human_size(self.mapped_size)
        self.mapped_percent = (self.mapped_cnt * 100.0) /  self.blocks_cnt

        self._bmap_file_end()

        try:
            self._f_bmap.flush()
        except IOError as err:
            raise Error("cannot flush the bmap file '%s': %s"
                        % (self._bmap_path, err))

        self._f_image.seek(image_pos)
Ejemplo n.º 6
0
    def generate(self, include_checksums = True):
        """ Generate bmap for the image file. If 'include_checksums' is 'True',
        also generate SHA1 checksums for block ranges. """

        # Save image file position in order to restore it at the end
        image_pos = self._f_image.tell()

        self._bmap_file_start()

        # Generate the block map and write it to the XML block map
        # file as we go.
        self.mapped_cnt = 0
        for first, last in self.fiemap.get_mapped_ranges(0, self.blocks_cnt):
            self.mapped_cnt += last - first + 1
            if include_checksums:
                sha1 = self._calculate_sha1(first, last)
                sha1 = " sha1=\"%s\"" % sha1
            else:
                sha1 = ""

            if first != last:
                self._f_bmap.write("        <Range%s> %s-%s </Range>\n" \
                                   % (sha1, first, last))
            else:
                self._f_bmap.write("        <Range%s> %s </Range>\n" \
                                   % (sha1, first))

        self.mapped_size = self.mapped_cnt * self.block_size
        self.mapped_size_human = human_size(self.mapped_size)
        self.mapped_percent = (self.mapped_cnt * 100.0) /  self.blocks_cnt

        self._bmap_file_end()

        try:
            self._f_bmap.flush()
        except IOError as err:
            raise Error("cannot flush the bmap file '%s': %s" \
                        % (self._bmap_path, err))

        self._f_image.seek(image_pos)
Ejemplo n.º 7
0
    def __init__(self, image, bmap, chksum_type="sha256", log=None):
        """
        Initialize a class instance:
        * image  - full path or a file-like object of the image to create bmap
                   for
        * bmap   - full path or a file object to use for writing the resulting
                   bmap to
        * chksum - type of the check sum to use in the bmap file (all checksum
                   types which python's "hashlib" module supports are allowed).
        * log     - the logger object to use for printing messages.
        """

        self._log = log
        if self._log is None:
            self._log = logging.getLogger(__name__)

        self.image_size = None
        self.image_size_human = None
        self.block_size = None
        self.blocks_cnt = None
        self.mapped_cnt = None
        self.mapped_size = None
        self.mapped_size_human = None
        self.mapped_percent = None

        self._mapped_count_pos1 = None
        self._mapped_count_pos2 = None
        self._chksum_pos = None

        self._f_image_needs_close = False
        self._f_bmap_needs_close = False

        self._cs_type = chksum_type.lower()
        try:
            self._cs_len = len(hashlib.new(self._cs_type).hexdigest())
        except ValueError as err:
            raise Error("cannot initialize hash function \"%s\": %s" %
                        (self._cs_type, err))

        if hasattr(image, "read"):
            self._f_image = image
            self._image_path = image.name
        else:
            self._image_path = image
            self._open_image_file()

        if hasattr(bmap, "read"):
            self._f_bmap = bmap
            self._bmap_path = bmap.name
        else:
            self._bmap_path = bmap
            self._open_bmap_file()

        try:
            self.filemap = Filemap.filemap(self._f_image, self._log)
        except (Filemap.Error, Filemap.ErrorNotSupp) as err:
            raise Error("cannot generate bmap: %s" % err)

        self.image_size = self.filemap.image_size
        self.image_size_human = human_size(self.image_size)
        if self.image_size == 0:
            raise Error("cannot generate bmap for zero-sized image file '%s'"
                        % self._image_path)

        self.block_size = self.filemap.block_size
        self.blocks_cnt = self.filemap.blocks_cnt