dissect.vmfs

Submodules

Package Contents

Classes

LVM

VMFS LVM implementation.

Extent

VMFS LVM physical extent implementation.

VMFS

VMFS filesystem implementation.

exception dissect.vmfs.Error

Bases: Exception

Common base class for all non-exit exceptions.

exception dissect.vmfs.FileNotFoundError

Bases: Error, FileNotFoundError

Common base class for all non-exit exceptions.

exception dissect.vmfs.InvalidHeader

Bases: Error

Common base class for all non-exit exceptions.

exception dissect.vmfs.NotADirectoryError

Bases: Error, NotADirectoryError

Common base class for all non-exit exceptions.

exception dissect.vmfs.NotASymlinkError

Bases: Error

Common base class for all non-exit exceptions.

class dissect.vmfs.LVM(fh: BinaryIO | list[BinaryIO])

Bases: dissect.util.stream.AlignedStream

VMFS LVM implementation.

Takes a list of file-like objects (or Extents) to construct a volume.

VMFS should start at LVM dataOffset + 0x200000

uuid = None
version = None
extents = []
class dissect.vmfs.Extent(fh: BinaryIO)

Bases: dissect.util.stream.AlignedStream

VMFS LVM physical extent implementation.

PE bitmap is at VMFS_LVM_PE_BITMAP_BASE + version dependent offset.

It appears that the LVM can start at the following offsets, however that still needs to be verified: - 0x100000 - 0x110000 - 0x200000 - 0x180000 - 0x900000

fh
metadata
volume_info
name
device_id
uuid
num_pe
first_pe
last_pe
class dissect.vmfs.VMFS(volume: BinaryIO | None = None, vh: BinaryIO | None = None, fdc: BinaryIO | None = None, fbb: BinaryIO | None = None, sbc: BinaryIO | None = None, pbc: BinaryIO | None = None, pb2: BinaryIO | None = None, jbc: BinaryIO | None = None)

VMFS filesystem implementation.

Assumes that an LVM has already been loaded.

We implement it quite a bit different from how ESXi seems to use it. ESXi doesn’t really distinguish between disk partitions and LVM volumes. Everything is a VMFS volume, and it either contains a filesystem header at 0x01300000 or it doesn’t. Either it contains an LVM that requires multiple extents or it doesn’t. It’s all VMFS, LVM doesn’t really exist and it’s really just an extra header that specifies if the _filesystem_ requires multiple extents or not.

This doesn’t really fit with how the rest of dissect is architected, so we act like the LVM is a “proper LVM” that exposes a logical volume. We then load a “VMFS filesystem” on top of this logical volume. This volume is made up of one or more extents that are loaded beforehand.

A lot of the math consists of bitwise shifts and masks, which translate to modulo or multiplication operations. For the sake of “maintainability” in relation to the original “code”, we keep this as bitwise masks, at the sacrifice of some human readability. Comments explaining as such are placed where appropriate.

fh = None
descriptor
block_size
major_version
minor_version
uuid
label
resources
file_descriptor
root
property is_vmfs5: bool
property is_vmfs6: bool
get(path: str | int, node: FileDescriptor | None = None) FileDescriptor
iter_fd() collections.abc.Iterator[FileDescriptor]