dissect.hypervisor 3.15.dev2__tar.gz → 3.16.dev1__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.
Files changed (91) hide show
  1. {dissect_hypervisor-3.15.dev2/dissect.hypervisor.egg-info → dissect_hypervisor-3.16.dev1}/PKG-INFO +1 -1
  2. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/vmdk.py +74 -33
  3. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1/dissect.hypervisor.egg-info}/PKG-INFO +1 -1
  4. dissect_hypervisor-3.16.dev1/tests/test_vmdk.py +93 -0
  5. dissect_hypervisor-3.15.dev2/tests/test_vmdk.py +0 -20
  6. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/COPYRIGHT +0 -0
  7. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/LICENSE +0 -0
  8. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/MANIFEST.in +0 -0
  9. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/README.md +0 -0
  10. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/__init__.py +0 -0
  11. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/backup/__init__.py +0 -0
  12. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/backup/c_vma.py +0 -0
  13. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/backup/vma.py +0 -0
  14. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/backup/xva.py +0 -0
  15. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/descriptor/__init__.py +0 -0
  16. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/descriptor/c_hyperv.py +0 -0
  17. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/descriptor/hyperv.py +0 -0
  18. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/descriptor/ovf.py +0 -0
  19. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/descriptor/pvs.py +0 -0
  20. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/descriptor/vbox.py +0 -0
  21. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/descriptor/vmx.py +0 -0
  22. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/__init__.py +0 -0
  23. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/c_hdd.py +0 -0
  24. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/c_qcow2.py +0 -0
  25. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/c_vdi.py +0 -0
  26. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/c_vhd.py +0 -0
  27. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/c_vhdx.py +0 -0
  28. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/c_vmdk.py +0 -0
  29. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/hdd.py +0 -0
  30. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/qcow2.py +0 -0
  31. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/vdi.py +0 -0
  32. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/vhd.py +0 -0
  33. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/disk/vhdx.py +0 -0
  34. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/exceptions.py +0 -0
  35. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/tools/__init__.py +0 -0
  36. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/tools/envelope.py +0 -0
  37. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/tools/vma.py +0 -0
  38. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/util/__init__.py +0 -0
  39. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/util/envelope.py +0 -0
  40. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect/hypervisor/util/vmtar.py +0 -0
  41. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect.hypervisor.egg-info/SOURCES.txt +0 -0
  42. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect.hypervisor.egg-info/dependency_links.txt +0 -0
  43. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect.hypervisor.egg-info/entry_points.txt +0 -0
  44. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect.hypervisor.egg-info/requires.txt +0 -0
  45. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/dissect.hypervisor.egg-info/top_level.txt +0 -0
  46. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/pyproject.toml +0 -0
  47. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/setup.cfg +0 -0
  48. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/__init__.py +0 -0
  49. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/conftest.py +0 -0
  50. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/differencing.avhdx.gz +0 -0
  51. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/dynamic.vhd.gz +0 -0
  52. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/dynamic.vhdx.gz +0 -0
  53. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/encrypted.vmx +0 -0
  54. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/encryption.info +0 -0
  55. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/expanding.hdd/DiskDescriptor.xml +0 -0
  56. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/expanding.hdd/expanding.hdd +0 -0
  57. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/expanding.hdd/expanding.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  58. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/fixed.vhd.gz +0 -0
  59. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/fixed.vhdx.gz +0 -0
  60. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/local.tgz.ve +0 -0
  61. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/plain.hdd/DiskDescriptor.xml +0 -0
  62. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/plain.hdd/plain.hdd +0 -0
  63. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/plain.hdd/plain.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  64. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/sesparse.vmdk.gz +0 -0
  65. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/DiskDescriptor.xml +0 -0
  66. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/split.hdd +0 -0
  67. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/split.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  68. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/split.hdd.1.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  69. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/split.hdd.2.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  70. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/split.hdd.3.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  71. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/split.hdd.4.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  72. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/split.hdd/split.hdd.5.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds.gz +0 -0
  73. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/test.VMRS +0 -0
  74. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/test.vgz +0 -0
  75. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/test.vma.gz +0 -0
  76. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/data/test.vmcx +0 -0
  77. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/docs/Makefile +0 -0
  78. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/docs/conf.py +0 -0
  79. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/docs/index.rst +0 -0
  80. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_envelope.py +0 -0
  81. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_hdd.py +0 -0
  82. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_hyperv.py +0 -0
  83. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_ovf.py +0 -0
  84. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_pvs.py +0 -0
  85. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_vbox.py +0 -0
  86. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_vhd.py +0 -0
  87. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_vhdx.py +0 -0
  88. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_vma.py +0 -0
  89. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_vmtar.py +0 -0
  90. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tests/test_vmx.py +0 -0
  91. {dissect_hypervisor-3.15.dev2 → dissect_hypervisor-3.16.dev1}/tox.ini +0 -0
@@ -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
@@ -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
@@ -0,0 +1,93 @@
1
+ import pytest
2
+
3
+ from dissect.hypervisor.disk.c_vmdk import c_vmdk
4
+ from dissect.hypervisor.disk.vmdk import VMDK, DiskDescriptor, ExtentDescriptor
5
+
6
+
7
+ def test_vmdk_sesparse(sesparse_vmdk):
8
+ vmdk = VMDK(sesparse_vmdk)
9
+
10
+ disk = vmdk.disks[0]
11
+
12
+ assert disk.is_sesparse
13
+ assert disk._grain_directory_size == 0x20000
14
+ assert disk._grain_table_size == 0x1000
15
+ assert disk._grain_entry_type == c_vmdk.uint64
16
+ assert disk._grain_directory[0] == 0x1000000000000000
17
+
18
+ header = disk.header
19
+ assert header.magic == c_vmdk.SESPARSE_CONST_HEADER_MAGIC
20
+ assert header.version == 0x200000001
21
+
22
+ assert vmdk.read(0x1000000) == b"a" * 0x1000000
23
+
24
+
25
+ @pytest.mark.parametrize(
26
+ "extent_description, expected_extents",
27
+ [
28
+ (
29
+ 'RW 123456789 SPARSE "disk.vmdk"',
30
+ [
31
+ ExtentDescriptor(
32
+ access_mode="RW",
33
+ sectors=123456789,
34
+ type="SPARSE",
35
+ filename="disk.vmdk",
36
+ partition_uuid=None,
37
+ device_identifier=None,
38
+ ),
39
+ ],
40
+ ),
41
+ (
42
+ 'RW 123456789 FLAT "disk-flat.vmdk" 0',
43
+ [
44
+ ExtentDescriptor(
45
+ access_mode="RW",
46
+ sectors=123456789,
47
+ type="FLAT",
48
+ filename="disk-flat.vmdk",
49
+ start_sector=0,
50
+ partition_uuid=None,
51
+ device_identifier=None,
52
+ )
53
+ ],
54
+ ),
55
+ (
56
+ "RDONLY 0 ZERO",
57
+ [
58
+ ExtentDescriptor(
59
+ access_mode="RDONLY",
60
+ sectors=0,
61
+ type="ZERO",
62
+ ),
63
+ ],
64
+ ),
65
+ (
66
+ 'NOACCESS 123456789 SPARSE "disk-sparse.vmdk" 123 partition-uuid device-id',
67
+ [
68
+ ExtentDescriptor(
69
+ access_mode="NOACCESS",
70
+ sectors=123456789,
71
+ type="SPARSE",
72
+ filename="disk-sparse.vmdk",
73
+ start_sector=123,
74
+ partition_uuid="partition-uuid",
75
+ device_identifier="device-id",
76
+ ),
77
+ ],
78
+ ),
79
+ ("RW 1234567890", []),
80
+ ('RDONLY "file.vmdk"', []),
81
+ ("NOACCESS", []),
82
+ ],
83
+ ids=("sparse", "flat", "zero", "sparse-ids", "bad-1", "bad-2", "bad-3"),
84
+ )
85
+ def test_vmdk_extent_description(extent_description: str, expected_extents: list) -> None:
86
+ """test if we correctly parse VMDK sparse and flat extent descriptions.
87
+
88
+ Resources:
89
+ - https://github.com/libyal/libvmdk/blob/main/documentation/VMWare%20Virtual%20Disk%20Format%20(VMDK).asciidoc#22-extent-descriptions
90
+ """ # noqa: E501
91
+
92
+ descriptor = DiskDescriptor.parse(extent_description)
93
+ assert descriptor.extents == expected_extents
@@ -1,20 +0,0 @@
1
- from dissect.hypervisor.disk.c_vmdk import c_vmdk
2
- from dissect.hypervisor.disk.vmdk import VMDK
3
-
4
-
5
- def test_vmdk_sesparse(sesparse_vmdk):
6
- vmdk = VMDK(sesparse_vmdk)
7
-
8
- disk = vmdk.disks[0]
9
-
10
- assert disk.is_sesparse
11
- assert disk._grain_directory_size == 0x20000
12
- assert disk._grain_table_size == 0x1000
13
- assert disk._grain_entry_type == c_vmdk.uint64
14
- assert disk._grain_directory[0] == 0x1000000000000000
15
-
16
- header = disk.header
17
- assert header.magic == c_vmdk.SESPARSE_CONST_HEADER_MAGIC
18
- assert header.version == 0x200000001
19
-
20
- assert vmdk.read(0x1000000) == b"a" * 0x1000000