dissect.hypervisor 3.15.dev2__py3-none-any.whl → 3.16.dev1__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,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import ctypes
2
4
  import io
3
5
  import logging
@@ -5,6 +7,7 @@ import os
5
7
  import textwrap
6
8
  import zlib
7
9
  from bisect import bisect_right
10
+ from dataclasses import dataclass
8
11
  from functools import lru_cache
9
12
  from pathlib import Path
10
13
 
@@ -59,13 +62,13 @@ class VMDK(AlignedStream):
59
62
  if self.descriptor.attr["parentCID"] != "ffffffff":
60
63
  self.parent = open_parent(path.parent, self.descriptor.attr["parentFileNameHint"])
61
64
 
62
- for _, size, extent_type, filename in self.descriptor.extents:
63
- if extent_type in ["SPARSE", "VMFSSPARSE", "SESPARSE"]:
64
- sdisk_fh = path.with_name(filename).open("rb")
65
+ for extent in self.descriptor.extents:
66
+ if extent.type in ["SPARSE", "VMFSSPARSE", "SESPARSE"]:
67
+ sdisk_fh = path.with_name(extent.filename).open("rb")
65
68
  self.disks.append(SparseDisk(sdisk_fh, parent=self.parent))
66
- elif extent_type in ["VMFS", "FLAT"]:
67
- rdisk_fh = path.with_name(filename).open("rb")
68
- self.disks.append(RawDisk(rdisk_fh, size * SECTOR_SIZE))
69
+ elif extent.type in ["VMFS", "FLAT"]:
70
+ rdisk_fh = path.with_name(extent.filename).open("rb")
71
+ self.disks.append(RawDisk(rdisk_fh, extent.sectors * SECTOR_SIZE))
69
72
 
70
73
  elif magic in (COWD_MAGIC, VMDK_MAGIC, SESPARSE_MAGIC):
71
74
  sparse_disk = SparseDisk(fh)
@@ -398,8 +401,37 @@ class SparseExtentHeader:
398
401
  return getattr(self.hdr, attr)
399
402
 
400
403
 
404
+ @dataclass
405
+ class ExtentDescriptor:
406
+ access_mode: str
407
+ sectors: int
408
+ type: str
409
+ filename: str | None = None
410
+ start_sector: int | None = None
411
+ partition_uuid: str | None = None
412
+ device_identifier: str | None = None
413
+
414
+ def __post_init__(self) -> None:
415
+ self._raw = " ".join(map(str, [v for v in self.__dict__.values() if v is not None]))
416
+ self.sectors = int(self.sectors)
417
+
418
+ if self.filename:
419
+ self.filename = self.filename.strip('"')
420
+
421
+ if self.start_sector:
422
+ self.start_sector = int(self.start_sector)
423
+
424
+ def __repr__(self) -> str:
425
+ return f"<ExtentDescriptor {self._raw}>"
426
+
427
+ def __str__(self) -> str:
428
+ return self._raw
429
+
430
+
401
431
  class DiskDescriptor:
402
- def __init__(self, attr, extents, disk_db, sectors, raw_config=None):
432
+ def __init__(
433
+ self, attr: dict, extents: list[ExtentDescriptor], disk_db: dict, sectors: int, raw_config: str | None = None
434
+ ):
403
435
  self.attr = attr
404
436
  self.extents = extents
405
437
  self.ddb = disk_db
@@ -407,9 +439,15 @@ class DiskDescriptor:
407
439
  self.raw = raw_config
408
440
 
409
441
  @classmethod
410
- def parse(cls, vmdk_config):
442
+ def parse(cls, vmdk_config: str) -> DiskDescriptor:
443
+ """Return :class:`DiskDescriptor` based on the provided ``vmdk_config``.
444
+
445
+ Resources:
446
+ - https://github.com/libyal/libvmdk/blob/main/documentation/VMWare%20Virtual%20Disk%20Format%20(VMDK).asciidoc
447
+ """ # noqa: E501
448
+
411
449
  descriptor_settings = {}
412
- extents = []
450
+ extents: list[ExtentDescriptor] = []
413
451
  disk_db = {}
414
452
  sectors = 0
415
453
 
@@ -420,11 +458,16 @@ class DiskDescriptor:
420
458
  continue
421
459
 
422
460
  if line.startswith("RW ") or line.startswith("RDONLY ") or line.startswith("NOACCESS "):
423
- access_type, size, extent_type, filename = line.split(" ", 3)
424
- filename = filename.strip('"')
425
- size = int(size)
426
- sectors += size
427
- extents.append([access_type, size, extent_type, filename])
461
+ # Extent descriptors can have up to seven values according to libvmdk documentation.
462
+ parts = line.split(" ", maxsplit=6)
463
+
464
+ if len(parts) < 3:
465
+ log.warning("Unexpected ExtentDescriptor format in vmdk config: %s, ignoring", line)
466
+ continue
467
+
468
+ extent = ExtentDescriptor(*parts)
469
+ sectors += extent.sectors
470
+ extents.append(extent)
428
471
  continue
429
472
 
430
473
  setting, _, value = line.partition("=")
@@ -438,35 +481,33 @@ class DiskDescriptor:
438
481
 
439
482
  return cls(descriptor_settings, extents, disk_db, sectors, vmdk_config)
440
483
 
441
- def __str__(self):
442
- str_template = """\
443
- # Disk DescriptorFile
444
- version=1
445
- {}
484
+ def __str__(self) -> str:
485
+ str_template = textwrap.dedent(
486
+ """\
487
+ # Disk DescriptorFile
488
+ version=1
489
+ {}
490
+
491
+ # Extent Description
492
+ {}
446
493
 
447
- # Extent Description
448
- {}
494
+ # The Disk Data Base
495
+ #DDB
449
496
 
450
- # The Disk Data Base
451
- #DDB
497
+ {}"""
498
+ )
452
499
 
453
- {}"""
454
- str_template = textwrap.dedent(str_template)
455
500
  descriptor_settings = []
456
501
  for setting, value in self.attr.items():
457
- if setting == "version":
458
- continue
459
- descriptor_settings.append("{}={}".format(setting, value))
502
+ if setting != "version":
503
+ descriptor_settings.append(f"{setting}={value}")
460
504
  descriptor_settings = "\n".join(descriptor_settings)
461
505
 
462
- extents = []
463
- for access_type, size, extent_type, filename in self.extents:
464
- extents.append('{} {} {} "{}"'.format(access_type, size, extent_type, filename))
465
- extents = "\n".join(extents)
506
+ extents = "\n".join(map(str, self.extents))
466
507
 
467
508
  disk_db = []
468
509
  for setting, value in self.ddb.items():
469
- disk_db.append('{} = "{}"'.format(setting, value))
510
+ disk_db.append(f'{setting} = "{value}"')
470
511
  disk_db = "\n".join(disk_db)
471
512
 
472
513
  return str_template.format(descriptor_settings, extents, disk_db)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.hypervisor
3
- Version: 3.15.dev2
3
+ Version: 3.16.dev1
4
4
  Summary: A Dissect module implementing parsers for various hypervisor disk, backup and configuration files
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Affero General Public License v3
@@ -23,17 +23,17 @@ dissect/hypervisor/disk/qcow2.py,sha256=K4zstjte7SxX2psSbAj4YqwGeplfIvfbq5ScP4mz
23
23
  dissect/hypervisor/disk/vdi.py,sha256=_kX7ZGOVo_98ckMaiaDEmw4VjNgM57cY4YUSYrk2JGs,1851
24
24
  dissect/hypervisor/disk/vhd.py,sha256=OqSdEO2NGMI5DjgxWFbtZp8bPjSon7moMJn_5152MbI,3660
25
25
  dissect/hypervisor/disk/vhdx.py,sha256=FVGTY5mUKFb7oRNKNiLGd5ngGfaGvERtFCGhAlyZD_k,12631
26
- dissect/hypervisor/disk/vmdk.py,sha256=KSz_76X_QcInImHNGfCJdN6nF4TmUZ7vqsbZtuUMgbg,18126
26
+ dissect/hypervisor/disk/vmdk.py,sha256=nXDWHziwbN1dxD-ehasuFG98mmhrf1Y9rNil0nAcUtI,19104
27
27
  dissect/hypervisor/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  dissect/hypervisor/tools/envelope.py,sha256=6_RLtKmFnZ69fx8HlvFgsjDjNrfnXD73dgszpG1mYQE,967
29
29
  dissect/hypervisor/tools/vma.py,sha256=N8x4Yh45BM5MweLSriwhAfSegbjw_Ko4i2yayMWF3rw,5422
30
30
  dissect/hypervisor/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  dissect/hypervisor/util/envelope.py,sha256=6nEJfgsxj696qxaLOQ2k5MrVWA2uLkbB5zxxRAvboF4,10405
32
32
  dissect/hypervisor/util/vmtar.py,sha256=oNJ-qTvQVOl7al_vExpg_T4LnGyE72O9hjOmQBiTKSA,1469
33
- dissect.hypervisor-3.15.dev2.dist-info/COPYRIGHT,sha256=EOOoIwk_inOMUD4c1ylpzMtYLjGzmc-MLEVAEdLLr20,305
34
- dissect.hypervisor-3.15.dev2.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
35
- dissect.hypervisor-3.15.dev2.dist-info/METADATA,sha256=UUeKTwLZFjF5Ln7VM_rH0CtZyhceWZKIRVdMIkzXils,3458
36
- dissect.hypervisor-3.15.dev2.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
37
- dissect.hypervisor-3.15.dev2.dist-info/entry_points.txt,sha256=qwOrIPRV4bYsKo2sAZznUqegFTMu1sm7ld-o7w_h_5U,124
38
- dissect.hypervisor-3.15.dev2.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
39
- dissect.hypervisor-3.15.dev2.dist-info/RECORD,,
33
+ dissect.hypervisor-3.16.dev1.dist-info/COPYRIGHT,sha256=EOOoIwk_inOMUD4c1ylpzMtYLjGzmc-MLEVAEdLLr20,305
34
+ dissect.hypervisor-3.16.dev1.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
35
+ dissect.hypervisor-3.16.dev1.dist-info/METADATA,sha256=QOBhT6Hp2GKbf6I4utzIYJIIxeu0ZKLCshWUlIeCFqw,3458
36
+ dissect.hypervisor-3.16.dev1.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
37
+ dissect.hypervisor-3.16.dev1.dist-info/entry_points.txt,sha256=qwOrIPRV4bYsKo2sAZznUqegFTMu1sm7ld-o7w_h_5U,124
38
+ dissect.hypervisor-3.16.dev1.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
39
+ dissect.hypervisor-3.16.dev1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.2)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5