dissect.target 3.18.dev2__py3-none-any.whl → 3.18.dev4__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.
@@ -1,8 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import platform
4
- from io import BytesIO
5
- from typing import BinaryIO, Iterable
4
+ from typing import BinaryIO, Iterator
6
5
 
7
6
  from dissect.cstruct import cstruct
8
7
  from dissect.util.stream import RangeStream
@@ -13,7 +12,11 @@ from dissect.target.plugin import export
13
12
  from dissect.target.plugins.os.unix.locate.locate import BaseLocatePlugin
14
13
 
15
14
  try:
16
- import zstandard # noqa
15
+ from zstandard import (
16
+ DECOMPRESSION_RECOMMENDED_OUTPUT_SIZE,
17
+ ZstdCompressionDict,
18
+ ZstdDecompressor,
19
+ )
17
20
 
18
21
  HAS_ZSTD = True
19
22
  except ImportError:
@@ -32,7 +35,7 @@ struct header {
32
35
  uint64_t filename_index_offset_bytes;
33
36
 
34
37
  /* Version 1 and up only. */
35
- uint32_t max_version;
38
+ uint32_t max_version; // Nominally 1 or 2, but can be increased if more features are added in a backward-compatible way.
36
39
  uint32_t zstd_dictionary_length_bytes;
37
40
  uint64_t zstd_dictionary_offset_bytes;
38
41
 
@@ -44,6 +47,7 @@ struct header {
44
47
  uint64_t conf_block_length_bytes;
45
48
  uint64_t conf_block_offset_bytes;
46
49
 
50
+ // Only if max_version >= 2.
47
51
  uint8_t check_visibility;
48
52
  char padding[7]; /* padding for alignment */
49
53
  };
@@ -51,7 +55,7 @@ struct header {
51
55
  struct file {
52
56
  char path[];
53
57
  };
54
- """
58
+ """ # noqa : E501
55
59
 
56
60
  PLocateRecord = TargetRecordDescriptor(
57
61
  "linux/locate/plocate",
@@ -104,40 +108,46 @@ class PLocateFile:
104
108
  self.dict_data = None
105
109
 
106
110
  if self.header.zstd_dictionary_offset_bytes:
107
- self.dict_data = zstandard.ZstdCompressionDict(self.fh.read(self.header.zstd_dictionary_length_bytes))
111
+ self.dict_data = ZstdCompressionDict(self.fh.read(self.header.zstd_dictionary_length_bytes))
108
112
 
109
113
  self.compressed_length_bytes = (
110
114
  self.header.filename_index_offset_bytes - self.HEADER_SIZE - self.header.zstd_dictionary_length_bytes
111
115
  )
112
- self.ctx = zstandard.ZstdDecompressor(dict_data=self.dict_data)
116
+ self.ctx = ZstdDecompressor(dict_data=self.dict_data)
113
117
  self.buf = RangeStream(self.fh, self.fh.tell(), self.compressed_length_bytes)
114
118
 
115
- def __iter__(self) -> Iterable[PLocateFile]:
119
+ def __iter__(self) -> Iterator[PLocateFile]:
116
120
  # NOTE: This is a workaround for a PyPy bug
117
121
  # We don't know what breaks, but PyPy + zstandard = unhappy times
118
122
  # You just get random garbage data back instead of the decompressed data
119
123
  # This weird dance of using a decompressobj and unused data is the only way that seems to work
120
124
  # It's more expensive on memory, but at least it doesn't break
121
125
  if platform.python_implementation() == "PyPy":
122
- obj = self.ctx.decompressobj()
123
126
  buf = self.buf.read()
124
127
 
125
- tmp = obj.decompress(buf)
126
- while unused_data := obj.unused_data:
127
- obj = self.ctx.decompressobj()
128
- tmp += obj.decompress(unused_data)
128
+ def reader(ctx: ZstdDecompressor) -> Iterator[bytes]:
129
+ obj = ctx.decompressobj()
129
130
 
130
- reader = BytesIO(tmp)
131
+ yield obj.decompress(buf)
132
+ while unused_data := obj.unused_data:
133
+ obj = self.ctx.decompressobj()
134
+ yield obj.decompress(unused_data)
135
+
136
+ it = reader(self.ctx)
131
137
  else:
132
- reader = self.ctx.stream_reader(self.buf)
133
-
134
- with reader:
135
- try:
136
- while True:
137
- file = c_plocate.file(reader)
138
- yield file.path.decode(errors="surrogateescape")
139
- except EOFError:
140
- return
138
+ # NOTE: The end of a zstandard frame does not include a final `0x00`.
139
+ # This causes the c_plocate `file` struct to parse the last path and the first path on the next frame as one
140
+ # since cstruct will read it across frame boundaries waiting for a `0x00`.
141
+ def reader() -> Iterator[bytes]:
142
+ with self.ctx.stream_reader(self.buf) as reader:
143
+ while chunk := reader.read(DECOMPRESSION_RECOMMENDED_OUTPUT_SIZE):
144
+ yield chunk
145
+
146
+ it = reader()
147
+
148
+ for chunk in it:
149
+ for path in chunk.split(b"\x00"):
150
+ yield path.decode(errors="surrogateescape")
141
151
 
142
152
  def filename_index(self) -> bytes:
143
153
  """Return the filename index of the plocate.db file."""
@@ -113,6 +113,7 @@ class TargetCmd(cmd.Cmd):
113
113
  def __init__(self, target: Target):
114
114
  cmd.Cmd.__init__(self)
115
115
  self.target = target
116
+ self.debug = False
116
117
 
117
118
  def __getattr__(self, attr: str) -> Any:
118
119
  if attr.startswith("help_"):
@@ -179,25 +180,22 @@ class TargetCmd(cmd.Cmd):
179
180
  lexer.whitespace_split = True
180
181
  argparts = list(lexer)
181
182
 
182
- try:
183
- if "|" in argparts:
184
- pipeidx = argparts.index("|")
185
- argparts, pipeparts = argparts[:pipeidx], argparts[pipeidx + 1 :]
186
- try:
187
- with build_pipe_stdout(pipeparts) as pipe_stdin:
188
- return func(argparts, pipe_stdin)
189
- except OSError as e:
190
- # in case of a failure in a subprocess
191
- print(e)
192
- else:
193
- ctx = contextlib.nullcontext()
194
- if self.target.props.get("cyber") and not no_cyber:
195
- ctx = cyber.cyber(color=None, run_at_end=True)
183
+ if "|" in argparts:
184
+ pipeidx = argparts.index("|")
185
+ argparts, pipeparts = argparts[:pipeidx], argparts[pipeidx + 1 :]
186
+ try:
187
+ with build_pipe_stdout(pipeparts) as pipe_stdin:
188
+ return func(argparts, pipe_stdin)
189
+ except OSError as e:
190
+ # in case of a failure in a subprocess
191
+ print(e)
192
+ else:
193
+ ctx = contextlib.nullcontext()
194
+ if self.target.props.get("cyber") and not no_cyber:
195
+ ctx = cyber.cyber(color=None, run_at_end=True)
196
196
 
197
- with ctx:
198
- return func(argparts, sys.stdout)
199
- except IOError:
200
- pass
197
+ with ctx:
198
+ return func(argparts, sys.stdout)
201
199
 
202
200
  def _exec_command(self, command: str, command_args_str: str) -> Optional[bool]:
203
201
  """Command execution helper for ``cmd_`` commands."""
@@ -279,6 +277,14 @@ class TargetCmd(cmd.Cmd):
279
277
  """exit shell"""
280
278
  return True
281
279
 
280
+ def do_debug(self, line: str) -> Optional[bool]:
281
+ """toggle debug mode"""
282
+ self.debug = not self.debug
283
+ if self.debug:
284
+ print("Debug mode on")
285
+ else:
286
+ print("Debug mode off")
287
+
282
288
 
283
289
  class TargetHubCli(cmd.Cmd):
284
290
  """Hub Cli for interacting with multiple targets."""
@@ -1241,7 +1247,12 @@ def run_cli(cli: cmd.Cmd) -> None:
1241
1247
  print()
1242
1248
  pass
1243
1249
  except Exception as e:
1244
- log.exception(e)
1250
+ if cli.debug:
1251
+ log.exception(e)
1252
+ else:
1253
+ log.info(e)
1254
+ print(f"*** Unhandled error: {e}")
1255
+ print("If you wish to see the full debug trace, enable debug mode.")
1245
1256
  pass
1246
1257
 
1247
1258
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.18.dev2
3
+ Version: 3.18.dev4
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
@@ -243,7 +243,7 @@ dissect/target/plugins/os/unix/locate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
243
243
  dissect/target/plugins/os/unix/locate/gnulocate.py,sha256=P-YbMFw901p2EBgTaZH6axShfIRRDrCx3APBy6Ii3lE,2934
244
244
  dissect/target/plugins/os/unix/locate/locate.py,sha256=uXFcWAqoz_3eNWHhsGoEtkkhmT5J3F1GYvr4uQxi308,122
245
245
  dissect/target/plugins/os/unix/locate/mlocate.py,sha256=DhrFgxDQF-fMZaA0WK8Z-5o9i9iDsuTHW7MHJtWwz6o,4485
246
- dissect/target/plugins/os/unix/locate/plocate.py,sha256=Skb24ba_MVzM4nuDaZHw-ZmomIEZ3TJ7g5kHCvQViko,6545
246
+ dissect/target/plugins/os/unix/locate/plocate.py,sha256=ShU-F9_31rGfMYXqaR_KrHXVxgDDRZMJ_zEMuekw57w,7229
247
247
  dissect/target/plugins/os/unix/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
248
248
  dissect/target/plugins/os/unix/log/atop.py,sha256=DdiTf-gVJJvvPbR36khU4388lxQzABaWI-95jLCGgSw,16345
249
249
  dissect/target/plugins/os/unix/log/audit.py,sha256=OjorWTmCFvCI5RJq6m6WNW0Lhb-poB2VAggKOGZUHK4,3722
@@ -326,7 +326,7 @@ dissect/target/tools/logging.py,sha256=5ZnumtMWLyslxfrUGZ4ntRyf3obOOhmn8SBjKfdLc
326
326
  dissect/target/tools/mount.py,sha256=L_0tSmiBdW4aSaF0vXjB0bAkTC0kmT2N1hrbW6s5Jow,3254
327
327
  dissect/target/tools/query.py,sha256=ONHu2FVomLccikb84qBrlhNmEfRoHYFQMcahk_y2c9A,15580
328
328
  dissect/target/tools/reg.py,sha256=FDsiBBDxjWVUBTRj8xn82vZe-J_d9piM-TKS3PHZCcM,3193
329
- dissect/target/tools/shell.py,sha256=4v6Z06YJDjKv6e6SRvWNjQ2n_KHo_CjL4P0w1_gY_ro,44827
329
+ dissect/target/tools/shell.py,sha256=1Z-gYRlJu0rmFI20taatlofrvp52ac_arXG8AMhwj0w,45182
330
330
  dissect/target/tools/utils.py,sha256=sQizexY3ui5vmWw4KOBLg5ecK3TPFjD-uxDqRn56ZTY,11304
331
331
  dissect/target/tools/dump/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
332
332
  dissect/target/tools/dump/run.py,sha256=aD84peRS4zHqC78fH7Vd4ni3m1ZmVP70LyMwBRvoDGY,9463
@@ -340,10 +340,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
340
340
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
341
341
  dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
342
342
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
343
- dissect.target-3.18.dev2.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
344
- dissect.target-3.18.dev2.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
345
- dissect.target-3.18.dev2.dist-info/METADATA,sha256=CQlktWeUyWCrkDq9WKqNFR3gxHwKVUZ-9KDPop4n6s8,11299
346
- dissect.target-3.18.dev2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
347
- dissect.target-3.18.dev2.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
348
- dissect.target-3.18.dev2.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
349
- dissect.target-3.18.dev2.dist-info/RECORD,,
343
+ dissect.target-3.18.dev4.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
344
+ dissect.target-3.18.dev4.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
345
+ dissect.target-3.18.dev4.dist-info/METADATA,sha256=gk5V6v0uboLj95v64bfrxLe_sT7-fksU2GJTOvRXBfE,11299
346
+ dissect.target-3.18.dev4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
347
+ dissect.target-3.18.dev4.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
348
+ dissect.target-3.18.dev4.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
349
+ dissect.target-3.18.dev4.dist-info/RECORD,,