55
66from functools import cached_property , lru_cache
77from io import BytesIO
8- from typing import BinaryIO , Generic , Iterator , Optional , TypeVar
8+ from typing import BinaryIO , Generic , Iterator , TypeVar
99from zlib import crc32
1010
1111from dissect .cstruct import Structure
12+ from dissect .hypervisor .backup .c_vbk import c_vbk
13+ from dissect .hypervisor .exceptions import Error
14+ from dissect .util .compression import lz4
1215from dissect .util .crc32c import crc32c
1316from dissect .util .stream import AlignedStream
1417from dissect .util .xmemoryview import xmemoryview
1518
16- try :
17- from lz4 .block import decompress as lz4_decompress
18- except ImportError :
19- from dissect .util .compression .lz4 import decompress as lz4_decompress
20-
21- from dissect .hypervisor .backup .c_vbk import c_vbk
22- from dissect .hypervisor .exceptions import Error
23-
2419PAGE_SIZE = 4096
2520"""VBK page size."""
2621
@@ -108,7 +103,7 @@ def read_meta_blob(self, page: int) -> bytes:
108103 """
109104 return self .active_slot ._get_meta_blob (page )
110105
111- def get (self , path : str , item : Optional [ DirItem ] = None ) -> DirItem :
106+ def get (self , path : str , item : DirItem | None = None ) -> DirItem :
112107 """Get a directory item from the VBK file."""
113108 item = item or self .root
114109
@@ -351,7 +346,7 @@ def size(self) -> int:
351346 raise VBKError (f"Size not available for { self !r} " )
352347
353348 @cached_property
354- def properties (self ) -> Optional [ PropertiesDictionary ] :
349+ def properties (self ) -> PropertiesDictionary | None :
355350 """The properties of the directory item, if it has them."""
356351 if self .entry .PropsRootPage == - 1 :
357352 return None
@@ -360,25 +355,22 @@ def properties(self) -> Optional[PropertiesDictionary]:
360355
361356 def is_dir (self ) -> bool :
362357 """Return whether the directory item is a directory."""
363- return isinstance ( self , ( RootDirectory , SubFolderItem ))
358+ return False
364359
365360 def is_file (self ) -> bool :
366361 """Return whether the directory item is a file."""
367362 return self .is_internal_file () or self .is_external_file ()
368363
369364 def is_internal_file (self ) -> bool :
370365 """Return whether the directory item is an internal file."""
371- return isinstance ( self , IntFibItem )
366+ return False
372367
373368 def is_external_file (self ) -> bool :
374369 """Return whether the directory item is an external file."""
375- return isinstance ( self , ExtFibItem )
370+ return False
376371
377372 def listdir (self ) -> dict [str , DirItem ]:
378373 """Return a dictionary of the items in the directory."""
379- if not self .is_dir ():
380- raise NotADirectoryError (f"{ self !r} is not a directory" )
381-
382374 return {item .name : item for item in self .iterdir ()}
383375
384376 def iterdir (self ) -> Iterator [DirItem ]:
@@ -402,6 +394,9 @@ def __init__(self, vbk: VBK, page: int, count: int):
402394 def __repr__ (self ) -> str :
403395 return f"<RootDirectory root={ self .root } count={ self .count } >"
404396
397+ def is_dir (self ) -> bool :
398+ return True
399+
405400 def iterdir (self ) -> Iterator [DirItem ]:
406401 yield from MetaVector (self .vbk , DirItem , self .root , self .count )
407402
@@ -422,6 +417,9 @@ def __init__(self, vbk: VBK, buf: bytes):
422417 def __repr__ (self ) -> str :
423418 return f"<SubFolderItem name={ self .name !r} root={ self .root } count={ self .count } >"
424419
420+ def is_dir (self ) -> bool :
421+ return True
422+
425423 def iterdir (self ) -> Iterator [DirItem ]:
426424 yield from MetaVector (self .vbk , DirItem , self .root , self .count )
427425
@@ -441,6 +439,9 @@ def __repr__(self) -> str:
441439 def size (self ) -> int :
442440 return self .entry .ExtFib .FibSize
443441
442+ def is_external_file (self ) -> bool :
443+ return True
444+
444445
445446class IntFibItem (DirItem ):
446447 """Directory item for an internal file.
@@ -460,6 +461,9 @@ def __repr__(self) -> str:
460461 def size (self ) -> int :
461462 return self .entry .IntFib .FibSize
462463
464+ def is_internal_file (self ) -> bool :
465+ return True
466+
463467 def open (self ) -> FibStream :
464468 return FibStream (
465469 self .vbk ,
@@ -477,13 +481,13 @@ class PatchItem(DirItem):
477481 - **TODO**: CPatchMeta
478482 """
479483
484+ def __repr__ (self ) -> str :
485+ return f"<PatchItem name={ self .name !r} size={ self .size } >"
486+
480487 @cached_property
481488 def size (self ) -> int :
482489 return self .entry .Patch .FibSize
483490
484- def __repr__ (self ) -> str :
485- return f"<PatchItem name={ self .name !r} size={ self .size } >"
486-
487491
488492class IncrementItem (DirItem ):
489493 """Directory item for an increment.
@@ -493,13 +497,13 @@ class IncrementItem(DirItem):
493497 - **TODO**: CIncrementMeta
494498 """
495499
500+ def __repr__ (self ) -> str :
501+ return f"<IncrementItem name={ self .name !r} size={ self .size } >"
502+
496503 @cached_property
497504 def size (self ) -> int :
498505 return self .entry .Increment .FibSize
499506
500- def __repr__ (self ) -> str :
501- return f"<IncrementItem name={ self .name !r} size={ self .size } >"
502-
503507
504508class MetaTableDescriptor (MetaItem ):
505509 """A descriptor for a meta table in the VBK file.
@@ -1030,7 +1034,7 @@ def _read(self, offset: int, length: int) -> bytes:
10301034 if block .is_compressed ():
10311035 if block .compression_type == c_vbk .CompressionType .LZ4 :
10321036 # First 12 bytes are Lz4BlockHeader
1033- buf = lz4_decompress (memoryview (buf )[12 :], block .source_size )
1037+ buf = lz4 . decompress (memoryview (buf )[12 :], block .source_size )
10341038 else :
10351039 raise VBKError (f"Unsupported compression type: { block .compression_type } " )
10361040
0 commit comments