@@ -269,7 +269,7 @@ def name(self) -> str:
269269 return target_name
270270
271271 @classmethod
272- def open (cls , path : str | Path ) -> Self :
272+ def open (cls , path : str | Path , * , apply : bool = True ) -> Self :
273273 """Try to find a suitable loader for the given path and load a ``Target`` from it.
274274
275275 Args:
@@ -307,20 +307,22 @@ def open(cls, path: str | Path) -> Self:
307307 except Exception as e :
308308 raise TargetError (f"Failed to initiate { loader_cls .__name__ } for target { spec } : { e } " ) from e
309309
310- return cls ._load (spec , loader_instance )
310+ return cls ._load (spec , loader_instance , apply = apply )
311311
312312 @classmethod
313- def open_raw (cls , path : str | Path ) -> Self :
313+ def open_raw (cls , path : str | Path , * , apply : bool = True ) -> Self :
314314 """Open a Target with the given path using the :class:`~dissect.target.loaders.raw.RawLoader`.
315315
316316 Args:
317317 path: Path to load the ``Target`` from.
318318 """
319319 adjusted_path = Path (path ) if not isinstance (path , os .PathLike ) else path
320- return cls ._load (path , loader .RawLoader (adjusted_path ))
320+ return cls ._load (path , loader .RawLoader (adjusted_path ), apply = apply )
321321
322322 @classmethod
323- def open_all (cls , paths : str | Path | list [str | Path ], include_children : bool = False ) -> Iterator [Self ]:
323+ def open_all (
324+ cls , paths : str | Path | list [str | Path ], include_children : bool = False , * , apply : bool = True
325+ ) -> Iterator [Self ]:
324326 """Yield all targets from one or more paths or directories.
325327
326328 If the path is a directory, iterate files one directory deep.
@@ -336,7 +338,7 @@ def open_all(cls, paths: str | Path | list[str | Path], include_children: bool =
336338 TargetError: Raised when not a single ``Target`` can be loaded.
337339 """
338340
339- def _open_all (spec : str | Path , include_children : bool = False ) -> Iterator [Target ]:
341+ def _open_all (spec : str | Path , include_children : bool = False , * , apply : bool = True ) -> Iterator [Target ]:
340342 # If the path is a URI-like string, separate the path component
341343 adjusted_path , parsed_path = parse_path_uri (spec )
342344 # We always need a path to work with, so convert the spec into one if it's not one already
@@ -390,7 +392,9 @@ def _open_all(spec: str | Path, include_children: bool = False) -> Iterator[Targ
390392 # load_spec is the original "spec"
391393 # For URI-like paths it's the full original URI
392394 # For file/dir-like paths it's a Path object
393- target = cls ._load (load_spec , ldr )
395+ # If include_children is True, we override the apply parameter so we can find child targets
396+ # The apply parameter will then be used on the children
397+ target = cls ._load (load_spec , ldr , apply = include_children or apply )
394398 except Exception as e :
395399 get_target_logger (load_spec ).error ("Failed to load target with loader %s" , ldr )
396400 get_target_logger (load_spec ).debug ("" , exc_info = e )
@@ -400,7 +404,7 @@ def _open_all(spec: str | Path, include_children: bool = False) -> Iterator[Targ
400404
401405 if include_children :
402406 try :
403- yield from target .open_children ()
407+ yield from target .open_children (apply = apply )
404408 except Exception as e :
405409 get_target_logger (load_spec ).error ("Failed to load child target from %s" , target , exc_info = e )
406410
@@ -413,7 +417,7 @@ def _open_all(spec: str | Path, include_children: bool = False) -> Iterator[Targ
413417 for spec in paths :
414418 loaded = False
415419
416- for target in _open_all (spec , include_children = include_children ):
420+ for target in _open_all (spec , include_children = include_children , apply = apply ):
417421 loaded = True
418422 at_least_one_loaded = True
419423 yield target
@@ -434,7 +438,7 @@ def _open_all(spec: str | Path, include_children: bool = False) -> Iterator[Targ
434438
435439 if path .is_dir ():
436440 for entry in path .iterdir ():
437- for target in _open_all (entry , include_children = include_children ):
441+ for target in _open_all (entry , include_children = include_children , apply = apply ):
438442 at_least_one_loaded = True
439443 yield target
440444
@@ -492,7 +496,7 @@ def _load_child_plugins(self) -> None:
492496 )
493497 self .log .debug ("" , exc_info = e )
494498
495- def open_child (self , child : int | str | Path ) -> Target :
499+ def open_child (self , child : int | str | Path , * , apply : bool = True ) -> Target :
496500 """Open a child target.
497501
498502 Allows opening a nested child target by path, index or child pattern.
@@ -516,7 +520,7 @@ def open_child(self, child: int | str | Path) -> Target:
516520 for child_idx in map (int , str (child ).split ("." )):
517521 for _ , child in current_target .list_children ():
518522 if child_idx == 0 :
519- current_target = Target .open (current_target .fs .path (child .path ))
523+ current_target = Target .open (current_target .fs .path (child .path ), apply = apply )
520524 break
521525 child_idx -= 1
522526 else :
@@ -525,9 +529,9 @@ def open_child(self, child: int | str | Path) -> Target:
525529 return current_target
526530
527531 # Open child by path
528- return Target .open (self .fs .path (child ))
532+ return Target .open (self .fs .path (child ), apply = apply )
529533
530- def open_children (self , recursive : bool = False ) -> Iterator [Target ]:
534+ def open_children (self , recursive : bool = False , * , apply : bool = True ) -> Iterator [Target ]:
531535 """Open all the child targets on a ``Target``.
532536
533537 Will open all discovered child targets if the current ``Target`` has them, such as VMs on a hypervisor.
@@ -540,15 +544,15 @@ def open_children(self, recursive: bool = False) -> Iterator[Target]:
540544 """
541545 for _ , child in self .list_children ():
542546 try :
543- target = self .open_child (child .path )
547+ target = self .open_child (child .path , apply = apply )
544548 except TargetError :
545549 self .log .exception ("Failed to open child target %s" , child )
546550 continue
547551
548552 yield target
549553
550554 if recursive :
551- yield from target .open_children (recursive = recursive )
555+ yield from target .open_children (recursive = recursive , apply = apply )
552556
553557 def list_children (self , recursive : bool = False ) -> Iterator [tuple [str , ChildTargetRecord ]]:
554558 """Lists all discovered child targets."""
@@ -569,7 +573,7 @@ def list_children(self, recursive: bool = False) -> Iterator[tuple[str, ChildTar
569573
570574 idx += 1
571575
572- def reload (self ) -> Target :
576+ def reload (self , * , apply : bool = True ) -> Target :
573577 """Reload the current target.
574578
575579 Using the loader with which the target was originally loaded,
@@ -584,12 +588,12 @@ def reload(self) -> Target:
584588 """
585589
586590 if self ._loader and self .path :
587- return self ._load (self .path , self ._loader )
591+ return self ._load (self .path , self ._loader , apply = apply )
588592
589593 raise TargetError ("Target has no path and/or loader" )
590594
591595 @classmethod
592- def _load (cls , path : str | Path | None , ldr : loader .Loader ) -> Self :
596+ def _load (cls , path : str | Path | None , ldr : loader .Loader , * , apply : bool = True ) -> Self :
593597 """Internal function that attemps to load a path using a given loader.
594598
595599 Args:
@@ -607,7 +611,9 @@ def _load(cls, path: str | Path | None, ldr: loader.Loader) -> Self:
607611 try :
608612 ldr .map (target )
609613 target ._loader = ldr
610- target .apply ()
614+
615+ if apply :
616+ target .apply ()
611617 except Exception as e :
612618 raise TargetError (f"Failed to load target: { path } " ) from e
613619 else :
@@ -893,6 +899,7 @@ def __repr__(self) -> str:
893899
894900class DiskCollection (Collection [container .Container ]):
895901 def apply (self ) -> None :
902+ """Identify (basic) volume systems on all disks and add their volumes to the volume collection."""
896903 for disk in self .entries :
897904 # Some LVM configurations (i.e. RAID with the metadata at the end of the disk)
898905 # may be misidentified as having a valid MBR/GPT on some of the disks
@@ -921,7 +928,13 @@ def apply(self) -> None:
921928
922929
923930class VolumeCollection (Collection [volume .Volume ]):
924- def apply (self ) -> None :
931+ def apply (self , * , filesystems : bool = True ) -> None :
932+ """Identify logical and encrypted volumes on all volumes and add their volumes to the volume collection.
933+ Additionally, identify filesystems on all volumes and add them to the filesystem collection.
934+
935+ Args:
936+ filesystems: Whether to identify filesystems on the volumes.
937+ """
925938 # We don't want later additions to modify the todo, so make a copy
926939 todo = self .entries [:]
927940 fs_volumes = []
@@ -988,6 +1001,10 @@ def apply(self) -> None:
9881001
9891002 todo = new_volumes
9901003
1004+ if not filesystems :
1005+ # Skip filesystem identification
1006+ return
1007+
9911008 mv_fs_volumes = []
9921009 for vol in fs_volumes :
9931010 try :
0 commit comments