dissect.target 3.18.dev2__py3-none-any.whl → 3.18.dev3__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."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.18.dev2
3
+ Version: 3.18.dev3
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
@@ -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.dev3.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
344
+ dissect.target-3.18.dev3.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
345
+ dissect.target-3.18.dev3.dist-info/METADATA,sha256=t5yUGDDtnDgTACRs1bUW1xJF2rlVMzxbFW0iWG5WRUw,11299
346
+ dissect.target-3.18.dev3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
347
+ dissect.target-3.18.dev3.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
348
+ dissect.target-3.18.dev3.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
349
+ dissect.target-3.18.dev3.dist-info/RECORD,,