dissect.hypervisor 3.17.dev2__py3-none-any.whl → 3.18.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dissect/hypervisor/tools/vmtar.py +20 -0
- dissect/hypervisor/util/vmtar.py +70 -5
- {dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info}/METADATA +3 -2
- {dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info}/RECORD +9 -8
- {dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info}/WHEEL +1 -1
- {dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info}/entry_points.txt +1 -0
- {dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info/licenses}/COPYRIGHT +0 -0
- {dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info/licenses}/LICENSE +0 -0
- {dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import tarfile
|
|
2
|
+
|
|
3
|
+
from dissect.hypervisor.util import vmtar
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main() -> None:
|
|
7
|
+
# We just want to run the main function of the tarfile module, but with our VisorTarFile and is_tarfile functions
|
|
8
|
+
type(tarfile.main)(
|
|
9
|
+
tarfile.main.__code__,
|
|
10
|
+
tarfile.main.__globals__
|
|
11
|
+
| {
|
|
12
|
+
"TarFile": vmtar.VisorTarFile,
|
|
13
|
+
"is_tarfile": vmtar.is_tarfile,
|
|
14
|
+
"open": vmtar.open,
|
|
15
|
+
},
|
|
16
|
+
)()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
main()
|
dissect/hypervisor/util/vmtar.py
CHANGED
|
@@ -5,6 +5,8 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
import struct
|
|
7
7
|
import tarfile
|
|
8
|
+
from io import BytesIO
|
|
9
|
+
from typing import BinaryIO, Final
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class VisorTarInfo(tarfile.TarInfo):
|
|
@@ -49,9 +51,72 @@ class VisorTarInfo(tarfile.TarInfo):
|
|
|
49
51
|
return super()._proc_member(tarfile)
|
|
50
52
|
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
class VisorTarFile(tarfile.TarFile):
|
|
55
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
56
|
+
super().__init__(*args, **kwargs, tarinfo=VisorTarInfo)
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
def
|
|
57
|
-
|
|
58
|
+
@classmethod
|
|
59
|
+
def visoropen(cls, name: str, mode: str = "r", fileobj: BinaryIO | None = None, **kwargs) -> VisorTarFile:
|
|
60
|
+
"""Open a visor tar file for reading. Supports gzip and lzma compression."""
|
|
61
|
+
if mode not in ("r",):
|
|
62
|
+
raise tarfile.TarError("visor currently only supports read mode")
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
from gzip import GzipFile
|
|
66
|
+
except ImportError:
|
|
67
|
+
raise tarfile.CompressionError("gzip module is not available") from None
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
from lzma import LZMAError, LZMAFile
|
|
71
|
+
except ImportError:
|
|
72
|
+
raise tarfile.CompressionError("lzma module is not available") from None
|
|
73
|
+
|
|
74
|
+
compressed = False
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
t = cls.taropen(name, mode, fileobj, **kwargs)
|
|
78
|
+
except Exception:
|
|
79
|
+
try:
|
|
80
|
+
fileobj = GzipFile(name, mode + "b", fileobj=fileobj)
|
|
81
|
+
except OSError as e:
|
|
82
|
+
if fileobj is not None and mode == "r":
|
|
83
|
+
raise tarfile.ReadError("not a visor file") from e
|
|
84
|
+
raise
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
t = cls.taropen(name, mode, fileobj, **kwargs)
|
|
88
|
+
except Exception:
|
|
89
|
+
fileobj.seek(0)
|
|
90
|
+
fileobj = LZMAFile(fileobj or name, mode) # noqa: SIM115
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
t = cls.taropen(name, mode, fileobj, **kwargs)
|
|
94
|
+
except (LZMAError, EOFError, OSError) as e:
|
|
95
|
+
fileobj.close()
|
|
96
|
+
if mode == "r":
|
|
97
|
+
raise tarfile.ReadError("not a visor file") from e
|
|
98
|
+
raise
|
|
99
|
+
except:
|
|
100
|
+
fileobj.close()
|
|
101
|
+
raise
|
|
102
|
+
|
|
103
|
+
compressed = True
|
|
104
|
+
|
|
105
|
+
# If we get here, we have a valid visor tar file
|
|
106
|
+
if fileobj is not None and compressed:
|
|
107
|
+
# Just read the entire file into memory, it's probably small
|
|
108
|
+
fileobj.seek(0)
|
|
109
|
+
fileobj = BytesIO(fileobj.read())
|
|
110
|
+
|
|
111
|
+
t = cls.taropen(name, mode, fileobj, **kwargs)
|
|
112
|
+
|
|
113
|
+
t._extfileobj = False
|
|
114
|
+
return t
|
|
115
|
+
|
|
116
|
+
# Only allow opening visor tar files
|
|
117
|
+
OPEN_METH: Final[dict[str, str]] = {"visor": "visoropen"}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
open = VisorTarFile.open
|
|
121
|
+
|
|
122
|
+
is_tarfile = type(tarfile.is_tarfile)(tarfile.is_tarfile.__code__, tarfile.is_tarfile.__globals__ | {"open": open})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.hypervisor
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.18.dev1
|
|
4
4
|
Summary: A Dissect module implementing parsers for various hypervisor disk, backup and configuration files
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
|
@@ -31,6 +31,7 @@ Provides-Extra: dev
|
|
|
31
31
|
Requires-Dist: dissect.hypervisor[full]; extra == "dev"
|
|
32
32
|
Requires-Dist: dissect.cstruct<5.0.dev,>=4.0.dev; extra == "dev"
|
|
33
33
|
Requires-Dist: dissect.util<4.0.dev,>=3.0.dev; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
34
35
|
|
|
35
36
|
# dissect.hypervisor
|
|
36
37
|
|
|
@@ -22,13 +22,14 @@ dissect/hypervisor/disk/vhdx.py,sha256=Yidz57PsH6IGRiN8cpfAnyZiOGt1qApd8ohVdHGF2
|
|
|
22
22
|
dissect/hypervisor/disk/vmdk.py,sha256=s23a8Gs_kemy4ZKYuJYXYCFckZtYgeZ7Rmrgxpj5W7s,19565
|
|
23
23
|
dissect/hypervisor/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
dissect/hypervisor/tools/envelope.py,sha256=BvaBSoXq3VrZ2GJVrfnL8NB6OLbdp8qD05jedxSAKwQ,1024
|
|
25
|
+
dissect/hypervisor/tools/vmtar.py,sha256=bAf_rEhqUmeI8my22p7L9uV3SgB5C_61YQKfD3tNo60,476
|
|
25
26
|
dissect/hypervisor/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
27
|
dissect/hypervisor/util/envelope.py,sha256=EhZjZh3EezqxkJ84OgqpptHIhpVWPcUkFMjdYU-iAnU,10442
|
|
27
|
-
dissect/hypervisor/util/vmtar.py,sha256=
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
dissect/hypervisor/util/vmtar.py,sha256=xzc4bd5RnBgP9_dCU9i-ZwXI_0S3N7gCfMzElwwnd5s,4004
|
|
29
|
+
dissect_hypervisor-3.18.dev1.dist-info/licenses/COPYRIGHT,sha256=EOOoIwk_inOMUD4c1ylpzMtYLjGzmc-MLEVAEdLLr20,305
|
|
30
|
+
dissect_hypervisor-3.18.dev1.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
|
31
|
+
dissect_hypervisor-3.18.dev1.dist-info/METADATA,sha256=I1eM8mXEJRNMCt4RfSLZQ1-FU730qvKO5xV6pqcw1WI,3434
|
|
32
|
+
dissect_hypervisor-3.18.dev1.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
|
33
|
+
dissect_hypervisor-3.18.dev1.dist-info/entry_points.txt,sha256=kW36GnJ3G1dSRYFL4r8Bj32Al_CkGqST3bdHvo3pyiY,120
|
|
34
|
+
dissect_hypervisor-3.18.dev1.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
|
35
|
+
dissect_hypervisor-3.18.dev1.dist-info/RECORD,,
|
{dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info/licenses}/COPYRIGHT
RENAMED
|
File without changes
|
{dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info/licenses}/LICENSE
RENAMED
|
File without changes
|
{dissect.hypervisor-3.17.dev2.dist-info → dissect_hypervisor-3.18.dev1.dist-info}/top_level.txt
RENAMED
|
File without changes
|