Source code for dfvfs.vfs.tsk_attribute

# -*- coding: utf-8 -*-
"""The SleuthKit (TSK) attribute implementation."""

import os

from dfvfs.lib import errors
from dfvfs.vfs import attribute


[docs] class TSKAttribute(attribute.Attribute): """File system attribute that uses pytsk3."""
[docs] def __init__(self, tsk_file, tsk_attribute): """Initializes an attribute. Args: tsk_file (pytsk3.File): TSK file. tsk_attribute (pytsk3.Attribute): TSK attribute. Raises: BackEndError: if the TSK file or attribute is missing. """ if not tsk_file: raise errors.BackEndError('Missing TSK file.') if not tsk_attribute: raise errors.BackEndError('Missing TSK attribute.') super(TSKAttribute, self).__init__() self._attribute_type = getattr(tsk_attribute.info, 'type', None) self._tsk_attribute = tsk_attribute self._tsk_file = tsk_file
@property def attribute_type(self): """object: attribute type.""" return self._attribute_type
[docs] class TSKExtendedAttribute(TSKAttribute): """File system extended attribute that uses pytsk3."""
[docs] def __init__(self, tsk_file, tsk_attribute): """Initializes an attribute. Args: tsk_file (pytsk3.File): TSK file. tsk_attribute (pytsk3.Attribute): TSK attribute. """ super(TSKExtendedAttribute, self).__init__(tsk_file, tsk_attribute) self._current_offset = 0 self._identifier = getattr(tsk_attribute.info, 'id', None) self._size = getattr(tsk_attribute.info, 'size', None)
@property def name(self): """str: name. Raises: BackEndError: if pytsk3 returns a non UTF-8 formatted name. """ name = getattr(self._tsk_attribute.info, 'name', None) if name: try: # pytsk3 returns an UTF-8 encoded byte string. return name.decode('utf8') except UnicodeError: raise errors.BackEndError( 'pytsk3 returned a non UTF-8 formatted name.') return name # Note: that the following functions do not follow the style guide # because they are part of the file-like object interface. # pylint: disable=invalid-name
[docs] def read(self, size=None): """Reads a byte string from the file input/output (IO) object. 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[int]): number of bytes to read, where None is all remaining data. Returns: bytes: data read. Raises: IOError: if the read failed. OSError: if the read failed. """ if size is None: size = self._size data = self._tsk_file.read_random( self._current_offset, size, self._attribute_type, self._identifier) self._current_offset += len(data) return data
[docs] def seek(self, offset, whence=os.SEEK_SET): """Seeks to an offset within the file input/output (IO) object. Args: offset (int): offset to seek. whence (Optional[int]): value that indicates whether offset is an absolute or relative position within the file. Raises: IOError: if the seek failed. OSError: if the seek failed. """ if whence == os.SEEK_CUR: offset += self._current_offset elif whence == os.SEEK_END: offset = self._size - offset elif whence != os.SEEK_SET: raise IOError('Invalid whence') if offset < 0: raise IOError('Invalid offset') self._current_offset = offset
# get_offset() is preferred above tell() by the libbfio layer used in libyal.
[docs] def get_offset(self): """Retrieves the current offset into the file input/output (IO) object. Returns: int: current offset into the file input/output (IO) object. """ return self._current_offset
# Pythonesque alias for get_offset().
[docs] def tell(self): """Retrieves the current offset into the file input/output (IO) object.""" return self.get_offset()
[docs] def get_size(self): """Retrieves the size of the file input/output (IO) object. Returns: int: size of the file input/output (IO) object. """ return self._size
[docs] def seekable(self): """Determines if a file input/output (IO) object is seekable. Returns: bool: True since a file IO object provides a seek method. """ return True