import array
import fcntl
import tempfile
+import logging
from bmaptools import BmapHelpers
"""
This is a base class for a couple of other classes in this module. This
class simply performs the common parts of the initialization process: opens
- the image file, gets its size, etc.
+ the image file, gets its size, etc. The 'log' parameter is the logger object
+ to use for printing messages.
"""
- def __init__(self, image):
+ def __init__(self, image, log=None):
"""
Initialize a class instance. The 'image' argument is full path to the
file or file object to operate on.
"""
+ self._log = log
+ if self._log is None:
+ self._log = logging.getLogger(__name__)
+
self._f_image_needs_close = False
if hasattr(image, "fileno"):
raise Error("cannot synchronize image file '%s': %s "
% (self._image_path, err.strerror))
+ self._log.debug("opened image \"%s\"" % self._image_path)
+ self._log.debug("block size %d, blocks count %d, image size %d"
+ % (self.block_size, self.blocks_cnt, self.image_size))
+
def __del__(self):
"""The class destructor which just closes the image file."""
if self._f_image_needs_close:
access to the image file.
"""
- def __init__(self, image):
+ def __init__(self, image, log=None):
"""Refer the '_FilemapBase' class for the documentation."""
# Call the base class constructor first
- _FilemapBase.__init__(self, image)
+ _FilemapBase.__init__(self, image, log)
+ self._log.debug("FilemapSeek: initializing")
self._probe_seek_hole()
if offs != 0:
# We are dealing with the stub 'SEEK_HOLE' implementation which
# always returns EOF.
+ self._log.debug("lseek(0, SEEK_HOLE) returned %d" % offs)
raise ErrorNotSupp("the file-system does not support "
"\"SEEK_HOLE\" and \"SEEK_DATA\" but only "
"provides a stub implementation")
"""Refer the '_FilemapBase' class for the documentation."""
offs = self._lseek(self._f_image, block * self.block_size, _SEEK_DATA)
if offs == -1:
- return False
+ result = False
+ else:
+ result = (offs / self.block_size == block)
- return offs / self.block_size == block
+ self._log.debug("FilemapSeek: block_is_mapped(%d) returns %s"
+ % (block, result))
+ return result
def block_is_unmapped(self, block):
"""Refer the '_FilemapBase' class for the documentation."""
if end > limit:
end = limit
- yield (start / self.block_size, end / self.block_size - 1)
+ start_blk = start / self.block_size
+ end_blk = end / self.block_size - 1
+ self._log.debug("FilemapSeek: yielding range (%d, %d)"
+ % (start_blk, end_blk))
+ yield (start_blk, end_blk)
def get_mapped_ranges(self, start, count):
"""Refer the '_FilemapBase' class for the documentation."""
+ self._log.debug("FilemapSeek: get_mapped_ranges(%d, %d(%d))"
+ % (start, count, start + count - 1))
return self._get_ranges(start, count, _SEEK_DATA, _SEEK_HOLE)
def get_unmapped_ranges(self, start, count):
"""Refer the '_FilemapBase' class for the documentation."""
+ self._log.debug("FilemapSeek: get_unmapped_ranges(%d, %d(%d))"
+ % (start, count, start + count - 1))
return self._get_ranges(start, count, _SEEK_HOLE, _SEEK_DATA)
ioctl in order to work-around early FIEMAP implementation kernel bugs.
"""
- def __init__(self, image):
+ def __init__(self, image, log=None):
"""
Initialize a class instance. The 'image' argument is full the file
object to operate on.
"""
# Call the base class constructor first
- _FilemapBase.__init__(self, image)
+ _FilemapBase.__init__(self, image, log)
+ self._log.debug("FilemapFiemap: initializing")
self._buf_size = _FIEMAP_BUFFER_SIZE
# Note, the FIEMAP ioctl is supported by the Linux kernel starting
# from version 2.6.28 (year 2008).
if err.errno == os.errno.EOPNOTSUPP:
- raise ErrorNotSupp("the FIEMAP ioctl is not supported by "
- "the file-system")
+ errstr = "FilemapFiemap: the FIEMAP ioctl is not supported " \
+ "by the file-system"
+ self._log.debug(errstr)
+ raise ErrorNotSupp(errstr)
if err.errno == os.errno.ENOTTY:
- raise ErrorNotSupp("the FIEMAP ioctl is not supported by "
- "the kernel")
+ errstr = "FilemapFiemap: the FIEMAP ioctl is not supported " \
+ "by the kernel"
+ self._log.debug(errstr)
+ raise ErrorNotSupp(errstr)
raise Error("the FIEMAP ioctl failed for '%s': %s"
% (self._image_path, err))
# The 3rd element of 'struct_fiemap' is the 'fm_mapped_extents' field.
# If it contains zero, the block is not mapped, otherwise it is
# mapped.
- return bool(struct_fiemap[3])
+ result = bool(struct_fiemap[3])
+ self._log.debug("FilemapFiemap: block_is_mapped(%d) returns %s"
+ % (block, result))
+ return result
def block_is_unmapped(self, block):
"""Refer the '_FilemapBase' class for the documentation."""
def get_mapped_ranges(self, start, count):
"""Refer the '_FilemapBase' class for the documentation."""
+ self._log.debug("FilemapFiemap: get_mapped_ranges(%d, %d(%d))"
+ % (start, count, start + count - 1))
iterator = self._do_get_mapped_ranges(start, count)
-
first_prev, last_prev = iterator.next()
for first, last in iterator:
if last_prev == first - 1:
last_prev = last
else:
+ self._log.debug("FilemapFiemap: yielding range (%d, %d)"
+ % (first_prev, last_prev))
yield (first_prev, last_prev)
first_prev, last_prev = first, last
+ self._log.debug("FilemapFiemap: yielding range (%d, %d)"
+ % (first_prev, last_prev))
yield (first_prev, last_prev)
def get_unmapped_ranges(self, start, count):
"""Refer the '_FilemapBase' class for the documentation."""
+ self._log.debug("FilemapFiemap: get_unmapped_ranges(%d, %d(%d))"
+ % (start, count, start + count - 1))
hole_first = start
for first, last in self._do_get_mapped_ranges(start, count):
if first > hole_first:
+ self._log.debug("FilemapFiemap: yielding range (%d, %d)"
+ % (hole_first, first - 1))
yield (hole_first, first - 1)
hole_first = last + 1
if hole_first < start + count:
+ self._log.debug("FilemapFiemap: yielding range (%d, %d)"
+ % (hole_first, start + count - 1))
yield (hole_first, start + count - 1)
-def filemap(image):
+def filemap(image, log=None):
"""
Create and return an instance of a Filemap class - 'FilemapFiemap' or
'FilemapSeek', depending on what the system we run on supports. If the
"""
try:
- return FilemapFiemap(image)
+ return FilemapFiemap(image, log)
except ErrorNotSupp:
- return FilemapSeek(image)
+ return FilemapSeek(image, log)