dissect.volume 3.12.dev1__tar.gz → 3.12.dev3__tar.gz
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_volume-3.12.dev3/.gitattributes +4 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/PKG-INFO +1 -1
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/ddf/ddf.py +24 -16
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/dm/thin.py +4 -0
- dissect_volume-3.12.dev3/dissect/volume/md/__init__.py +6 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/md/md.py +38 -36
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/raid/raid.py +6 -3
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/raid/stream.py +20 -22
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect.volume.egg-info/PKG-INFO +1 -1
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect.volume.egg-info/SOURCES.txt +2 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/conftest.py +5 -0
- dissect_volume-3.12.dev3/tests/data/dm/dm-thin-empty-data.bin.gz +0 -0
- dissect_volume-3.12.dev3/tests/data/dm/dm-thin-empty-metadata.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_dm.py +21 -1
- dissect_volume-3.12.dev1/.gitattributes +0 -46
- dissect_volume-3.12.dev1/dissect/volume/md/__init__.py +0 -6
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/COPYRIGHT +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/LICENSE +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/MANIFEST.in +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/README.md +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/ddf/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/ddf/c_ddf.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/disk.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/partition.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/schemes/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/schemes/apm.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/schemes/bsd.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/schemes/gpt.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/schemes/mbr.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/dm/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/dm/btree.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/dm/c_dm.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/exceptions.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/ldm.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/lvm/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/lvm/c_lvm2.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/lvm/lvm2.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/lvm/metadata.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/lvm/physical.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/md/c_md.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/raid/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/vss.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect.volume.egg-info/dependency_links.txt +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect.volume.egg-info/requires.txt +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect.volume.egg-info/top_level.txt +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/pyproject.toml +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/setup.cfg +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/__init__.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/apm.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/bsd.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/bsd64.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid0-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid0-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid0-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid0-raid1-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid0-raid1-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid1-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid1-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid10-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid10-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid10-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid10-4.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid4-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid4-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid5-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid5-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid5-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid6-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid6-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid6-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid6-4.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/dm/dm-thin-data.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/dm/dm-thin-metadata.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/gpt.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/gpt_4k.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/gpt_esxi.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/gpt_hybrid.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/gpt_no_name_xff.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/lvm/lvm-mirror-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/lvm/lvm-mirror-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/lvm/lvm-thin.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/lvm/lvm.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/mbr.bin +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-90-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-90-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-90-raid1-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-90-raid1-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-linear-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-linear-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid0-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid0-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid0-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid1-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid1-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid10-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid10-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid4-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid4-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid4-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid5-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid5-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid5-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid6-1.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid6-2.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid6-3.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/md/md-raid6-4.bin.gz +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/docs/Makefile +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/docs/conf.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/docs/index.rst +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_apm.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_bsd.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_ddf.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_gpt.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_lvm.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_mbr.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/test_md.py +0 -0
- {dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dissect.volume
|
|
3
|
-
Version: 3.12.
|
|
3
|
+
Version: 3.12.dev3
|
|
4
4
|
Summary: A Dissect module implementing a parser for different disk volume and partition systems, for example LVM2, GPT and MBR
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
|
@@ -1,43 +1,51 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import io
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import TYPE_CHECKING, BinaryIO
|
|
5
5
|
|
|
6
6
|
from dissect.util import ts
|
|
7
7
|
|
|
8
8
|
from dissect.volume.ddf.c_ddf import DEFAULT_SECTOR_SIZE, c_ddf
|
|
9
9
|
from dissect.volume.exceptions import DDFError
|
|
10
|
-
from dissect.volume.raid.raid import
|
|
10
|
+
from dissect.volume.raid.raid import (
|
|
11
|
+
RAID,
|
|
12
|
+
Configuration,
|
|
13
|
+
DiskMap,
|
|
14
|
+
PhysicalDisk,
|
|
15
|
+
VirtualDisk,
|
|
16
|
+
)
|
|
11
17
|
from dissect.volume.raid.stream import Layout, Level
|
|
12
18
|
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
DDFPhysicalDiskDescriptor = BinaryIO | "DDFPhysicalDisk"
|
|
21
|
+
|
|
13
22
|
DECADE = 3600 * 24 * (365 * 10 + 2)
|
|
14
23
|
|
|
15
24
|
|
|
16
25
|
class DDF(RAID):
|
|
17
|
-
def __init__(
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
fh: list[DDFPhysicalDiskDescriptor] | DDFPhysicalDiskDescriptor,
|
|
29
|
+
sector_size: int = DEFAULT_SECTOR_SIZE,
|
|
30
|
+
):
|
|
18
31
|
fhs = [fh] if not isinstance(fh, list) else fh
|
|
19
|
-
|
|
20
|
-
self.sector_size = sector_size
|
|
32
|
+
physical_disks = [DDFPhysicalDisk(f, sector_size) if not isinstance(f, DDFPhysicalDisk) else f for f in fhs]
|
|
21
33
|
|
|
22
34
|
config_map = {}
|
|
23
|
-
for pd in
|
|
35
|
+
for pd in physical_disks:
|
|
24
36
|
config_map.setdefault(pd.anchor.DDF_Header_GUID, []).append(pd)
|
|
25
37
|
|
|
26
38
|
super().__init__([DDFConfiguration(disks) for disks in config_map.values()])
|
|
27
39
|
|
|
28
40
|
|
|
29
41
|
class DDFConfiguration(Configuration):
|
|
30
|
-
def __init__(self,
|
|
31
|
-
fhs = [fh] if not isinstance(fh, list) else fh
|
|
32
|
-
self.disks = [DDFPhysicalDisk(f, sector_size) if not isinstance(f, DDFPhysicalDisk) else f for f in fhs]
|
|
33
|
-
self.sector_size = sector_size
|
|
34
|
-
|
|
42
|
+
def __init__(self, physical_disks: list[DDFPhysicalDisk]):
|
|
35
43
|
pd_map: dict[int, DDFPhysicalDisk] = {}
|
|
36
44
|
vde_map: dict[bytes, VirtualDiskRecord] = {}
|
|
37
45
|
vdcr_map: dict[bytes, VirtualDiskConfigurationRecord] = {}
|
|
38
46
|
vdcr_uniq: dict[tuple[bytes, int], VirtualDiskConfigurationRecord] = {}
|
|
39
47
|
|
|
40
|
-
for pd in
|
|
48
|
+
for pd in physical_disks:
|
|
41
49
|
pd_map[pd.reference] = pd
|
|
42
50
|
vde_map.update({vde.guid: vde for vde in pd.virtual_disk_records})
|
|
43
51
|
vdcr_map.update({vdcr.guid: vdcr for vdcr in pd.virtual_disk_configuration_records})
|
|
@@ -61,7 +69,7 @@ class DDFConfiguration(Configuration):
|
|
|
61
69
|
i += 1
|
|
62
70
|
|
|
63
71
|
virtual_disks = [DDFVirtualDisk(vdcr_map[guid], vde_map[guid], vd_map[guid]) for guid in vd_map.keys()]
|
|
64
|
-
super().__init__(
|
|
72
|
+
super().__init__(physical_disks, virtual_disks)
|
|
65
73
|
|
|
66
74
|
|
|
67
75
|
class DDFVirtualDisk(VirtualDisk):
|
|
@@ -69,14 +77,14 @@ class DDFVirtualDisk(VirtualDisk):
|
|
|
69
77
|
self,
|
|
70
78
|
vdcr: VirtualDiskConfigurationRecord,
|
|
71
79
|
vdr: VirtualDiskRecord,
|
|
72
|
-
disks:
|
|
80
|
+
disks: DiskMap,
|
|
73
81
|
):
|
|
74
82
|
self.vdcr = vdcr
|
|
75
83
|
self.vdr = vdr
|
|
76
84
|
self.disks = disks
|
|
77
85
|
|
|
78
86
|
if (block_size := self.vdcr.block_size) == 0xFFFF:
|
|
79
|
-
block_size = list(
|
|
87
|
+
block_size = list(disks.values())[0][1].block_size
|
|
80
88
|
|
|
81
89
|
level, layout, num_disks = _convert_raid_layout(
|
|
82
90
|
vdcr.primary_raid_level,
|
|
@@ -218,7 +226,7 @@ class VirtualDiskRecord:
|
|
|
218
226
|
self.state = self.header.VD_State
|
|
219
227
|
self.init_state = self.header.Init_State
|
|
220
228
|
name = self.header.VD_Name.split(b"\x00")[0]
|
|
221
|
-
self.name = name.decode("utf-8") if self.type & 0x02 else name.decode()
|
|
229
|
+
self.name = name.decode(encoding="utf-8") if self.type & 0x02 else name.decode(encoding="ascii")
|
|
222
230
|
|
|
223
231
|
def __repr__(self) -> str:
|
|
224
232
|
return f"<VirtualDiskRecord guid={self.guid} number={self.number} type={self.type:#x} name={self.name!r}>"
|
|
@@ -77,6 +77,10 @@ class ThinDevice(AlignedStream):
|
|
|
77
77
|
while length > 0:
|
|
78
78
|
block_info = data_mapping.lookup([self.device_id, block])
|
|
79
79
|
if block_info is None:
|
|
80
|
+
remaining = length
|
|
81
|
+
if self.size is None or (remaining := self.size - offset) > 0:
|
|
82
|
+
return b"\x00" * min(length, remaining)
|
|
83
|
+
|
|
80
84
|
break
|
|
81
85
|
|
|
82
86
|
block_time = int.from_bytes(block_info, "little")
|
|
@@ -4,7 +4,7 @@ import datetime
|
|
|
4
4
|
import io
|
|
5
5
|
import operator
|
|
6
6
|
import struct
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import TYPE_CHECKING, BinaryIO
|
|
8
8
|
from uuid import UUID
|
|
9
9
|
|
|
10
10
|
from dissect.util import ts
|
|
@@ -13,7 +13,8 @@ from dissect.volume.md.c_md import SECTOR_SIZE, c_md
|
|
|
13
13
|
from dissect.volume.raid.raid import RAID, Configuration, PhysicalDisk, VirtualDisk
|
|
14
14
|
from dissect.volume.raid.stream import Level
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
MDPhysicalDiskDescriptor = BinaryIO | "MDPhysicalDisk"
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class MD(RAID):
|
|
@@ -22,62 +23,63 @@ class MD(RAID):
|
|
|
22
23
|
Use this class to read from a RAID set.
|
|
23
24
|
|
|
24
25
|
Args:
|
|
25
|
-
fh: A single file-like object or :class:`
|
|
26
|
+
fh: A single file-like object or :class:`MDPhysicalDisk`, or a list of multiple belonging to the same RAID set.
|
|
26
27
|
"""
|
|
27
28
|
|
|
28
|
-
def __init__(self, fh:
|
|
29
|
+
def __init__(self, fh: list[MDPhysicalDiskDescriptor] | MDPhysicalDiskDescriptor):
|
|
29
30
|
fhs = [fh] if not isinstance(fh, list) else fh
|
|
30
|
-
|
|
31
|
+
physical_disks = [MDPhysicalDisk(fh) if not isinstance(fh, MDPhysicalDisk) else fh for fh in fhs]
|
|
31
32
|
|
|
32
33
|
config_map = {}
|
|
33
|
-
for
|
|
34
|
-
config_map.setdefault(
|
|
34
|
+
for disk in physical_disks:
|
|
35
|
+
config_map.setdefault(disk.set_uuid, []).append(disk)
|
|
35
36
|
|
|
36
|
-
super().__init__([MDConfiguration(
|
|
37
|
+
super().__init__([MDConfiguration(disks) for disks in config_map.values()])
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
class MDConfiguration(Configuration):
|
|
40
|
-
def __init__(self,
|
|
41
|
-
|
|
41
|
+
def __init__(self, physical_disks: list[MDPhysicalDisk]):
|
|
42
|
+
physical_disks = sorted(physical_disks, key=operator.attrgetter("raid_disk"))
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
raise ValueError("Multiple MD sets detected, supply only the devices of a single set")
|
|
44
|
+
if len({disk.set_uuid for disk in physical_disks}) != 1:
|
|
45
|
+
raise ValueError("Multiple MD sets detected, supply only the disks of a single set")
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
super().__init__(
|
|
47
|
+
virtual_disks = [MDVirtualDisk(physical_disks)]
|
|
48
|
+
super().__init__(physical_disks, virtual_disks)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
class
|
|
52
|
-
def __init__(self,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
disks = {dev.raid_disk: (0, dev) for dev in self.configuration.devices if dev.raid_disk is not None}
|
|
51
|
+
class MDVirtualDisk(VirtualDisk):
|
|
52
|
+
def __init__(self, physical_disks: list[MDPhysicalDisk]):
|
|
53
|
+
reference_disk = sorted(physical_disks, key=operator.attrgetter("events"), reverse=True)[0]
|
|
54
|
+
disk_map = {disk.raid_disk: (0, disk) for disk in physical_disks if disk.raid_disk is not None}
|
|
56
55
|
|
|
57
|
-
if
|
|
58
|
-
size = sum(disk.size for _, disk in
|
|
59
|
-
elif
|
|
56
|
+
if reference_disk.level == Level.LINEAR:
|
|
57
|
+
size = sum(disk.size for _, disk in disk_map.values())
|
|
58
|
+
elif reference_disk.level == Level.RAID0:
|
|
60
59
|
size = 0
|
|
61
|
-
for _, disk in
|
|
62
|
-
size += disk.size & ~(
|
|
63
|
-
elif
|
|
64
|
-
size =
|
|
60
|
+
for _, disk in disk_map.values():
|
|
61
|
+
size += disk.size & ~(reference_disk.chunk_size - 1)
|
|
62
|
+
elif reference_disk.level in (Level.RAID1, Level.RAID4, Level.RAID5, Level.RAID6, Level.RAID10):
|
|
63
|
+
size = reference_disk.sb.size * SECTOR_SIZE
|
|
65
64
|
else:
|
|
66
|
-
raise ValueError(
|
|
65
|
+
raise ValueError(
|
|
66
|
+
"Invalid MD RAID configuration: No valid RAID level found for the reference disk, found: %d",
|
|
67
|
+
reference_disk.level,
|
|
68
|
+
)
|
|
67
69
|
|
|
68
70
|
super().__init__(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
reference_disk.set_name,
|
|
72
|
+
reference_disk.set_uuid,
|
|
71
73
|
size,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
reference_disk.level,
|
|
75
|
+
reference_disk.layout,
|
|
76
|
+
reference_disk.chunk_size,
|
|
77
|
+
reference_disk.raid_disks,
|
|
78
|
+
disk_map,
|
|
77
79
|
)
|
|
78
80
|
|
|
79
81
|
|
|
80
|
-
class
|
|
82
|
+
class MDPhysicalDisk(PhysicalDisk):
|
|
81
83
|
"""Parse metadata from an MD device.
|
|
82
84
|
|
|
83
85
|
Supports 0.90 and 1.x metadata.
|
|
@@ -12,6 +12,9 @@ from dissect.volume.raid.stream import (
|
|
|
12
12
|
RAID456Stream,
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
+
DiskMap = dict[int, tuple[int, "PhysicalDisk"]]
|
|
16
|
+
"""A dict of the structure: {disk_idx: {data_offset: PhysicalDisk}}"""
|
|
17
|
+
|
|
15
18
|
|
|
16
19
|
class RAID:
|
|
17
20
|
def __init__(self, configurations: list[Configuration]):
|
|
@@ -45,7 +48,7 @@ class VirtualDisk:
|
|
|
45
48
|
layout: int,
|
|
46
49
|
stripe_size: int,
|
|
47
50
|
num_disks: int,
|
|
48
|
-
|
|
51
|
+
disk_map: DiskMap,
|
|
49
52
|
):
|
|
50
53
|
self.name = name
|
|
51
54
|
self.uuid = uuid
|
|
@@ -54,7 +57,7 @@ class VirtualDisk:
|
|
|
54
57
|
self.layout = layout
|
|
55
58
|
self.stripe_size = stripe_size
|
|
56
59
|
self.num_disks = num_disks
|
|
57
|
-
self.
|
|
60
|
+
self.disk_map = disk_map
|
|
58
61
|
|
|
59
62
|
def open(self) -> BinaryIO:
|
|
60
63
|
"""Return a file-like object of the RAID volume in this set."""
|
|
@@ -64,7 +67,7 @@ class VirtualDisk:
|
|
|
64
67
|
return RAID0Stream(self)
|
|
65
68
|
elif self.level == Level.RAID1:
|
|
66
69
|
# Don't really care which mirror to read from, so just open the first disk
|
|
67
|
-
return self.
|
|
70
|
+
return self.disk_map[0][1].open()
|
|
68
71
|
elif self.level in (Level.RAID4, Level.RAID5, Level.RAID6):
|
|
69
72
|
return RAID456Stream(self)
|
|
70
73
|
elif self.level == Level.RAID10:
|
|
@@ -8,7 +8,7 @@ from dissect.util.stream import AlignedStream, MappingStream
|
|
|
8
8
|
from dissect.volume.exceptions import RAIDError
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
-
from dissect.volume.raid.raid import PhysicalDisk, VirtualDisk
|
|
11
|
+
from dissect.volume.raid.raid import DiskMap, PhysicalDisk, VirtualDisk
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Level(IntEnum):
|
|
@@ -54,13 +54,13 @@ class LinearStream(MappingStream):
|
|
|
54
54
|
def __init__(self, virtual_disk: VirtualDisk):
|
|
55
55
|
super().__init__()
|
|
56
56
|
self.virtual_disk = virtual_disk
|
|
57
|
+
self.disk_map: DiskMap = dict(sorted(virtual_disk.disk_map.items()))
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
if len(physical_disks) != virtual_disk.num_disks:
|
|
59
|
+
if len(self.disk_map) != virtual_disk.num_disks:
|
|
60
60
|
raise RAIDError(f"Missing disks in linear RAID set {virtual_disk.uuid} ({virtual_disk.name})")
|
|
61
61
|
|
|
62
62
|
offset = 0
|
|
63
|
-
for disk_offset, disk in
|
|
63
|
+
for disk_offset, disk in self.disk_map.values():
|
|
64
64
|
self.add(offset, disk.size, disk.open(), disk_offset)
|
|
65
65
|
offset += disk.size
|
|
66
66
|
|
|
@@ -68,7 +68,7 @@ class LinearStream(MappingStream):
|
|
|
68
68
|
class Zone(NamedTuple):
|
|
69
69
|
zone_end: int
|
|
70
70
|
dev_start: int
|
|
71
|
-
devices:
|
|
71
|
+
devices: DiskMap
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
class RAID0Stream(AlignedStream):
|
|
@@ -76,27 +76,25 @@ class RAID0Stream(AlignedStream):
|
|
|
76
76
|
|
|
77
77
|
def __init__(self, virtual_disk: VirtualDisk):
|
|
78
78
|
self.virtual_disk = virtual_disk
|
|
79
|
+
self.disk_map = dict(sorted(self.virtual_disk.disk_map.items()))
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
if len(disks) != virtual_disk.num_disks:
|
|
81
|
+
if len(self.disk_map) != virtual_disk.num_disks:
|
|
82
82
|
raise RAIDError(f"Missing disks in RAID0 set {virtual_disk.uuid} ({virtual_disk.name})")
|
|
83
83
|
|
|
84
84
|
# Determine how many strip zones we need to construct
|
|
85
85
|
# If a RAID0 set consists of devices with different sizes, additional strip zones
|
|
86
86
|
# may exist on the larger devices but not on the smaller ones
|
|
87
87
|
# Reference: create_strip_zones
|
|
88
|
-
|
|
89
|
-
rounded_sizes = {}
|
|
90
|
-
|
|
88
|
+
rounded_sizes: dict[PhysicalDisk, int] = {}
|
|
91
89
|
stripe_size = virtual_disk.stripe_size
|
|
92
90
|
num_strip_zones = 0
|
|
93
|
-
for idx1, (_, dev1) in
|
|
91
|
+
for idx1, (_, dev1) in self.disk_map.items():
|
|
94
92
|
rounded_sizes[dev1] = (dev1.size // stripe_size) * stripe_size
|
|
95
93
|
|
|
96
94
|
has_same_size = False
|
|
97
95
|
# Check if dev1 is unequal in size to the sizes of any of the previous devices
|
|
98
96
|
# If so, this means an extra strip zone is present
|
|
99
|
-
for idx2, (_, dev2) in
|
|
97
|
+
for idx2, (_, dev2) in self.disk_map.items():
|
|
100
98
|
if idx1 == idx2:
|
|
101
99
|
break
|
|
102
100
|
|
|
@@ -109,25 +107,25 @@ class RAID0Stream(AlignedStream):
|
|
|
109
107
|
|
|
110
108
|
# Determine the smallest device
|
|
111
109
|
smallest = None
|
|
112
|
-
for _, dev in
|
|
110
|
+
for _, dev in self.disk_map.values():
|
|
113
111
|
if not smallest or rounded_sizes[dev] < rounded_sizes[smallest]:
|
|
114
112
|
smallest = dev
|
|
115
113
|
|
|
116
114
|
# Construct the strip zones
|
|
117
|
-
zones = [Zone(rounded_sizes[smallest] * len(
|
|
115
|
+
zones = [Zone(rounded_sizes[smallest] * len(self.disk_map), 0, self.disk_map)]
|
|
118
116
|
|
|
119
117
|
cur_zone_end = zones[0].zone_end
|
|
120
118
|
for _ in range(1, num_strip_zones):
|
|
121
|
-
zone_devices =
|
|
119
|
+
zone_devices = {}
|
|
122
120
|
dev_start = rounded_sizes[smallest]
|
|
123
121
|
smallest = None
|
|
124
122
|
|
|
125
123
|
# Look for the next smallest device, that is: the smallest device that is larger than the "dev_start" device
|
|
126
|
-
for
|
|
124
|
+
for disk_idx, (data_offset, dev) in self.disk_map.items():
|
|
127
125
|
if rounded_sizes[dev] <= dev_start:
|
|
128
126
|
continue
|
|
129
127
|
|
|
130
|
-
zone_devices
|
|
128
|
+
zone_devices[disk_idx] = (data_offset, dev)
|
|
131
129
|
if not smallest or rounded_sizes[dev] < rounded_sizes[smallest]:
|
|
132
130
|
smallest = dev
|
|
133
131
|
|
|
@@ -192,8 +190,8 @@ class RAID456Stream(AlignedStream):
|
|
|
192
190
|
self.algorithm = self.virtual_disk.layout
|
|
193
191
|
self.max_degraded = 2 if self.level == 6 else 1
|
|
194
192
|
|
|
195
|
-
self.
|
|
196
|
-
if len(self.
|
|
193
|
+
self.disk_map = self.virtual_disk.disk_map
|
|
194
|
+
if len(self.disk_map) < self.virtual_disk.num_disks - self.max_degraded:
|
|
197
195
|
raise RAIDError(f"Missing disks in RAID{self.level} set {virtual_disk.uuid} ({virtual_disk.name})")
|
|
198
196
|
|
|
199
197
|
super().__init__(self.virtual_disk.size, self.virtual_disk.stripe_size)
|
|
@@ -362,7 +360,7 @@ class RAID456Stream(AlignedStream):
|
|
|
362
360
|
while length:
|
|
363
361
|
stripe, offset_in_stripe, dd_idx, pd_idx, qd_idx, ddf_layout = self._get_stripe_read_info(offset)
|
|
364
362
|
offset_in_device = stripe * stripe_size + offset_in_stripe
|
|
365
|
-
dd_start, dd_dev = self.
|
|
363
|
+
dd_start, dd_dev = self.disk_map[dd_idx]
|
|
366
364
|
|
|
367
365
|
stripe_remaining = stripe_size - offset_in_stripe
|
|
368
366
|
read_length = min(length, stripe_remaining)
|
|
@@ -383,7 +381,7 @@ class RAID10Stream(AlignedStream):
|
|
|
383
381
|
def __init__(self, virtual_disk: VirtualDisk):
|
|
384
382
|
self.virtual_disk = virtual_disk
|
|
385
383
|
self.raid_disks = self.virtual_disk.num_disks
|
|
386
|
-
self.
|
|
384
|
+
self.disk_map = virtual_disk.disk_map
|
|
387
385
|
|
|
388
386
|
# Reference: setup_geo
|
|
389
387
|
layout = virtual_disk.layout
|
|
@@ -420,7 +418,7 @@ class RAID10Stream(AlignedStream):
|
|
|
420
418
|
|
|
421
419
|
if self.far_offset:
|
|
422
420
|
stripe *= self.far_copies
|
|
423
|
-
device_start, device = self.
|
|
421
|
+
device_start, device = self.disk_map[dev]
|
|
424
422
|
|
|
425
423
|
stripe_remaining = stripe_size - offset_in_stripe
|
|
426
424
|
read_length = min(length, stripe_remaining)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dissect.volume
|
|
3
|
-
Version: 3.12.
|
|
3
|
+
Version: 3.12.dev3
|
|
4
4
|
Summary: A Dissect module implementing a parser for different disk volume and partition systems, for example LVM2, GPT and MBR
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
|
@@ -80,6 +80,8 @@ tests/data/ddf/ddf-raid6-2.bin.gz
|
|
|
80
80
|
tests/data/ddf/ddf-raid6-3.bin.gz
|
|
81
81
|
tests/data/ddf/ddf-raid6-4.bin.gz
|
|
82
82
|
tests/data/dm/dm-thin-data.bin.gz
|
|
83
|
+
tests/data/dm/dm-thin-empty-data.bin.gz
|
|
84
|
+
tests/data/dm/dm-thin-empty-metadata.bin.gz
|
|
83
85
|
tests/data/dm/dm-thin-metadata.bin.gz
|
|
84
86
|
tests/data/lvm/lvm-mirror-1.bin.gz
|
|
85
87
|
tests/data/lvm/lvm-mirror-2.bin.gz
|
|
@@ -90,6 +90,11 @@ def dm_thin() -> Iterator[list[BinaryIO]]:
|
|
|
90
90
|
yield from open_files_gz(["data/dm/dm-thin-metadata.bin.gz", "data/dm/dm-thin-data.bin.gz"])
|
|
91
91
|
|
|
92
92
|
|
|
93
|
+
@pytest.fixture
|
|
94
|
+
def dm_thin_empty() -> Iterator[list[BinaryIO]]:
|
|
95
|
+
yield from open_files_gz(["data/dm/dm-thin-empty-metadata.bin.gz", "data/dm/dm-thin-empty-data.bin.gz"])
|
|
96
|
+
|
|
97
|
+
|
|
93
98
|
@pytest.fixture
|
|
94
99
|
def md_linear() -> Iterator[list[BinaryIO]]:
|
|
95
100
|
yield from open_files_gz(["data/md/md-linear-1.bin.gz", "data/md/md-linear-2.bin.gz"])
|
|
Binary file
|
|
Binary file
|
|
@@ -22,4 +22,24 @@ def test_dm_thin(dm_thin: list[BinaryIO]) -> None:
|
|
|
22
22
|
|
|
23
23
|
thin_no_size = pool.open(0)
|
|
24
24
|
thin_no_size.seek((1024 * 1024 * 2) - 512)
|
|
25
|
-
assert len(thin_no_size.read(1024)) ==
|
|
25
|
+
assert len(thin_no_size.read(1024)) == 1024
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_dm_thin_empty(dm_thin_empty: list[BinaryIO]) -> None:
|
|
29
|
+
metadata_fh, data_fh = dm_thin_empty
|
|
30
|
+
pool = ThinPool(metadata_fh, data_fh)
|
|
31
|
+
|
|
32
|
+
dev = pool.open(0)
|
|
33
|
+
|
|
34
|
+
assert dev.read(512) == b"\x00" * 512
|
|
35
|
+
|
|
36
|
+
dev.seek(512 * 1024)
|
|
37
|
+
assert dev.read(512) != b"\x00" * 512
|
|
38
|
+
|
|
39
|
+
# Far beyond the file boundary
|
|
40
|
+
dev.seek(2**64)
|
|
41
|
+
assert dev.read(512) == b"\x00" * 512
|
|
42
|
+
|
|
43
|
+
dev = pool.open(0, 512)
|
|
44
|
+
assert dev.read(512) == b"\x00" * 512
|
|
45
|
+
assert dev.read(512) == b""
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
tests/data/dm/dm-thin-data.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
2
|
-
tests/data/dm/dm-thin-metadata.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
3
|
-
tests/data/md/md-linear-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
4
|
-
tests/data/md/md-linear-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
5
|
-
tests/data/md/md-raid0-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
6
|
-
tests/data/md/md-raid0-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
7
|
-
tests/data/md/md-raid0-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
8
|
-
tests/data/md/md-raid1-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
9
|
-
tests/data/md/md-raid1-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
10
|
-
tests/data/md/md-raid4-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
11
|
-
tests/data/md/md-raid4-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
12
|
-
tests/data/md/md-raid4-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
13
|
-
tests/data/md/md-raid5-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
14
|
-
tests/data/md/md-raid5-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
15
|
-
tests/data/md/md-raid5-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
16
|
-
tests/data/md/md-raid6-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
17
|
-
tests/data/md/md-raid6-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
18
|
-
tests/data/md/md-raid6-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
19
|
-
tests/data/md/md-raid6-4.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
20
|
-
tests/data/md/md-raid10-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
21
|
-
tests/data/md/md-raid10-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
22
|
-
tests/data/md/md-90-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
23
|
-
tests/data/md/md-90-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
24
|
-
tests/data/md/md-90-raid1-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
25
|
-
tests/data/md/md-90-raid1-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
26
|
-
tests/data/ddf/ddf-raid0-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
27
|
-
tests/data/ddf/ddf-raid0-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
28
|
-
tests/data/ddf/ddf-raid0-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
29
|
-
tests/data/ddf/ddf-raid0-raid1-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
30
|
-
tests/data/ddf/ddf-raid0-raid1-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
31
|
-
tests/data/ddf/ddf-raid1-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
32
|
-
tests/data/ddf/ddf-raid1-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
33
|
-
tests/data/ddf/ddf-raid4-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
34
|
-
tests/data/ddf/ddf-raid4-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
35
|
-
tests/data/ddf/ddf-raid5-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
36
|
-
tests/data/ddf/ddf-raid5-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
37
|
-
tests/data/ddf/ddf-raid5-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
38
|
-
tests/data/ddf/ddf-raid6-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
39
|
-
tests/data/ddf/ddf-raid6-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
40
|
-
tests/data/ddf/ddf-raid6-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
41
|
-
tests/data/ddf/ddf-raid6-4.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
42
|
-
tests/data/ddf/ddf-raid10-1.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
43
|
-
tests/data/ddf/ddf-raid10-2.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
44
|
-
tests/data/ddf/ddf-raid10-3.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
45
|
-
tests/data/ddf/ddf-raid10-4.bin.gz filter=lfs diff=lfs merge=lfs -text
|
|
46
|
-
tests/data/lvm/* filter=lfs diff=lfs merge=lfs -text
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect/volume/disk/schemes/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/dissect.volume.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid0-raid1-1.bin.gz
RENAMED
|
File without changes
|
{dissect_volume-3.12.dev1 → dissect_volume-3.12.dev3}/tests/data/ddf/ddf-raid0-raid1-2.bin.gz
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|