From: Artem Bityutskiy Date: Mon, 20 Jan 2014 14:55:49 +0000 (+0200) Subject: Filemap: implement ugly heuristics for SEEK_HOLE X-Git-Tag: v3.2~36 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=be266a96f89bf9fb901e62ec674aa6c280b70ee0;p=tools%2Fbmap-tools.git Filemap: implement ugly heuristics for SEEK_HOLE Old kernels do not have real SEEK_HOLE support, but instead, provide a stub implementation which just returns EOF. And there seem to be no easy way to find out whether the implementation is real or fake. But we need to know this, because it is crucial for use since we won't get the block map with fake SEEK_HOLE implementation. This patch implements an ugly test which appends a hole to the image file, tests whether SEEK_HOLE is fake or not, and then truncats the image file back to the original size. Change-Id: Ib5744d5247aa0cda02517afe7189059cc5efeb9b Signed-off-by: Artem Bityutskiy --- diff --git a/bmaptools/Filemap.py b/bmaptools/Filemap.py index 2daf77e..fcc2f2c 100644 --- a/bmaptools/Filemap.py +++ b/bmaptools/Filemap.py @@ -26,6 +26,7 @@ import os import struct import array import fcntl +import tempfile from bmaptools import BmapHelpers @@ -153,6 +154,8 @@ _SEEK_HOLE = 4 class FilemapSeek(_FilemapBase): """ This class uses the 'SEEK_HOLE' and 'SEEK_DATA' to find file block mapping. + Unfortunately, the current implementation requires the caller to have write + access to the image file. """ def __init__(self, image): @@ -161,6 +164,46 @@ class FilemapSeek(_FilemapBase): # Call the base class constructor first _FilemapBase.__init__(self, image) + self._probe_seek_hole() + + def _probe_seek_hole(self): + """ + Check whether the system implements 'SEEK_HOLE' and 'SEEK_DATA'. + Unfortunately, there seems to be no clean way for detecting this, + because often the system just fakes them by just assuming that all + files are fully mapped, so 'SEEK_HOLE' always returns EOF and + 'SEEK_DATA' always returns the requested offset. + + I could not invent a better way of detecting the fake 'SEEK_HOLE' + implementation than just to create a temporary file in the same + directory where the image file resides. It would be nice to change this + to something better. + """ + + directory = os.path.dirname(self._image_path) + + try: + tmp_obj = tempfile.TemporaryFile("w+", dir=directory) + except IOError as err: + raise ErrorNotSupp("cannot create a temporary in \"%s\": %s" + % (directory, err)) + + try: + os.ftruncate(tmp_obj.fileno(), self.block_size) + except OSError as err: + raise ErrorNotSupp("cannot truncate temporary file in \"%s\": %s" + % (directory, err)) + + offs = self._lseek(tmp_obj, 0, _SEEK_HOLE) + if offs != 0: + # We are dealing with the stub 'SEEK_HOLE' implementation which + # always returns EOF. + raise ErrorNotSupp("the file-system does not support " + "\"SEEK_HOLE\" and \"SEEK_DATA\" but only " + "provides a stub implementation") + + tmp_obj.close() + def _lseek(self, file_obj, offset, whence): """This is a helper function which invokes 'os.lseek' for file object 'file_obj' and with specified 'offset' and 'whence'. The 'whence'