Skip to content

Commit

Permalink
Code review: 283010043: Added LVM support #89
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimmetz committed Feb 21, 2016
1 parent 64dcc2e commit 0783a44
Show file tree
Hide file tree
Showing 83 changed files with 1,554 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ language: python
python:
- "2.7"
before_install:
- if test `uname -s` = 'Linux'; then sudo add-apt-repository ppa:gift/dev -y && sudo apt-get update -q && sudo apt-get install libbde-python libewf-python libfsntfs-python libqcow-python libsigscan-python libsmdev-python libsmraw-python libtsk libvhdi-python libvmdk-python libvshadow-python python-construct python-coverage python-coveralls python-crypto python-docopt python-protobuf python-requests python-six pytsk3; fi
- if test `uname -s` = 'Linux'; then sudo add-apt-repository ppa:gift/dev -y && sudo apt-get update -q && sudo apt-get install libbde-python libewf-python libfsntfs-python libqcow-python libsigscan-python libsmdev-python libsmraw-python libtsk libvhdi-python libvmdk-python libvshadow-python libvslvm-python python-construct python-coverage python-coveralls python-crypto python-docopt python-protobuf python-requests python-six pytsk3; fi
script:
- ./run_tests.py
- ./setup.py build
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ install:
- ps: $Output = Invoke-Expression -Command "& 'C:\\Program Files\\7-Zip\\7z.exe' -y -oC:\\Projects\\ x C:\\Projects\\sqlite-dll-win32-x86-3080803.zip 2>&1"
- cmd: copy C:\Projects\sqlite3.dll C:\Python27\DLLs\
- cmd: git clone https://github.com/log2timeline/l2tdevtools.git && move l2tdevtools ..\
- cmd: mkdir dependencies && set PYTHONPATH=..\l2tdevtools && "%PYTHON%\\python.exe" ..\l2tdevtools\tools\update.py --download-directory dependencies --machine-type x86 --msi-targetdir "%PYTHON%" construct libfsntfs-python libqcow-python libsigscan-python libsmdev-python libsmraw-python libvhdi-python libvmdk-python libvshadow-python protobuf pybde pycrypto pyewf python-gflags pytsk3 six
- cmd: mkdir dependencies && set PYTHONPATH=..\l2tdevtools && "%PYTHON%\\python.exe" ..\l2tdevtools\tools\update.py --download-directory dependencies --machine-type x86 --msi-targetdir "%PYTHON%" construct libfsntfs-python libqcow-python libsigscan-python libsmdev-python libsmraw-python libvhdi-python libvmdk-python libvshadow-python libvslvm-python protobuf pybde pycrypto pyewf python-gflags pytsk3 six

build: off

Expand Down
4 changes: 2 additions & 2 deletions config/dpkg/changelog
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
python-dfvfs (20160201-1) unstable; urgency=low
dfvfs (20160203-1) unstable; urgency=low

* Auto-generated

-- Log2Timeline <[email protected]> Mon, 01 Feb 2016 20:34:54 +0100
-- Log2Timeline <[email protected]> Wed, 03 Feb 2016 21:47:21 +0100
8 changes: 4 additions & 4 deletions config/dpkg/control
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ Maintainer: dfVFS development team <[email protected]>
Build-Depends: debhelper (>= 7), python-all (>= 2.7~), python-setuptools, python3-all (>= 3.2~), python3-setuptools
Standards-Version: 3.9.5
X-Python-Version: >= 2.7
X-Python3-Version: >= 3.2
X-Python-Version: >= 3.2
Homepage: https://github.com/log2timeline/dfvfs/

Package: python-dfvfs
Architecture: all
Depends: libprotobuf7|libprotobuf8, libbde-python, libewf-python, libfsntfs-python, libqcow-python, libsigscan-python, libsmdev-python, libsmraw-python, libvhdi-python, libvmdk-python, libvshadow-python, python-construct, python-pycrypto, python-protobuf, python-six, pytsk3, ${python:Depends}, ${misc:Depends}
Depends: libprotobuf7|libprotobuf8, libbde-python, libewf-python, libfsntfs-python, libqcow-python, libsigscan-python, libsmdev-python, libsmraw-python, libvhdi-python, libvmdk-python, libvshadow-python, libvslvm-python, python-construct, python-pycrypto, python-protobuf, python-six, pytsk3-python, ${python:Depends}, ${misc:Depends}
Description: Digital Forensics Virtual File System (dfVFS).
dfVFS, or Digital Forensics Virtual File System, provides read-only access to
file-system objects from various storage media types and file formats. The goal
Expand All @@ -20,11 +20,11 @@ Description: Digital Forensics Virtual File System (dfVFS).

Package: python3-dfvfs
Architecture: all
Depends: libprotobuf7|libprotobuf8, libbde-python3, libewf-python3, libfsntfs-python3, libqcow-python3, libsigscan-python3, libsmdev-python3, libsmraw-python3, libvhdi-python3, libvmdk-python3, libvshadow-python3, python3-contruct, python3-pycrypto, python3-protobuf, python3-six, pytsk3, ${python:Depends}, ${misc:Depends}
Depends: libprotobuf7|libprotobuf8, libbde-python3, libewf-python3, libfsntfs-python3, libqcow-python3, libsigscan-python3, libsmdev-python3, libsmraw-python3, libvhdi-python3, libvmdk-python3, libvshadow-python3, libvslvm-python3, python3-construct, python3-pycrypto, python3-protobuf, python3-six, pytsk3-python3, ${python3:Depends}, ${misc:Depends}
Description: Digital Forensics Virtual File System (dfVFS).
dfVFS, or Digital Forensics Virtual File System, provides read-only access to
file-system objects from various storage media types and file formats. The goal
of dfVFS is to provide a generic interface for accessing file-system objects,
for which it uses several back-ends that provide the actual implementation of
the various storage media types, volume systems and file systems.

2 changes: 1 addition & 1 deletion dfvfs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-

__version__ = '20160201'
__version__ = '20160203'
1 change: 1 addition & 0 deletions dfvfs/analyzer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dfvfs.analyzer import bzip2_analyzer_helper
from dfvfs.analyzer import ewf_analyzer_helper
from dfvfs.analyzer import gzip_analyzer_helper
from dfvfs.analyzer import lvm_analyzer_helper
from dfvfs.analyzer import ntfs_analyzer_helper
from dfvfs.analyzer import qcow_analyzer_helper
from dfvfs.analyzer import tar_analyzer_helper
Expand Down
33 changes: 33 additions & 0 deletions dfvfs/analyzer/lvm_analyzer_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
"""The Logical Volume Manager (LVM) format analyzer helper implementation."""

from dfvfs.analyzer import analyzer
from dfvfs.analyzer import analyzer_helper
from dfvfs.analyzer import specification
from dfvfs.lib import definitions


class LVMAnalyzerHelper(analyzer_helper.AnalyzerHelper):
"""Class that implements the LVM analyzer helper."""

FORMAT_CATEGORIES = frozenset([
definitions.FORMAT_CATEGORY_VOLUME_SYSTEM])

TYPE_INDICATOR = definitions.TYPE_INDICATOR_LVM

def GetFormatSpecification(self):
"""Retrieves the format specification."""
format_specification = specification.FormatSpecification(
self.type_indicator)

# LVM signature.
format_specification.AddNewSignature(b'LABELONE', offset=0)
format_specification.AddNewSignature(b'LABELONE', offset=512)
format_specification.AddNewSignature(b'LABELONE', offset=1024)
format_specification.AddNewSignature(b'LABELONE', offset=1536)

return format_specification


# Register the analyzer helpers with the analyzer.
analyzer.Analyzer.RegisterHelper(LVMAnalyzerHelper())
1 change: 0 additions & 1 deletion dfvfs/credentials/bde_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ class BDECredentials(credentials.Credentials):
TYPE_INDICATOR = definitions.TYPE_INDICATOR_BDE


# Register the resolver helpers with the resolver.
manager.CredentialsManager.RegisterCredentials(BDECredentials())
1 change: 0 additions & 1 deletion dfvfs/credentials/encrypted_stream_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ class EncryptedStreamCredentials(credentials.Credentials):
TYPE_INDICATOR = definitions.TYPE_INDICATOR_ENCRYPTED_STREAM


# Register the resolver helpers with the resolver.
manager.CredentialsManager.RegisterCredentials(EncryptedStreamCredentials())
3 changes: 2 additions & 1 deletion dfvfs/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
u'pysmraw': 20140612,
u'pyvhdi': 20131210,
u'pyvmdk': 20140421,
u'pyvshadow': 20160110}
u'pyvshadow': 20160110,
u'pyvslvm': 20160109}

# The tuple values are:
# module_name, version_attribute_name, minimum_version, maximum_version
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/compressed_stream_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/data_range_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/encoded_stream_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/encrypted_stream_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/fake_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: The offset to seek.
whence: Optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: The offset to seek.
whence: Optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/file_object_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
130 changes: 130 additions & 0 deletions dfvfs/file_io/lvm_file_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
"""The Logical Volume Manager (LVM) file-like object implementation."""

import os

from dfvfs.file_io import file_io
from dfvfs.lib import errors
from dfvfs.lib import lvm
from dfvfs.resolver import resolver


class LVMFile(file_io.FileIO):
"""Class that implements a file-like object using pyvslvm."""

def __init__(self, resolver_context):
"""Initializes the file-like object.
Args:
resolver_context: the resolver context (instance of Context).
"""
super(LVMFile, self).__init__(resolver_context)
self._file_system = None
self._vslvm_logical_volume = None

def _Close(self):
"""Closes the file-like object.
Raises:
IOError: if the close failed.
"""
self._vslvm_logical_volume = None

self._file_system.Close()
self._file_system = None

def _Open(self, path_spec=None, mode='rb'):
"""Opens the file-like object defined by path specification.
Args:
path_spec: optional path specification (instance of PathSpec).
mode: optional file access mode. The default is 'rb' read-only binary.
Raises:
AccessError: if the access to open the file was denied.
IOError: if the file-like object could not be opened.
PathSpecError: if the path specification is incorrect.
ValueError: if the path specification is invalid.
"""
if not path_spec:
raise ValueError(u'Missing path specfication.')

volume_index = lvm.LVMPathSpecGetVolumeIndex(path_spec)
if volume_index is None:
raise errors.PathSpecError(
u'Unable to retrieve volume index from path specification.')

self._file_system = resolver.Resolver.OpenFileSystem(
path_spec, resolver_context=self._resolver_context)
vslvm_volume_group = self._file_system.GetLVMVolumeGroup()

if (volume_index < 0 or
volume_index >= vslvm_volume_group.number_of_logical_volumes):
raise errors.PathSpecError((
u'Unable to retrieve LVM logical volume index: {0:d} from path '
u'specification.').format(volume_index))

self._vslvm_logical_volume = vslvm_volume_group.get_logical_volume(
volume_index)

# Note: that the following functions do not follow the style guide
# because they are part of the file-like object interface.

def read(self, size=None):
"""Reads a byte string from the file-like object at the current offset.
The function will read a byte string of the specified size or
all of the remaining data if no size was specified.
Args:
size: Optional integer value containing the number of bytes to read.
Default is all remaining data (None).
Returns:
A byte string containing the data read.
Raises:
IOError: if the read failed.
"""
if not self._is_open:
raise IOError(u'Not opened.')

return self._vslvm_logical_volume.read(size)

def seek(self, offset, whence=os.SEEK_SET):
"""Seeks an offset within the file-like object.
Args:
offset: The offset to seek.
whence: Optional value that indicates whether offset is an absolute
or relative position within the file.
Raises:
IOError: if the seek failed.
"""
if not self._is_open:
raise IOError(u'Not opened.')

self._vslvm_logical_volume.seek(offset, whence)

def get_offset(self):
"""Returns the current offset into the file-like object.
Raises:
IOError: if the file-like object has not been opened.
"""
if not self._is_open:
raise IOError(u'Not opened.')

return self._vslvm_logical_volume.get_offset()

def get_size(self):
"""Returns the size of the file-like object.
Raises:
IOError: if the file-like object has not been opened.
"""
if not self._is_open:
raise IOError(u'Not opened.')

return self._vslvm_logical_volume.size
2 changes: 1 addition & 1 deletion dfvfs/file_io/ntfs_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/os_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: The offset to seek.
whence: Optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/sqlite_blob_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: The offset to seek.
whence: Optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/tar_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/tsk_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: The offset to seek.
whence: Optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/vshadow_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: The offset to seek.
whence: Optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 1 addition & 1 deletion dfvfs/file_io/zip_file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def seek(self, offset, whence=os.SEEK_SET):
Args:
offset: the offset to seek.
whence: optional value that indicates whether offset is an absolute
or relative position within the file. Default is SEEK_SET.
or relative position within the file.
Raises:
IOError: if the seek failed.
Expand Down
2 changes: 2 additions & 0 deletions dfvfs/lib/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
TYPE_INDICATOR_EWF = u'EWF'
TYPE_INDICATOR_FAKE = u'FAKE'
TYPE_INDICATOR_GZIP = u'GZIP'
TYPE_INDICATOR_LVM = u'LVM'
TYPE_INDICATOR_MOUNT = u'MOUNT'
TYPE_INDICATOR_NTFS = u'NTFS'
TYPE_INDICATOR_OS = u'OS'
Expand Down Expand Up @@ -53,6 +54,7 @@
TYPE_INDICATOR_VMDK])

VOLUME_SYSTEM_TYPE_INDICATORS = frozenset([
TYPE_INDICATOR_LVM,
TYPE_INDICATOR_TSK_PARTITION,
TYPE_INDICATOR_VSHADOW])

Expand Down
Loading

0 comments on commit 0783a44

Please sign in to comment.