forked from log2timeline/dfvfs
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added fsfat back-end log2timeline#580
- Loading branch information
1 parent
55e01ab
commit 57d3fbf
Showing
18 changed files
with
1,390 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
# -*- coding: utf-8 -*- | ||
"""The Hierarchical File System (FAT) file-like object implementation.""" | ||
|
||
import os | ||
|
||
from dfvfs.file_io import file_io | ||
from dfvfs.resolver import resolver | ||
|
||
|
||
class FATFile(file_io.FileIO): | ||
"""File input/output (IO) object using pyfsfat.file_entry""" | ||
|
||
def __init__(self, resolver_context, path_spec): | ||
"""Initializes a file input/output (IO) object. | ||
Args: | ||
resolver_context (Context): resolver context. | ||
path_spec (PathSpec): a path specification. | ||
""" | ||
super(FATFile, self).__init__(resolver_context, path_spec) | ||
self._file_system = None | ||
self._fsfat_data_stream = None | ||
self._fsfat_file_entry = None | ||
|
||
def _Close(self): | ||
"""Closes the file-like object.""" | ||
self._fsfat_data_stream = None | ||
self._fsfat_file_entry = None | ||
|
||
self._file_system = None | ||
|
||
def _Open(self, mode='rb'): | ||
"""Opens the file-like object defined by path specification. | ||
Args: | ||
mode (Optional[str]): file access mode. | ||
Raises: | ||
AccessError: if the access to open the file was denied. | ||
IOError: if the file-like object could not be opened. | ||
NotSupported: if a data stream, like the resource or named fork, is | ||
requested to be opened. | ||
OSError: if the file-like object could not be opened. | ||
PathSpecError: if the path specification is incorrect. | ||
""" | ||
data_stream_name = getattr(self._path_spec, 'data_stream', None) | ||
|
||
self._file_system = resolver.Resolver.OpenFileSystem( | ||
self._path_spec, resolver_context=self._resolver_context) | ||
|
||
file_entry = self._file_system.GetFileEntryByPathSpec(self._path_spec) | ||
if not file_entry: | ||
raise IOError('Unable to open file entry.') | ||
|
||
fsfat_data_stream = None | ||
fsfat_file_entry = file_entry.GetFATFileEntry() | ||
if not fsfat_file_entry: | ||
raise IOError('Unable to open FAT file entry.') | ||
|
||
if data_stream_name == 'rsrc': | ||
fsfat_data_stream = fsfat_file_entry.get_resource_fork() | ||
elif data_stream_name: | ||
raise IOError('Unable to open data stream: {0:s}.'.format( | ||
data_stream_name)) | ||
|
||
self._fsfat_data_stream = fsfat_data_stream | ||
self._fsfat_file_entry = fsfat_file_entry | ||
|
||
# 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 | ||
|
||
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[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 not self._is_open: | ||
raise IOError('Not opened.') | ||
|
||
if self._fsfat_data_stream: | ||
return self._fsfat_data_stream.read(size=size) | ||
return self._fsfat_file_entry.read(size=size) | ||
|
||
def seek(self, offset, whence=os.SEEK_SET): | ||
"""Seeks to an offset within the file-like object. | ||
Args: | ||
offset (int): offset to seek to. | ||
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 not self._is_open: | ||
raise IOError('Not opened.') | ||
|
||
if self._fsfat_data_stream: | ||
self._fsfat_data_stream.seek(offset, whence) | ||
else: | ||
self._fsfat_file_entry.seek(offset, whence) | ||
|
||
def get_offset(self): | ||
"""Retrieves the current offset into the file-like object. | ||
Return: | ||
int: current offset into the file-like object. | ||
Raises: | ||
IOError: if the file-like object has not been opened. | ||
OSError: if the file-like object has not been opened. | ||
""" | ||
if not self._is_open: | ||
raise IOError('Not opened.') | ||
|
||
if self._fsfat_data_stream: | ||
return self._fsfat_data_stream.get_offset() | ||
return self._fsfat_file_entry.get_offset() | ||
|
||
def get_size(self): | ||
"""Retrieves the size of the file-like object. | ||
Returns: | ||
int: size of the file-like object data. | ||
Raises: | ||
IOError: if the file-like object has not been opened. | ||
OSError: if the file-like object has not been opened. | ||
""" | ||
if not self._is_open: | ||
raise IOError('Not opened.') | ||
|
||
if self._fsfat_data_stream: | ||
return self._fsfat_data_stream.get_size() | ||
return self._fsfat_file_entry.get_size() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# -*- coding: utf-8 -*- | ||
"""The FAT path specification implementation.""" | ||
|
||
from dfvfs.lib import definitions | ||
from dfvfs.path import factory | ||
from dfvfs.path import path_spec | ||
|
||
|
||
class FATPathSpec(path_spec.PathSpec): | ||
"""FAT path specification implementation. | ||
Attributes: | ||
identifier (int): catalog node identifier (CNID). | ||
location (str): location. | ||
""" | ||
|
||
TYPE_INDICATOR = definitions.TYPE_INDICATOR_FAT | ||
|
||
def __init__( | ||
self, identifier=None, location=None, parent=None, **kwargs): | ||
"""Initializes a path specification. | ||
Note that an FAT path specification must have a parent. | ||
Args: | ||
identifier (Optional[int]): catalog node identifier (CNID). | ||
location (Optional[str]): location. | ||
parent (Optional[PathSpec]): parent path specification. | ||
Raises: | ||
ValueError: when parent or both identifier and location are not set. | ||
""" | ||
if (not identifier and not location) or not parent: | ||
raise ValueError('Missing identifier and location, or parent value.') | ||
|
||
super(FATPathSpec, self).__init__(parent=parent, **kwargs) | ||
self.identifier = identifier | ||
self.location = location | ||
|
||
@property | ||
def comparable(self): | ||
"""str: comparable representation of the path specification.""" | ||
string_parts = [] | ||
|
||
if self.identifier is not None: | ||
string_parts.append('identifier: {0:d}'.format(self.identifier)) | ||
if self.location is not None: | ||
string_parts.append('location: {0:s}'.format(self.location)) | ||
|
||
return self._GetComparable(sub_comparable_string=', '.join(string_parts)) | ||
|
||
|
||
factory.Factory.RegisterPathSpec(FATPathSpec) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# -*- coding: utf-8 -*- | ||
"""The FAT path specification resolver helper implementation.""" | ||
|
||
from dfvfs.file_io import fat_file_io | ||
from dfvfs.lib import definitions | ||
from dfvfs.resolver_helpers import manager | ||
from dfvfs.resolver_helpers import resolver_helper | ||
from dfvfs.vfs import fat_file_system | ||
|
||
|
||
class FATResolverHelper(resolver_helper.ResolverHelper): | ||
"""FAT resolver helper.""" | ||
|
||
TYPE_INDICATOR = definitions.TYPE_INDICATOR_FAT | ||
|
||
def NewFileObject(self, resolver_context, path_spec): | ||
"""Creates a new file input/output (IO) object. | ||
Args: | ||
resolver_context (Context): resolver context. | ||
path_spec (PathSpec): a path specification. | ||
Returns: | ||
FileIO: file input/output (IO) object. | ||
""" | ||
return fat_file_io.FATFile(resolver_context, path_spec) | ||
|
||
def NewFileSystem(self, resolver_context, path_spec): | ||
"""Creates a new file system object. | ||
Args: | ||
resolver_context (Context): resolver context. | ||
path_spec (PathSpec): a path specification. | ||
Returns: | ||
FileSystem: file system. | ||
""" | ||
return fat_file_system.FATFileSystem(resolver_context, path_spec) | ||
|
||
|
||
manager.ResolverHelperManager.RegisterHelper(FATResolverHelper()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# -*- coding: utf-8 -*- | ||
"""The FAT directory implementation.""" | ||
|
||
from dfvfs.path import fat_path_spec | ||
from dfvfs.vfs import directory | ||
|
||
|
||
class FATDirectory(directory.Directory): | ||
"""File system directory that uses pyfsfat.""" | ||
|
||
def __init__(self, file_system, path_spec, fsfat_file_entry): | ||
"""Initializes a directory. | ||
Args: | ||
file_system (FileSystem): file system. | ||
path_spec (PathSpec): path specification. | ||
fsfat_file_entry (pyfsfat.file_entry): FAT file entry. | ||
""" | ||
super(FATDirectory, self).__init__(file_system, path_spec) | ||
self._fsfat_file_entry = fsfat_file_entry | ||
|
||
def _EntriesGenerator(self): | ||
"""Retrieves directory entries. | ||
Since a directory can contain a vast number of entries using | ||
a generator is more memory efficient. | ||
Yields: | ||
FATPathSpec: FAT path specification. | ||
""" | ||
location = getattr(self.path_spec, 'location', None) | ||
|
||
for fsfat_sub_file_entry in self._fsfat_file_entry.sub_file_entries: | ||
directory_entry = fsfat_sub_file_entry.name | ||
|
||
if not location or location == self._file_system.PATH_SEPARATOR: | ||
directory_entry = self._file_system.JoinPath([directory_entry]) | ||
else: | ||
directory_entry = self._file_system.JoinPath([ | ||
location, directory_entry]) | ||
|
||
yield fat_path_spec.FATPathSpec( | ||
identifier=fsfat_sub_file_entry.identifier, location=directory_entry, | ||
parent=self.path_spec.parent) |
Oops, something went wrong.