1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
#!/usr/bin/python
#
# Copyright 2011, Michael Cohen <scudette@gmail.com>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This module selects a suitable image info object based on the type."""
import bisect
import sys
import pyqcow
import ewf
import pytsk3
class EWFImgInfo(pytsk3.Img_Info):
"""An image info class which uses ewf as a backing reader.
All we really need to do to provide TSK with the ability to read image formats
is override the methods below.
"""
def __init__(self, *paths_to_ewf_files):
self.fd = ewf.ewffile(*paths_to_ewf_files)
# Make sure to call the original base constructor.
pytsk3.Img_Info.__init__(self, "")
def get_size(self):
"""This should return the size of the image."""
return self.fd.size
def read(self, off, length):
"""This method simply returns data from a particular offset."""
self.fd.seek(off)
return self.fd.read(length)
def close(self):
"""Dispose of the underlying file like object."""
self.fd.close()
class QcowImgInfo(pytsk3.Img_Info):
def __init__(self, filename):
self._qcow_file = pyqcow.file()
self._qcow_file.open(filename)
super(QcowImgInfo, self).__init__(
url='', type=pytsk3.TSK_IMG_TYPE_EXTERNAL)
def close(self):
self._qcow_file.close()
def read(self, offset, size):
self._qcow_file.seek(offset)
return self._qcow_file.read(size)
def get_size(self):
return self._qcow_file.get_media_size()
class SplitImage(pytsk3.Img_Info):
"""Virtualize access to split images.
Note that unlike other tools (e.g. affuse) we do not assume that the images
are the same size.
"""
def __init__(self, *files):
self.fds = []
self.offsets = [0]
offset = 0
for fd in files:
# Support either a filename or file like objects
if not hasattr(fd, "read"):
fd = open(fd, "rb")
fd.seek(0,2)
offset += fd.tell()
self.offsets.append(offset)
self.fds.append(fd)
self.size = offset
# Make sure to call the original base constructor.
pytsk3.Img_Info.__init__(self, "")
def get_size(self):
return self.size
def read(self, offset, length):
"""Read a buffer from the split image set.
Handles the buffer straddling images.
"""
result = ""
# The total available size in the file
length = int(length)
length = min(length, long(self.size) - offset)
while length > 0:
data = self._ReadPartial(offset, length)
if not data: break
length -= len(data)
result += data
offset += len(data)
return result
def _ReadPartial(self, offset, length):
"""Read as much as we can from the current image."""
# The part we need to read from.
idx = bisect.bisect_right(self.offsets, offset + 1) - 1
fd = self.fds[idx]
# The offset this part is in the overall image
img_offset = self.offsets[idx]
fd.seek(offset - img_offset)
# This can return less than length
return fd.read(length)
def SelectImage(img_type, files):
if img_type == "raw":
if len(files) == 1:
# For a single file this is faster.
return pytsk3.Img_Info(files[0])
else:
return SplitImage(*files)
elif img_type == "ewf":
# Instantiate our special image object
return EWFImgInfo(*files)
elif img_type == "qcow":
return QcowImgInfo(files[0])
|