From 0ad62946629c628dfcbef15ceac9140f3c16f345 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 25 Nov 2017 14:00:16 +0000 Subject: [PATCH] Reuse the cache if we're within the same ResourceAccessor. This effectively means that the FileTranslationLayer will reuse the cached file even with multiple opens, but rerunning python, or starting a new context (with a new FileTranslationLayer but on the same URL) will cause a redownload whether necessary or not. This ensures that running volatility as an engine (inside a long lived python session) will not prevent a file being checked again later. Other caching mechanisms (such as last-modified) should be used to determine if the cached file is still valid. Note this may cause issues if plugins run concurrently. --- volatility/framework/layers/__init__.py | 31 +++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/volatility/framework/layers/__init__.py b/volatility/framework/layers/__init__.py index 4b6a990af..84ec3fbde 100644 --- a/volatility/framework/layers/__init__.py +++ b/volatility/framework/layers/__init__.py @@ -40,6 +40,7 @@ class ResourceAccessor(object): """ self._progress_callback = progress_callback self._context = context + self._cached_files = [] self._handlers = list(framework.class_subclasses(request.BaseHandler)) vollog.log(constants.LOGLEVEL_VVV, "Available URL handlers: {}".format(", ".join([x.__name__ for x in self._handlers]))) @@ -60,16 +61,26 @@ class ResourceAccessor(object): block_size = 1028 * 8 temp_filename = os.path.join(constants.CACHE_PATH, "data_" + hashlib.sha512(bytes(url, 'latin-1')).hexdigest()) - cache_file = open(temp_filename, "wb") - while True: - block = fp.read(block_size) - if not block: - break - cache_file.write(block) - if self._progress_callback: - # TODO: Figure out the size and therefore percentage complete - self._progress_callback(0, "Reading file {}".format(url)) - cache_file.close() + + if not temp_filename in self._cached_files or not os.path.exists(temp_filename): + vollog.info("Caching file at: {}".format(temp_filename)) + + content_length = fp.info().get('Content-Length', -1) + cache_file = open(temp_filename, "wb") + + count = 0 + while True: + block = fp.read(block_size) + count += len(block) + if not block: + break + if self._progress_callback: + self._progress_callback(count / max(count, int(content_length)), + "Reading file {}".format(url)) + cache_file.write(block) + cache_file.close() + # Globally stash the file as cached this python session + self._cached_files += [temp_filename] # Re-open the cache with a different mode curfile = open(temp_filename, mode = "rb")