dissect.target 3.16.dev24__py3-none-any.whl → 3.16.dev25__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- dissect/target/filesystem.py +2 -0
- dissect/target/filesystems/cpio.py +18 -0
- dissect/target/helpers/fsutil.py +37 -6
- {dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/METADATA +1 -1
- {dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/RECORD +10 -9
- {dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/LICENSE +0 -0
- {dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/WHEEL +0 -0
- {dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/top_level.txt +0 -0
dissect/target/filesystem.py
CHANGED
@@ -1588,5 +1588,7 @@ register("btrfs", "BtrfsFilesystem")
|
|
1588
1588
|
register("exfat", "ExfatFilesystem")
|
1589
1589
|
register("squashfs", "SquashFSFilesystem")
|
1590
1590
|
register("zip", "ZipFilesystem")
|
1591
|
+
register("tar", "TarFilesystem")
|
1592
|
+
register("cpio", "CpioFilesystem")
|
1591
1593
|
register("ad1", "AD1Filesystem")
|
1592
1594
|
register("jffs", "JFFSFilesystem")
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from typing import BinaryIO, Optional
|
2
|
+
|
3
|
+
from dissect.util import cpio
|
4
|
+
|
5
|
+
from dissect.target.filesystems.tar import TarFilesystem
|
6
|
+
from dissect.target.helpers.fsutil import open_decompress
|
7
|
+
|
8
|
+
|
9
|
+
class CpioFilesystem(TarFilesystem):
|
10
|
+
__type__ = "cpio"
|
11
|
+
|
12
|
+
def __init__(self, fh: BinaryIO, base: Optional[str] = None, *args, **kwargs):
|
13
|
+
super().__init__(open_decompress(fileobj=fh), base, tarinfo=cpio.CpioInfo, *args, **kwargs)
|
14
|
+
|
15
|
+
@staticmethod
|
16
|
+
def _detect(fh: BinaryIO) -> bool:
|
17
|
+
"""Detect a cpio file on a given file-like object."""
|
18
|
+
return cpio.detect_header(open_decompress(fileobj=fh)) != cpio.FORMAT_CPIO_UNKNOWN
|
dissect/target/helpers/fsutil.py
CHANGED
@@ -20,6 +20,13 @@ try:
|
|
20
20
|
except ImportError:
|
21
21
|
HAVE_BZ2 = False
|
22
22
|
|
23
|
+
try:
|
24
|
+
import zstandard
|
25
|
+
|
26
|
+
HAVE_ZSTD = True
|
27
|
+
except ImportError:
|
28
|
+
HAVE_ZSTD = False
|
29
|
+
|
23
30
|
import dissect.target.filesystem as filesystem
|
24
31
|
from dissect.target.exceptions import FileNotFoundError, SymlinkRecursionError
|
25
32
|
from dissect.target.helpers.polypath import (
|
@@ -445,17 +452,22 @@ def resolve_link(
|
|
445
452
|
|
446
453
|
|
447
454
|
def open_decompress(
|
448
|
-
path: TargetPath,
|
455
|
+
path: Optional[TargetPath] = None,
|
449
456
|
mode: str = "rb",
|
457
|
+
*,
|
458
|
+
fileobj: Optional[BinaryIO] = None,
|
450
459
|
encoding: Optional[str] = "UTF-8",
|
451
460
|
errors: Optional[str] = "backslashreplace",
|
452
461
|
newline: Optional[str] = None,
|
453
462
|
) -> Union[BinaryIO, TextIO]:
|
454
|
-
"""Open and decompress a file. Handles gz and
|
463
|
+
"""Open and decompress a file. Handles gz, bz2 and zstd files. Uncompressed files are opened as-is.
|
464
|
+
|
465
|
+
When passing in an already opened ``fileobj``, the mode, encoding, errors and newline arguments are ignored.
|
455
466
|
|
456
467
|
Args:
|
457
468
|
path: The path to the file to open and decompress. It is assumed this path exists.
|
458
469
|
mode: The mode in which to open the file.
|
470
|
+
fileobj: The file-like object to open and decompress. This is mutually exclusive with path.
|
459
471
|
encoding: The decoding for text streams. By default UTF-8 encoding is used.
|
460
472
|
errors: The error handling for text streams. By default we're more lenient and use ``backslashreplace``.
|
461
473
|
newline: How newlines are handled for text streams.
|
@@ -469,7 +481,17 @@ def open_decompress(
|
|
469
481
|
for line in open_decompress(Path("/dir/file.gz"), "rt"):
|
470
482
|
print(line)
|
471
483
|
"""
|
472
|
-
|
484
|
+
if path and fileobj:
|
485
|
+
raise ValueError("path and fileobj are mutually exclusive")
|
486
|
+
|
487
|
+
if not path and not fileobj:
|
488
|
+
raise ValueError("path or fileobj is required")
|
489
|
+
|
490
|
+
if path:
|
491
|
+
file = path.open("rb")
|
492
|
+
else:
|
493
|
+
file = fileobj
|
494
|
+
|
473
495
|
magic = file.read(4)
|
474
496
|
file.seek(0)
|
475
497
|
|
@@ -480,13 +502,22 @@ def open_decompress(
|
|
480
502
|
|
481
503
|
if magic[:2] == b"\x1f\x8b":
|
482
504
|
return gzip.open(file, mode, encoding=encoding, errors=errors, newline=newline)
|
483
|
-
|
484
|
-
|
505
|
+
|
506
|
+
if HAVE_BZ2 and magic[:3] == b"BZh" and 0x31 <= magic[3] <= 0x39:
|
507
|
+
# In a valid bz2 header the 4th byte is in the range b'1' ... b'9'.
|
485
508
|
return bz2.open(file, mode, encoding=encoding, errors=errors, newline=newline)
|
486
|
-
|
509
|
+
|
510
|
+
if HAVE_ZSTD and magic[:4] in [b"\xfd\x2f\xb5\x28", b"\x28\xb5\x2f\xfd"]:
|
511
|
+
# stream_reader is not seekable, so we have to resort to the less
|
512
|
+
# efficient decompressor which returns bytes.
|
513
|
+
return io.BytesIO(zstandard.decompress(file.read()))
|
514
|
+
|
515
|
+
if path:
|
487
516
|
file.close()
|
488
517
|
return path.open(mode, encoding=encoding, errors=errors, newline=newline)
|
489
518
|
|
519
|
+
return file
|
520
|
+
|
490
521
|
|
491
522
|
def reverse_readlines(fh: TextIO, chunk_size: int = 1024 * 1024 * 8) -> Iterator[str]:
|
492
523
|
"""Like iterating over a ``TextIO`` file-like object, but starting from the end of the file.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.16.
|
3
|
+
Version: 3.16.dev25
|
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
|
@@ -1,7 +1,7 @@
|
|
1
1
|
dissect/target/__init__.py,sha256=Oc7ounTgq2hE4nR6YcNabetc7SQA40ldSa35VEdZcQU,63
|
2
2
|
dissect/target/container.py,sha256=9ixufT1_0WhraqttBWwQjG80caToJqvCX8VjFk8d5F0,9307
|
3
3
|
dissect/target/exceptions.py,sha256=VVW_Rq_vQinapz-2mbJ3UkxBEZpb2pE_7JlhMukdtrY,2877
|
4
|
-
dissect/target/filesystem.py,sha256=
|
4
|
+
dissect/target/filesystem.py,sha256=VuWp_nxaG5WI9xvhEjl0M6X37_sVdclzgt3pZvtZ3hE,53944
|
5
5
|
dissect/target/loader.py,sha256=0-LcZNi7S0qsXR7XGtrzxpuCh9BsLcqNR1T15O7SnBM,7257
|
6
6
|
dissect/target/plugin.py,sha256=bwtTPASgJBUHBZ7Nr8eb5eXDOHMWfumduWj7loB0FP0,48605
|
7
7
|
dissect/target/report.py,sha256=06uiP4MbNI8cWMVrC1SasNS-Yg6ptjVjckwj8Yhe0Js,7958
|
@@ -25,6 +25,7 @@ dissect/target/filesystems/ad1.py,sha256=nEPzaaRsb6bL4ItFo0uLdmdLvrmK9BjqHeD3FOp
|
|
25
25
|
dissect/target/filesystems/btrfs.py,sha256=5MBi193ZvclkEQcxDr_sDHfj_FYU_hyYNRL4YqpDu4M,6243
|
26
26
|
dissect/target/filesystems/cb.py,sha256=6LcoJiwsYu1Han31IUzVpZVDTifhTLTx_gLfNpB_p6k,5329
|
27
27
|
dissect/target/filesystems/config.py,sha256=C2JnzBzMqbAjchGFDwURItCeUY7uxkhw1Gen-6cGkAc,11432
|
28
|
+
dissect/target/filesystems/cpio.py,sha256=ssVCjkAtLn2FqmNxeo6U5boyUdSYFxLWfXpytHYGPqs,641
|
28
29
|
dissect/target/filesystems/dir.py,sha256=7GRvojL151_Vk9e3vqgZbWE3I8IL9bU6LUKc_xjk6D4,4050
|
29
30
|
dissect/target/filesystems/exfat.py,sha256=PRkZPUVN5NlgB1VetFtywdNgF6Yj5OBtF5a25t-fFvw,5917
|
30
31
|
dissect/target/filesystems/extfs.py,sha256=9Cke-H0CL-SPd3-xvdAgfc3YA5hYso0sq6hm0C9vGII,4640
|
@@ -46,7 +47,7 @@ dissect/target/helpers/configutil.py,sha256=t_UNvcWuMMT5C1tut_PgTwCnVUodf6RjhfXP
|
|
46
47
|
dissect/target/helpers/cyber.py,sha256=Ki5oSU0GgQxjgC_yWoeieGP7GOY5blQCzNX7vy7Pgas,16782
|
47
48
|
dissect/target/helpers/descriptor_extensions.py,sha256=uT8GwznfDAiIgMM7JKKOY0PXKMv2c0GCqJTCkWFgops,2605
|
48
49
|
dissect/target/helpers/docs.py,sha256=J5U65Y3yOTqxDEZRCdrEmO63XQCeDzOJea1PwPM6Cyc,5146
|
49
|
-
dissect/target/helpers/fsutil.py,sha256=
|
50
|
+
dissect/target/helpers/fsutil.py,sha256=NKwpAq_NlbFDvGGV9ahC5flPda_5jUBDqtF-Ch5ASDs,19543
|
50
51
|
dissect/target/helpers/hashutil.py,sha256=SD24rcV_y0sBEl7M9T-isjm-VzJvCiTN2BoWMqAOAVI,2160
|
51
52
|
dissect/target/helpers/keychain.py,sha256=wYH0sf7eaxP0bZTo80RF_BQMWulCWmIQ8Tzt9K5TSNQ,3611
|
52
53
|
dissect/target/helpers/lazy.py,sha256=823VtmdWsbJyVZvNWopDhQdqq2i1xtj6b8IKfveboKw,1771
|
@@ -330,10 +331,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
|
|
330
331
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
331
332
|
dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
|
332
333
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
333
|
-
dissect.target-3.16.
|
334
|
-
dissect.target-3.16.
|
335
|
-
dissect.target-3.16.
|
336
|
-
dissect.target-3.16.
|
337
|
-
dissect.target-3.16.
|
338
|
-
dissect.target-3.16.
|
339
|
-
dissect.target-3.16.
|
334
|
+
dissect.target-3.16.dev25.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
335
|
+
dissect.target-3.16.dev25.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
336
|
+
dissect.target-3.16.dev25.dist-info/METADATA,sha256=dlfz79OtrmH132ugeqPIQsRDdu-FgcSqIbt0i1AdSgo,11113
|
337
|
+
dissect.target-3.16.dev25.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
338
|
+
dissect.target-3.16.dev25.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
|
339
|
+
dissect.target-3.16.dev25.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
340
|
+
dissect.target-3.16.dev25.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.16.dev24.dist-info → dissect.target-3.16.dev25.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|