Source code for dfvfs.vfs.file_entry

# -*- coding: utf-8 -*-
"""The Virtual File System (VFS) file entry interface.

The file entry can be various file system elements like a regular file, a
directory or file system metadata.
"""

import abc

from dfvfs.lib import definitions
from dfvfs.resolver import resolver
from dfvfs.vfs import data_stream


[docs] class FileEntry(object): """File entry interface. Attributes: entry_type (str): file entry type, such as device, directory, file, link, socket and pipe or None if not available. The available file entry types are defined in dfvfs.lib.definitions for example FILE_ENTRY_TYPE_FILE. path_spec (PathSpec): path specification. """ # pylint: disable=redundant-returns-doc,redundant-yields-doc
[docs] def __init__( self, resolver_context, file_system, path_spec, is_root=False, is_virtual=False): """Initializes a file entry. Args: resolver_context (Context): resolver context. file_system (FileSystem): file system. path_spec (PathSpec): path specification. is_root (Optional[bool]): True if the file entry is the root file entry of the corresponding file system. is_virtual (Optional[bool]): True if the file entry is a virtual file entry emulated by the corresponding file system. Raises: ValueError: if a derived file entry class does not define a type indicator. """ super(FileEntry, self).__init__() self._attributes = None self._data_streams = None self._directory = None self._file_system = file_system self._is_root = is_root self._is_virtual = is_virtual self._link = None self._resolver_context = resolver_context self.entry_type = None self.path_spec = path_spec if not getattr(self, 'TYPE_INDICATOR', None): raise ValueError('Missing type indicator.')
def _GetAttributes(self): """Retrieves the attributes. Returns: list[Attribute]: attributes. """ if self._attributes is None: self._attributes = [] return self._attributes def _GetDataStreams(self): """Retrieves the data streams. Returns: list[DataStream]: data streams. """ if self._data_streams is None: self._data_streams = [] # It is assumed that non-file file entries do not have data streams. if self.entry_type == definitions.FILE_ENTRY_TYPE_FILE: data_stream_object = data_stream.DataStream(self) self._data_streams.append(data_stream_object) return self._data_streams @abc.abstractmethod def _GetDirectory(self): """Retrieves the directory. Returns: Directory: a directory. """ def _GetLink(self): """Retrieves the link. Returns: str: full path of the linked file entry. """ if self._link is None: self._link = '' return self._link def _GetStatAttribute(self): """Retrieves a stat attribute. Returns: StatAttribute: a stat attribute or None if not available. """ return None @abc.abstractmethod def _GetSubFileEntries(self): """Retrieves sub file entries. Yields: FileEntry: a sub file entry. """ @property def access_time(self): """Retrieves the access time. Returns: dfdatetime.DateTimeValues: access time or None if not available. """ return None @property def added_time(self): """Retrieves the added time. Returns: dfdatetime.DateTimeValues: added time or None if not available. """ return None @property def attributes(self): """Retrieves attributes. Returns: generator[Attribute]: attributes. """ return self._GetAttributes() @property def backup_time(self): """Retrieves the backup time. Returns: dfdatetime.DateTimeValues: backup time or None if not available. """ return None @property def change_time(self): """Retrieves the change time. Returns: dfdatetime.DateTimeValues: change time or None if not available. """ return None @property def creation_time(self): """Retrieves the creation time. Returns: dfdatetime.DateTimeValues: creation time or None if not available. """ return None @property def deletion_time(self): """Retrieves the deletion time. Returns: dfdatetime.DateTimeValues: deletion time or None if not available. """ return None @property def data_streams(self): """Retrieves data streams. Returns: generator[DataStream]: data streams. """ return self._GetDataStreams() @property def link(self): """Retrieves the path of a linked file entry. Returns: str: full path of the linked file entry or None if not available. """ if not self.IsLink(): return None return self._GetLink() @property def modification_time(self): """Retrieves the modification time. Returns: dfdatetime.DateTimeValues: modification time or None if not available. """ return None @property @abc.abstractmethod def name(self): """Retrieves the name. Returns: str: name of the file entry, without the full path. """ @property def number_of_attributes(self): """Retrieves the number of attributes. Returns: int: number of attributes. """ attributes = self._GetAttributes() return len(attributes) @property def number_of_data_streams(self): """Retrieves the number of data streams. Returns: int: number of data streams. """ data_streams = self._GetDataStreams() return len(data_streams) @property def number_of_sub_file_entries(self): """Retrieves the number of sub file entries. Returns: int: number of sub file entries. """ number_of_sub_file_entries = 0 if self.entry_type == definitions.FILE_ENTRY_TYPE_DIRECTORY: directory = self._GetDirectory() # We cannot use len(directory.entries) since entries is a generator. number_of_sub_file_entries = sum(1 for path_spec in directory.entries) return number_of_sub_file_entries @property def size(self): """Retrieves the size. Returns: int: size of the file entry in bytes or None if not available. """ return None @property def sub_file_entries(self): """Retrieves sub file entries. Returns: generator[FileEntry]: sub file entries. """ return self._GetSubFileEntries() @property def type_indicator(self): """Retrieves the type indicator. Returns: str: type indicator. """ return getattr(self, 'TYPE_INDICATOR', None)
[docs] def GetDataStream(self, name, case_sensitive=True): """Retrieves a data stream by name. Args: name (str): name of the data stream. case_sensitive (Optional[bool]): True if the name is case sensitive. Returns: DataStream: a data stream or None if not available. Raises: ValueError: if the name is not string. """ if not isinstance(name, str): raise ValueError('Name is not a string.') name_lower = name.lower() matching_data_stream = None for data_stream_object in self._GetDataStreams(): if data_stream_object.name == name: return data_stream_object if not case_sensitive and data_stream_object.name.lower() == name_lower: if not matching_data_stream: matching_data_stream = data_stream_object return matching_data_stream
[docs] def GetExtents(self): """Retrieves the extents. Returns: list[Extent]: the extents. """ return []
[docs] def GetFileObject(self, data_stream_name=''): """Retrieves a file-like object of a specific data stream. Args: data_stream_name (Optional[str]): name of the data stream, where an empty string represents the default data stream. Returns: FileIO: a file-like object or None if not available. """ if data_stream_name: return None return resolver.Resolver.OpenFileObject( self.path_spec, resolver_context=self._resolver_context)
[docs] def GetFileSystem(self): """Retrieves the file system which contains the file entry. Returns: FileSystem: a file system. """ return self._file_system
[docs] def GetLinkedFileEntry(self): """Retrieves the linked file entry, for example for a symbolic link. Returns: FileEntry: linked file entry or None if not available. """ return None
[docs] def GetParentFileEntry(self): """Retrieves the parent file entry. Returns: FileEntry: parent file entry or None if not available. """ return None
[docs] def GetSubFileEntryByName(self, name, case_sensitive=True): """Retrieves a sub file entry by name. Args: name (str): name of the file entry. case_sensitive (Optional[bool]): True if the name is case sensitive. Returns: FileEntry: a file entry or None if not available. """ name_lower = name.lower() matching_sub_file_entry = None for sub_file_entry in self.sub_file_entries: if sub_file_entry.name == name: return sub_file_entry if not case_sensitive and sub_file_entry.name.lower() == name_lower: if not matching_sub_file_entry: matching_sub_file_entry = sub_file_entry return matching_sub_file_entry
[docs] def GetStatAttribute(self): """Retrieves a stat attribute. Returns: StatAttribute: a stat attribute or None if not available. """ return self._GetStatAttribute()
[docs] def HasDataStream(self, name, case_sensitive=True): """Determines if the file entry has specific data stream. Args: name (str): name of the data stream. case_sensitive (Optional[bool]): True if the name is case sensitive. Returns: bool: True if the file entry has the data stream. Raises: ValueError: if the name is not string. """ if not isinstance(name, str): raise ValueError('Name is not a string.') name_lower = name.lower() for data_stream_object in self._GetDataStreams(): if data_stream_object.name == name: return True if not case_sensitive and data_stream_object.name.lower() == name_lower: return True return False
[docs] def HasExternalData(self): """Determines if the file entry has external stored data. Returns: bool: True if the file entry has external stored data. """ return False
[docs] def IsAllocated(self): """Determines if the file entry is allocated. Returns: bool: True if the file entry is allocated. """ return True
[docs] def IsDevice(self): """Determines if the file entry is a device. Returns: bool: True if the file entry is a device. """ return self.entry_type in ( definitions.FILE_ENTRY_TYPE_BLOCK_DEVICE, definitions.FILE_ENTRY_TYPE_CHARACTER_DEVICE, definitions.FILE_ENTRY_TYPE_DEVICE)
[docs] def IsDirectory(self): """Determines if the file entry is a directory. Returns: bool: True if the file entry is a directory. """ return self.entry_type == definitions.FILE_ENTRY_TYPE_DIRECTORY
[docs] def IsFile(self): """Determines if the file entry is a file. Returns: bool: True if the file entry is a file. """ return self.entry_type == definitions.FILE_ENTRY_TYPE_FILE
[docs] def IsLocked(self): """Determines if the file entry is locked. Returns: bool: True if the file entry is locked. """ return False
[docs] def IsPipe(self): """Determines if the file entry is a pipe. Returns: bool: True if the file entry is a pipe. """ return self.entry_type == definitions.FILE_ENTRY_TYPE_PIPE
[docs] def IsRoot(self): """Determines if the file entry is the root file entry. Returns: bool: True if the file entry is the root file entry. """ return self._is_root
[docs] def IsSocket(self): """Determines if the file entry is a socket. Returns: bool: True if the file entry is a socket. """ return self.entry_type == definitions.FILE_ENTRY_TYPE_SOCKET
[docs] def IsVirtual(self): """Determines if the file entry is virtual (emulated by dfVFS). Returns: bool: True if the file entry is virtual. """ return self._is_virtual
[docs] def Unlock(self): """Unlocks the file entry. Returns: bool: True if the file entry was unlocked. """ return True