dissect.target 3.19.dev38__py3-none-any.whl → 3.19.dev39__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- dissect/target/filesystems/zip.py +81 -46
- {dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/METADATA +1 -1
- {dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/RECORD +8 -8
- {dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/LICENSE +0 -0
- {dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/WHEEL +0 -0
- {dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/top_level.txt +0 -0
@@ -4,16 +4,21 @@ import logging
|
|
4
4
|
import stat
|
5
5
|
import zipfile
|
6
6
|
from datetime import datetime, timezone
|
7
|
-
from typing import BinaryIO,
|
7
|
+
from typing import BinaryIO, Iterator
|
8
8
|
|
9
9
|
from dissect.util.stream import BufferedStream
|
10
10
|
|
11
|
-
from dissect.target.exceptions import
|
11
|
+
from dissect.target.exceptions import (
|
12
|
+
FileNotFoundError,
|
13
|
+
FilesystemError,
|
14
|
+
IsADirectoryError,
|
15
|
+
NotADirectoryError,
|
16
|
+
NotASymlinkError,
|
17
|
+
)
|
12
18
|
from dissect.target.filesystem import (
|
13
19
|
Filesystem,
|
14
20
|
FilesystemEntry,
|
15
21
|
VirtualDirectory,
|
16
|
-
VirtualFile,
|
17
22
|
VirtualFilesystem,
|
18
23
|
)
|
19
24
|
from dissect.target.helpers import fsutil
|
@@ -33,7 +38,7 @@ class ZipFilesystem(Filesystem):
|
|
33
38
|
def __init__(
|
34
39
|
self,
|
35
40
|
fh: BinaryIO,
|
36
|
-
base:
|
41
|
+
base: str | None = None,
|
37
42
|
*args,
|
38
43
|
**kwargs,
|
39
44
|
):
|
@@ -52,12 +57,7 @@ class ZipFilesystem(Filesystem):
|
|
52
57
|
continue
|
53
58
|
|
54
59
|
rel_name = fsutil.normpath(mname[len(self.base) :], alt_separator=self.alt_separator)
|
55
|
-
|
56
|
-
# NOTE: Normally we would check here if the member is a symlink or not
|
57
|
-
|
58
|
-
entry_cls = ZipFilesystemDirectoryEntry if member.is_dir() else ZipFilesystemEntry
|
59
|
-
file_entry = entry_cls(self, rel_name, member)
|
60
|
-
self._fs.map_file_entry(rel_name, file_entry)
|
60
|
+
self._fs.map_file_entry(rel_name, ZipFilesystemEntry(self, rel_name, member))
|
61
61
|
|
62
62
|
@staticmethod
|
63
63
|
def _detect(fh: BinaryIO) -> bool:
|
@@ -69,60 +69,95 @@ class ZipFilesystem(Filesystem):
|
|
69
69
|
return self._fs.get(path, relentry=relentry)
|
70
70
|
|
71
71
|
|
72
|
-
|
72
|
+
# Note: We subclass from VirtualDirectory because VirtualFilesystem is currently only compatible with VirtualDirectory
|
73
|
+
# Subclass from VirtualDirectory so we get that compatibility for free, and override the rest to do our own thing
|
74
|
+
class ZipFilesystemEntry(VirtualDirectory):
|
75
|
+
fs: ZipFilesystem
|
76
|
+
entry: zipfile.ZipInfo
|
77
|
+
|
78
|
+
def __init__(self, fs: ZipFilesystem, path: str, entry: zipfile.ZipInfo):
|
79
|
+
super().__init__(fs, path)
|
80
|
+
self.entry = entry
|
81
|
+
|
73
82
|
def open(self) -> BinaryIO:
|
74
|
-
|
83
|
+
if self.is_dir():
|
84
|
+
raise IsADirectoryError(self.path)
|
85
|
+
|
86
|
+
if self.is_symlink():
|
87
|
+
return self._resolve().open()
|
88
|
+
|
75
89
|
try:
|
76
90
|
return BufferedStream(self.fs.zip.open(self.entry), size=self.entry.file_size)
|
77
91
|
except Exception:
|
78
|
-
raise FileNotFoundError()
|
92
|
+
raise FileNotFoundError(self.path)
|
79
93
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
94
|
+
def iterdir(self) -> Iterator[str]:
|
95
|
+
if not self.is_dir():
|
96
|
+
raise NotADirectoryError(self.path)
|
83
97
|
|
84
|
-
|
85
|
-
|
86
|
-
|
98
|
+
entry = self._resolve()
|
99
|
+
if isinstance(entry, ZipFilesystemEntry):
|
100
|
+
yield from super(ZipFilesystemEntry, entry).iterdir()
|
101
|
+
else:
|
102
|
+
yield from entry.iterdir()
|
87
103
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
104
|
+
def scandir(self) -> Iterator[FilesystemEntry]:
|
105
|
+
if not self.is_dir():
|
106
|
+
raise NotADirectoryError(self.path)
|
91
107
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
stat.S_IFREG | 0o777,
|
98
|
-
self.entry.header_offset,
|
99
|
-
id(self.fs),
|
100
|
-
1,
|
101
|
-
0,
|
102
|
-
0,
|
103
|
-
self.entry.file_size,
|
104
|
-
0,
|
105
|
-
datetime(*self.entry.date_time, tzinfo=timezone.utc).timestamp(),
|
106
|
-
0,
|
107
|
-
]
|
108
|
-
)
|
108
|
+
entry = self._resolve()
|
109
|
+
if isinstance(entry, ZipFilesystemEntry):
|
110
|
+
yield from super(ZipFilesystemEntry, entry).scandir()
|
111
|
+
else:
|
112
|
+
yield from entry.scandir()
|
109
113
|
|
114
|
+
def is_dir(self, follow_symlinks: bool = True) -> bool:
|
115
|
+
try:
|
116
|
+
entry = self._resolve(follow_symlinks=follow_symlinks)
|
117
|
+
except FilesystemError:
|
118
|
+
return False
|
110
119
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
120
|
+
if isinstance(entry, ZipFilesystemEntry):
|
121
|
+
return entry.entry.is_dir()
|
122
|
+
return isinstance(entry, VirtualDirectory)
|
123
|
+
|
124
|
+
def is_file(self, follow_symlinks: bool = True) -> bool:
|
125
|
+
try:
|
126
|
+
entry = self._resolve(follow_symlinks=follow_symlinks)
|
127
|
+
except FilesystemError:
|
128
|
+
return False
|
129
|
+
|
130
|
+
if isinstance(entry, ZipFilesystemEntry):
|
131
|
+
return not entry.entry.is_dir()
|
132
|
+
return False
|
133
|
+
|
134
|
+
def is_symlink(self) -> bool:
|
135
|
+
return stat.S_ISLNK(self.entry.external_attr >> 16)
|
136
|
+
|
137
|
+
def readlink(self) -> str:
|
138
|
+
if not self.is_symlink():
|
139
|
+
raise NotASymlinkError()
|
140
|
+
return self.fs.zip.open(self.entry).read().decode()
|
141
|
+
|
142
|
+
def readlink_ext(self) -> FilesystemEntry:
|
143
|
+
return FilesystemEntry.readlink_ext(self)
|
115
144
|
|
116
145
|
def stat(self, follow_symlinks: bool = True) -> fsutil.stat_result:
|
117
|
-
|
118
|
-
return self.lstat()
|
146
|
+
return self._resolve(follow_symlinks=follow_symlinks).lstat()
|
119
147
|
|
120
148
|
def lstat(self) -> fsutil.stat_result:
|
121
149
|
"""Return the stat information of the given path, without resolving links."""
|
122
150
|
# ['mode', 'addr', 'dev', 'nlink', 'uid', 'gid', 'size', 'atime', 'mtime', 'ctime']
|
151
|
+
mode = self.entry.external_attr >> 16
|
152
|
+
|
153
|
+
if self.entry.is_dir() and not stat.S_ISDIR(mode):
|
154
|
+
mode = stat.S_IFDIR | mode
|
155
|
+
elif not self.entry.is_dir() and not stat.S_ISREG(mode):
|
156
|
+
mode = stat.S_IFREG | mode
|
157
|
+
|
123
158
|
return fsutil.stat_result(
|
124
159
|
[
|
125
|
-
|
160
|
+
mode,
|
126
161
|
self.entry.header_offset,
|
127
162
|
id(self.fs),
|
128
163
|
1,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.19.
|
3
|
+
Version: 3.19.dev39
|
4
4
|
Summary: This module ties all other Dissect modules together, it provides a programming API and command line tools which allow easy access to various data sources inside disk images or file collections (a.k.a. targets)
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
6
6
|
License: Affero General Public License v3
|
@@ -42,7 +42,7 @@ dissect/target/filesystems/tar.py,sha256=kQNhcEDPX005svse039OeR2AGSDigGuGz2AKoVr
|
|
42
42
|
dissect/target/filesystems/vmfs.py,sha256=sRtYBUAKTKcHrjCXqpFJ8GIVU-ERjqxhB2zXBndtcXU,4955
|
43
43
|
dissect/target/filesystems/vmtar.py,sha256=LlKWkTIuLemQmG9yGqL7980uC_AOL77_GWhbJc_grSk,804
|
44
44
|
dissect/target/filesystems/xfs.py,sha256=kIyFGKYlyFYC7H3jaEv-lNKtBW4ZkD92H0WpfGcr1ww,4498
|
45
|
-
dissect/target/filesystems/zip.py,sha256=
|
45
|
+
dissect/target/filesystems/zip.py,sha256=BeNj23DOYfWuTm5V1V419ViJiMfBrO1VA5gP6rljwXs,5467
|
46
46
|
dissect/target/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
47
|
dissect/target/helpers/cache.py,sha256=TXlJBdFRz6V9zKs903am4Yawr0maYw5kZY0RqklDQJM,8568
|
48
48
|
dissect/target/helpers/config.py,sha256=RMHnIuKJHINHiLrvKN3EyA0jFA1o6-pbeaycG8Pgrp8,2596
|
@@ -349,10 +349,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
|
|
349
349
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
350
350
|
dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
|
351
351
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
352
|
-
dissect.target-3.19.
|
353
|
-
dissect.target-3.19.
|
354
|
-
dissect.target-3.19.
|
355
|
-
dissect.target-3.19.
|
356
|
-
dissect.target-3.19.
|
357
|
-
dissect.target-3.19.
|
358
|
-
dissect.target-3.19.
|
352
|
+
dissect.target-3.19.dev39.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
353
|
+
dissect.target-3.19.dev39.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
354
|
+
dissect.target-3.19.dev39.dist-info/METADATA,sha256=c6QzWVFBBowHJF8fihCzibN_ELCTHhj59sC_YGZIqhY,12719
|
355
|
+
dissect.target-3.19.dev39.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
356
|
+
dissect.target-3.19.dev39.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
|
357
|
+
dissect.target-3.19.dev39.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
358
|
+
dissect.target-3.19.dev39.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.19.dev38.dist-info → dissect.target-3.19.dev39.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|