-
Notifications
You must be signed in to change notification settings - Fork 75
Add support for --direct access for cim plugins #1437
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
Open
william-billaud
wants to merge
40
commits into
fox-it:main
Choose a base branch
from
william-billaud:cim_add_direct_support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
b5bcc7c
Add support for --direct access for cim plugins
william-billaud df955f1
Merge branch 'main' into cim_add_direct_support
william-billaud c36698b
Merge branch 'main' into cim_add_direct_support
william-billaud f183164
Merge branch 'main' into cim_add_direct_support
william-billaud 340ce17
Merge branch 'main' into cim_add_direct_support
william-billaud 1000f34
Merge branch 'main' into cim_add_direct_support
william-billaud db71419
Use case insentive vfs by default on direct mode.
william-billaud 28b5a4a
Fix test python < 3.12
william-billaud 5ea70ae
Merge branch 'main' into cim_add_direct_support
william-billaud 1afdbb9
Fix tests on case insensitive fs
william-billaud 25b8d17
Revert static version
william-billaud 4d60ab1
Use VirtualFilesystem (currently causing a deadlock)
william-billaud 6bc3c16
Merge branch 'main' into cim_add_direct_support
william-billaud 715c249
Fix direct loader vfs conversion to str, causing errors in tests
william-billaud 1e6a00d
Merge branch 'main' into cim_add_direct_support
william-billaud 6b076a4
Merge branch 'main' into cim_add_direct_support
william-billaud 5bc1b42
Revert tox ini change
william-billaud 076f512
Delete no longer used variable
william-billaud 21a6aee
Merge branch 'main' into cim_add_direct_support
william-billaud 4ed0bcd
Apply suggestion
william-billaud 867dbc0
Update tests/loaders/test_direct.py
william-billaud 8140f64
Add specific function to enumerate file for windows before 3.12
william-billaud 88cfc2f
Ruff
william-billaud 10f348b
Ruff
william-billaud 9f2a012
typo
william-billaud 880e20d
Add comment
william-billaud 4710aba
Merge branch 'main' into cim_add_direct_support
william-billaud 808e028
Merge branch 'main' into cim_add_direct_support
twiggler f1e01c4
Fix for python < 3.12 on windows
william-billaud 310632a
Lint
william-billaud 48719bd
Merge branch 'main' into cim_add_direct_support
william-billaud f413c9a
Update dissect/target/loaders/direct.py
william-billaud 8b2fd4a
Update dissect/target/loaders/direct.py
william-billaud f2d7ab1
Update dissect/target/tools/query.py
william-billaud 0a1efce
Update tests/tools/test_query.py
william-billaud 5815c12
Update dissect/target/target.py
william-billaud c674034
Move __repr__
william-billaud c6033b7
Fix docstyle
william-billaud 745e5d9
Fix open_direct call
william-billaud e9386bd
Merge branch 'main' into cim_add_direct_support
william-billaud File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 |
|---|---|---|
| @@ -1,31 +1,93 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import sys | ||
| from itertools import chain | ||
| from pathlib import Path | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| from dissect.target.filesystem import VirtualFilesystem | ||
| from dissect.target.helpers.logging import get_logger | ||
| from dissect.target.loader import Loader | ||
| from dissect.target.plugins.os.default._os import DefaultOSPlugin | ||
|
|
||
| if TYPE_CHECKING: | ||
| from collections.abc import Iterator | ||
|
|
||
| from dissect.target.target import Target | ||
|
|
||
| log = get_logger(__name__) | ||
|
|
||
|
|
||
| class DirectLoader(Loader): | ||
| def __init__(self, paths: list[str | Path]): | ||
| def __init__(self, paths: list[str | Path], case_sensitive: bool = False): | ||
| self.case_sensitive = case_sensitive | ||
| self.paths = [(Path(path) if not isinstance(path, Path) else path).resolve() for path in paths] | ||
|
|
||
| def __repr__(self) -> str: | ||
| """ | ||
| As DirectLoader does not call super().__init__() self.path is not defined, we need to redefine the __repr__ func | ||
| :return: | ||
| """ | ||
| return f"{self.__class__.__name__}({str(self.paths)!r})" | ||
|
|
||
| @staticmethod | ||
| def detect(path: Path) -> bool: | ||
| return False | ||
|
|
||
| def map(self, target: Target) -> None: | ||
| vfs = VirtualFilesystem() | ||
| if not self.case_sensitive and self.check_case_insensitive_overlap(): | ||
| log.warning( | ||
| "Direct mode used in case insensitive mode, but this will cause files overlap, " | ||
| "consider using --direct-sensitive" | ||
| ) | ||
| vfs = VirtualFilesystem(case_sensitive=self.case_sensitive) | ||
| for path in self.paths: | ||
| if path.is_file(): | ||
| vfs.map_file(str(path), str(path)) | ||
| vfs.map_file(str(path), path) | ||
| elif path.is_dir(): | ||
| vfs.map_dir(str(path), str(path)) | ||
| vfs.map_dir(str(path), path) | ||
|
|
||
| target.filesystems.add(vfs) | ||
| target._os_plugin = DefaultOSPlugin | ||
|
|
||
| def check_case_insensitive_overlap(self) -> bool: | ||
| """Verify if two differents files will have the same path in a case-insensitive scenario.""" | ||
| if sys.version_info >= (3, 12) or sys.platform != "win32": | ||
|
|
||
| def get_files(path: Path) -> Iterator[Path]: | ||
| """Return list of all files recursively.""" | ||
| if not path.exists(): | ||
| return | ||
| if path.is_file(): | ||
| yield path | ||
| # Recursively find all files in the directory | ||
| yield from path.rglob("*") | ||
| else: | ||
|
|
||
| def get_files(path: Path, max_depth: int = 7) -> Iterator[Path]: | ||
| """ | ||
william-billaud marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| rglob seems to have issue on windows with python <3.12 when working on a case sensitive FS. Thus | ||
| we use another implementation without using rglob. | ||
| Probably related to https://github.com/python/cpython/issues/94537 | ||
| """ | ||
|
|
||
| if max_depth == 0: | ||
| return | ||
| if not path.exists(): | ||
| return | ||
| if path.is_dir(): | ||
| for f in path.iterdir(): | ||
| if f.is_dir(): | ||
| yield from get_files(f, max_depth=max_depth - 1) | ||
| else: | ||
| yield f | ||
| elif path.is_file(): | ||
| yield path | ||
|
|
||
| # Create a flat list of all file paths from all input directories | ||
| all_paths = chain.from_iterable(get_files(p) for p in self.paths) | ||
| # Filter out directories, keeping only files | ||
| all_files = [p for p in all_paths if p.is_file()] | ||
| # Compare the count of all files with the count of unique, lowercased file paths | ||
|
|
||
| return len({str(p).lower() for p in all_files}) != len(all_files) | ||
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,43 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import io | ||
william-billaud marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import logging | ||
| import typing | ||
|
|
||
| from dissect.target import Target | ||
| from dissect.target.filesystem import VirtualFilesystem | ||
|
|
||
| if typing.TYPE_CHECKING: | ||
| from pathlib import Path | ||
|
|
||
| import pytest | ||
|
|
||
|
|
||
| def test_direct_overlap_warning( | ||
| tmp_path: Path, caplog: pytest.LogCaptureFixture, monkeypatch: pytest.MonkeyPatch | ||
| ) -> None: | ||
| """Assert direct raise warning in case sensitive mode if some files overlap | ||
william-billaud marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| We must uncompress files in a temporary directory as having two files with same name | ||
| would cause issue with git on case insensitive fs. | ||
| """ | ||
| source_vfs = VirtualFilesystem(case_sensitive=True) | ||
| source_vfs.map_file_fh("file.txt", io.BytesIO(b"a")) | ||
| source_vfs.map_file_fh("File.txt", io.BytesIO(b"b")) | ||
| with caplog.at_level(logging.WARNING): | ||
| _ = Target.open_direct([source_vfs.path("/")], case_sensitive=True) | ||
| assert ( | ||
| "Direct mode used in case insensitive mode, but this will cause files overlap, " | ||
| "consider using --direct-sensitive" not in caplog.text | ||
| ) | ||
| with caplog.at_level(logging.WARNING): | ||
| _ = Target.open_direct([source_vfs.path("/")], case_sensitive=False) | ||
| assert ( | ||
| "Direct mode used in case insensitive mode, but this will cause files overlap, " | ||
| "consider using --direct-sensitive" in caplog.text | ||
| ) | ||
| with caplog.at_level(logging.WARNING): | ||
| _ = Target.open_direct([source_vfs.path("/file.txt"), source_vfs.path("/File.txt")], case_sensitive=False) | ||
| assert ( | ||
| "Direct mode used in case insensitive mode, but this will cause files overlap, " | ||
| "consider using --direct-sensitive" in caplog.text | ||
| ) | ||
This file contains hidden or 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 hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@twiggler regarding
As the path variable (that containes the VFS) was converted to string, the vfs object was lost and vfs.map_file tried to map the string '/' (thus my root fs)