Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify __type__ on filesystems and containers #444

Merged
merged 5 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion dissect/target/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,22 @@ class Container(io.IOBase):
vs: An optional shorthand to set the underlying volume system, usually set later.
"""

# Due to lazy importing we generally can't use isinstance(), so we add a short identifying string to each class
# This has the added benefit of having a readily available "pretty name" for each implementation
__type__: str = None
"""A short string identifying the type of container."""

def __init__(self, fh: Union[BinaryIO, Path], size: int, vs: VolumeSystem = None):
self.fh = fh
self.size = size

# Shorthand access to vs
self.vs = vs

def __repr__(self):
if self.__type__ is None:
raise NotImplementedError(f"{self.__class__.__name__} must define __type__")

def __repr__(self) -> str:
return f"<{self.__class__.__name__} size={self.size} vs={self.vs}>"

@classmethod
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/asdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@


class AsdfContainer(Container):
__type__ = "asdf"

def __init__(self, fh: BinaryIO, *args, **kwargs):
file_container = fh

Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/ewf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
class EwfContainer(Container):
"""Expert Witness Disk Image Format"""

__type__ = "ewf"

def __init__(self, fh: Union[list, BinaryIO, Path], *args, **kwargs):
fhs = [fh] if not isinstance(fh, list) else fh
if hasattr(fhs[0], "read"):
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/hdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@


class HddContainer(Container):
__type__ = "hdd"

def __init__(self, fh: Path, *args, **kwargs):
if hasattr(fh, "read"):
raise TypeError("HddContainer can only be opened by path")
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/hds.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@


class HdsContainer(Container):
__type__ = "hds"

def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
f = fh
if not hasattr(fh, "read"):
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/qcow2.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@


class QCow2Container(Container):
__type__ = "qcow2"

def __init__(self, fh: Union[BinaryIO, Path], data_file=None, backing_file=None, *args, **kwargs):
f = fh
if not hasattr(fh, "read"):
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@


class RawContainer(Container):
__type__ = "raw"

def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
if not hasattr(fh, "read"):
fh = fh.open("rb")
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/split.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def find_files(path: Path) -> List[Path]:


class SplitContainer(Container):
__type__ = "split"

def __init__(self, fh: Union[list, BinaryIO, Path], *args, **kwargs):
self._fhs = []
self.offsets = [0]
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/vdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
class VdiContainer(Container):
"""VirtualBox hard disks"""

__type__ = "vdi"

def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
f = fh
if not hasattr(fh, "read"):
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/vhd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@


class VhdContainer(Container):
__type__ = "vhd"

def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
f = fh
if not hasattr(fh, "read"):
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/vhdx.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@


class VhdxContainer(Container):
__type__ = "vhdx"

def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
self.vhdx = vhdx.VHDX(fh)
super().__init__(fh, self.vhdx.size, *args, **kwargs)
Expand Down
2 changes: 2 additions & 0 deletions dissect/target/containers/vmdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
class VmdkContainer(Container):
"""VMWare hard disks"""

__type__ = "vmdk"

def __init__(self, fh: Union[BinaryIO, Path], *args, **kwargs):
self.vmdk = vmdk.VMDK(fh)
super().__init__(fh, self.vmdk.size, *args, **kwargs)
Expand Down
29 changes: 21 additions & 8 deletions dissect/target/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
import os
import stat
import warnings
from collections import defaultdict
from typing import (
TYPE_CHECKING,
Expand Down Expand Up @@ -40,8 +41,10 @@
class Filesystem:
"""Base class for filesystems."""

__fstype__: str = None
"""Defines the type of filesystem it is."""
# Due to lazy importing we generally can't use isinstance(), so we add a short identifying string to each class
# This has the added benefit of having a readily available "pretty name" for each implementation
__type__: str = None
"""A short string identifying the type of filesystem."""

def __init__(
self,
Expand All @@ -57,17 +60,27 @@ def __init__(
alt_separator: The alternative separator used to distingish between directories in a path.

Raises:
NotImplementedError: When the internal ``__fstype__`` of the class is not defined.
NotImplementedError: When the internal ``__type__`` of the class is not defined.
"""
self.volume = volume
self.case_sensitive = case_sensitive
self.alt_separator = alt_separator
if self.__fstype__ is None:
raise NotImplementedError(f"{self.__class__.__name__} must define __fstype__")

if self.__type__ is None:
raise NotImplementedError(f"{self.__class__.__name__} must define __type__")

def __repr__(self) -> str:
return f"<{self.__class__.__name__}>"

@classmethod
@property
def __fstype__(cls) -> str:
warnings.warn(
"The __fstype__ attribute is deprecated and will be removed in dissect.target 3.15. Use __type__ instead",
category=DeprecationWarning,
)
return cls.__type__

def path(self, *args) -> fsutil.TargetPath:
"""Get a specific path from the filesystem."""
return fsutil.TargetPath(self, *args)
Expand All @@ -91,7 +104,7 @@ def detect(cls, fh: BinaryIO) -> bool:
except NotImplementedError:
raise
except Exception as e:
log.warning("Failed to detect %s filesystem", cls.__fstype__)
log.warning("Failed to detect %s filesystem", cls.__type__)
log.debug("", exc_info=e)
finally:
fh.seek(offset)
Expand Down Expand Up @@ -1028,7 +1041,7 @@ def readlink(self) -> str:


class VirtualFilesystem(Filesystem):
__fstype__ = "virtual"
__type__ = "virtual"

def __init__(self, **kwargs):
super().__init__(None, **kwargs)
Expand Down Expand Up @@ -1184,7 +1197,7 @@ def symlink(self, src: str, dst: str) -> None:


class RootFilesystem(Filesystem):
__fstype__ = "root"
__type__ = "root"

def __init__(self, target: Target):
self.target = target
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/ad1.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


class AD1Filesystem(Filesystem):
__fstype__ = "ad1"
__type__ = "ad1"

def __init__(self, fh, *args, **kwargs):
super().__init__(fh, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/cb.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class OS(IntEnum):


class CbFilesystem(Filesystem):
__fstype__ = "cb"
__type__ = "cb"

def __init__(self, session: LiveResponseSession, prefix: str, *args, **kwargs):
self.session = session
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


class ConfigurationFilesystem(VirtualFilesystem):
__fstype__: str = "META:configuration"
__type__: str = "META:configuration"

def __init__(self, target: Target, path: str, **kwargs):
super().__init__(**kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/dir.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


class DirectoryFilesystem(Filesystem):
__fstype__ = "dir"
__type__ = "dir"

def __init__(self, path: Path, *args, **kwargs):
super().__init__(None, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/exfat.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


class ExfatFilesystem(Filesystem):
__fstype__ = "exfat"
__type__ = "exfat"

def __init__(self, fh: BinaryIO, *args, **kwargs):
super().__init__(fh, case_sensitive=False, alt_separator="\\", *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/extfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


class ExtFilesystem(Filesystem):
__fstype__ = "ext"
__type__ = "ext"

def __init__(self, fh: BinaryIO, *args, **kwargs):
super().__init__(fh, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/fat.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


class FatFilesystem(Filesystem):
__fstype__ = "fat"
__type__ = "fat"

def __init__(self, fh: BinaryIO, *args, **kwargs):
super().__init__(fh, case_sensitive=False, alt_separator="\\", *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/ffs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


class FfsFilesystem(Filesystem):
__fstype__ = "ffs"
__type__ = "ffs"

def __init__(self, fh: BinaryIO, *args, **kwargs):
super().__init__(fh, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/itunes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
class ITunesFilesystem(Filesystem):
"""Filesystem implementation for iTunes backups."""

__fstype__ = "itunes"
__type__ = "itunes"

def __init__(self, backup: ITunesBackup, *args, **kwargs):
super().__init__(None, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/ntfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


class NtfsFilesystem(Filesystem):
__fstype__ = "ntfs"
__type__ = "ntfs"

def __init__(
self,
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
class SmbFilesystem(Filesystem):
"""Filesystem implementation for SMB."""

__fstype__ = "smb"
__type__ = "smb"

def __init__(self, conn: SMBConnection, share_name: str, *args, **kwargs):
super().__init__(None, *args, **kwargs, alt_separator="\\", case_sensitive=False)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/squashfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


class SquashFSFilesystem(Filesystem):
__fstype__ = "squashfs"
__type__ = "squashfs"

def __init__(self, fh: BinaryIO, *args, **kwargs):
super().__init__(fh, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/tar.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
class TarFilesystem(Filesystem):
"""Filesystem implementation for tar files."""

__fstype__ = "tar"
__type__ = "tar"

def __init__(
self,
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/vmfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


class VmfsFilesystem(Filesystem):
__fstype__ = "vmfs"
__type__ = "vmfs"

def __init__(self, fh: BinaryIO, *args, **kwargs):
super().__init__(fh, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/xfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


class XfsFilesystem(Filesystem):
__fstype__ = "xfs"
__type__ = "xfs"

def __init__(self, fh: BinaryIO, *args, **kwargs):
super().__init__(fh, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion dissect/target/filesystems/zip.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ZipFilesystem(Filesystem):
See https://github.com/python/cpython/issues/82102 for more information.
"""

__fstype__ = "zip"
__type__ = "zip"

def __init__(
self,
Expand Down
10 changes: 5 additions & 5 deletions dissect/target/plugins/filesystem/icat.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ICatPlugin(Plugin):

def check_compatible(self) -> None:
filesystems = self.target.filesystems
if not any(fs.__fstype__ in self.FS_SUPPORTED for fs in filesystems):
if not any(fs.__type__ in self.FS_SUPPORTED for fs in filesystems):
raise UnsupportedPluginError("No supported filesystems found")

@arg("--segment", "--inode", "-i", dest="inum", required=True, type=int, help="MFT segment or inode number")
Expand Down Expand Up @@ -72,14 +72,14 @@ def icat(self, inum, fs, ads):
)
return

if filesystem.__fstype__ == "ntfs" or open_as == "ntfs":
if filesystem.__type__ == "ntfs" or open_as == "ntfs":
fh = filesystem.ntfs.mft(inum).open(ads)
elif filesystem.__fstype__ == "ext":
elif filesystem.__type__ == "ext":
fh = filesystem.extfs.get_inode(inum).open()
elif filesystem.__fstype__ == "xfs":
elif filesystem.__type__ == "xfs":
fh = filesystem.xfs.get_inode(inum).open()
else:
self.target.log.exception('Unsupported FS type "%s"', filesystem.__fstype__)
self.target.log.exception('Unsupported FS type "%s"', filesystem.__type__)
return

shutil.copyfileobj(fh, sys.stdout.buffer)
Expand Down
4 changes: 2 additions & 2 deletions dissect/target/plugins/filesystem/ntfs/mft.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@

class MftPlugin(Plugin):
def check_compatible(self) -> None:
ntfs_filesystems = [fs for fs in self.target.filesystems if fs.__fstype__ == "ntfs"]
ntfs_filesystems = [fs for fs in self.target.filesystems if fs.__type__ == "ntfs"]
if not len(ntfs_filesystems):
raise UnsupportedPluginError("No NTFS filesystems found")

Expand Down Expand Up @@ -133,7 +133,7 @@ def mft(self, compact: bool = False):
record_formatter = formatter

for fs in self.target.filesystems:
if fs.__fstype__ != "ntfs":
if fs.__type__ != "ntfs":
continue

drive_letter = get_drive_letter(self.target, fs)
Expand Down
Loading