class FSTimeline:
    def __init__(self, disk):
        self._disk = disk
        self._filesystem = None
        self._filetype_cache = {}
        self._checksum_cache = {}
        self.logger = logging.getLogger(
            "%s.%s" % (self.__module__, self.__class__.__name__))

    def __enter__(self):
        self._filesystem = FileSystem(self._disk)
        self._filesystem.mount()

        return self

    def __exit__(self, *_):
        self._filesystem.umount()

    def __getattr__(self, attr):
        return getattr(self._filesystem, attr)

    def timeline(self):
        self.logger.debug("Extracting File System timeline events.")
        events = tuple(
            Event(d.inode, d.path, d.size, d.allocated, t, r)
            for d in self._visit_filesystem()
            for t, r in ((d.atime, 'access'), (d.mtime, 'change'),
                         (d.ctime, 'attribute_change'), (d.crtime, 'creation'))
            if t > 0)

        self.logger.debug("Sorting File System timeline events.")
        return sorted(events, key=lambda e: e.timestamp)

    @lru_cache(maxsize=None)
    def file(self, path):
        """Identifies the file type.

        Caches the result to reduce overhead on duplicated events.

        """
        return self._filesystem.file(path)

    @lru_cache(maxsize=None)
    def checksum(self, path):
        """Identifies the file type.

        Caches the result to reduce overhead on duplicated events.

        """
        return self._filesystem.checksum(path)

    def _visit_filesystem(self):
        """Walks through the filesystem content."""
        self.logger.debug("Parsing File System content.")

        root_partition = self._filesystem.inspect_get_roots()[0]

        yield from self._root_dirent()

        for entry in self._filesystem.filesystem_walk(root_partition):
            yield Dirent(
                entry['tsk_inode'],
                self._filesystem.path('/' + entry['tsk_name']),
                entry['tsk_size'], entry['tsk_type'],
                True if entry['tsk_flags'] & TSK_ALLOC else False,
                timestamp(entry['tsk_atime_sec'], entry['tsk_atime_nsec']),
                timestamp(entry['tsk_mtime_sec'], entry['tsk_mtime_nsec']),
                timestamp(entry['tsk_ctime_sec'], entry['tsk_ctime_nsec']),
                timestamp(entry['tsk_crtime_sec'], entry['tsk_crtime_nsec']))

    def _root_dirent(self):
        """Returns the root folder dirent as filesystem_walk API doesn't."""
        fstat = self._filesystem.stat('/')

        yield Dirent(fstat['ino'], self._filesystem.path('/'), fstat['size'],
                     'd', True, timestamp(fstat['atime'], 0),
                     timestamp(fstat['mtime'],
                               0), timestamp(fstat['ctime'], 0), 0)
Beispiel #2
0
class FSTimeline:
    def __init__(self, disk):
        self._disk = disk
        self._filesystem = None
        self._filetype_cache = {}
        self._checksum_cache = {}
        self.logger = logging.getLogger(
            "%s.%s" % (self.__module__, self.__class__.__name__))

    def __enter__(self):
        self._filesystem = FileSystem(self._disk)
        self._filesystem.mount()

        return self

    def __exit__(self, *_):
        self._filesystem.umount()

    def __getattr__(self, attr):
        return getattr(self._filesystem, attr)

    def timeline(self):
        self.logger.debug("Extracting File System timeline events.")
        events = tuple(Event(d.inode, d.path, d.size, d.allocated, t, r)
                       for d in self._visit_filesystem()
                       for t, r in ((d.atime, 'access'),
                                    (d.mtime, 'change'),
                                    (d.ctime, 'attribute_change'),
                                    (d.crtime, 'creation'))
                       if t > 0)

        self.logger.debug("Sorting File System timeline events.")
        return sorted(events, key=lambda e: e.timestamp)

    @lru_cache(maxsize=None)
    def file(self, path):
        """Identifies the file type.

        Caches the result to reduce overhead on duplicated events.

        """
        return self._filesystem.file(path)

    @lru_cache(maxsize=None)
    def checksum(self, path):
        """Identifies the file type.

        Caches the result to reduce overhead on duplicated events.

        """
        return self._filesystem.checksum(path)

    def _visit_filesystem(self):
        """Walks through the filesystem content."""
        self.logger.debug("Parsing File System content.")

        root_partition = self._filesystem.inspect_get_roots()[0]

        yield from self._root_dirent()

        for entry in self._filesystem.filesystem_walk(root_partition):
            yield Dirent(
                entry['tsk_inode'],
                self._filesystem.path('/' + entry['tsk_name']),
                entry['tsk_size'], entry['tsk_type'],
                True if entry['tsk_flags'] & TSK_ALLOC else False,
                timestamp(entry['tsk_atime_sec'], entry['tsk_atime_nsec']),
                timestamp(entry['tsk_mtime_sec'], entry['tsk_mtime_nsec']),
                timestamp(entry['tsk_ctime_sec'], entry['tsk_ctime_nsec']),
                timestamp(entry['tsk_crtime_sec'], entry['tsk_crtime_nsec']))

    def _root_dirent(self):
        """Returns the root folder dirent as filesystem_walk API doesn't."""
        fstat = self._filesystem.stat('/')

        yield Dirent(fstat['ino'], self._filesystem.path('/'),
                     fstat['size'], 'd', True,
                     timestamp(fstat['atime'], 0),
                     timestamp(fstat['mtime'], 0),
                     timestamp(fstat['ctime'], 0),
                     0)