nobodd.disk

The nobodd.disk module contains the DiskImage class which is the primary entry point for handling disk images. Constructed with a filename (or file-like object which provides a valid fileno() method), the class will attempt to determine if MBR or GPT style partitioning is in use. The DiskImage.partitions attribute can then be queried to enumerate, or access the data of, individual partitions:

>>> from nobodd.disk import DiskImage
>>> img = DiskImage('gpt_disk.img')
>>> img
<DiskImage file=<_io.BufferedReader name='gpt_disk.img'> style='gpt' signature=UUID('733b49a8-6918-4e44-8d3d-47ed9b481335')>
>>> img.style
'gpt'
>>> len(img.partitions)
4
>>> img.partitions
DiskPartitionsGPT({
1: <DiskPartition size=8388608 label='big-part' type=UUID('ebd0a0a2-b9e5-4433-87c0-68b6b72699c7')>,
2: <DiskPartition size=204800 label='little-part1' type=UUID('ebd0a0a2-b9e5-4433-87c0-68b6b72699c7')>,
5: <DiskPartition size=4194304 label='medium-part' type=UUID('ebd0a0a2-b9e5-4433-87c0-68b6b72699c7')>,
6: <DiskPartition size=204800 label='little-part2' type=UUID('ebd0a0a2-b9e5-4433-87c0-68b6b72699c7')>,
})

Note that partitions are numbered from 1 and that, especially in the case of MBR, partition numbers may not be contiguous: primary partitions are numbered 1 through 4, but logical partitions may only exist in one primary partition, and are numbered from 5. Hence it is entirely valid to have partitions 1, 5, and 6:

>>> from nobodd.disk import DiskImage
>>> img = DiskImage('test-ebr.img')
>>> img.style
'mbr'
>>> len(img.partitions)
3
>>> list(img.partitions.keys())
[1, 5, 6]
>>> img.partitions[1]
<DiskPartition size=536870912 label='Partition 1' type=12>
>>> img.partitions[5]
<DiskPartition size=536870912 label='Partition 5' type=131>
>>> img.partitions[6]
<DiskPartition size=1070596096 label='Partition 6' type=131>

GPT partition tables may also have non-contiguous numbering, although this is less common in practice. The DiskPartition.data attribute can be used to access the content of the partition as a buffer object (see memoryview).

DiskImage

class nobodd.disk.DiskImage(filename_or_obj, sector_size=512, access=1)[source]

Represents a disk image, specified by filename_or_obj which must be a str or Path naming the file, or a file-like object.

If a file-like object is provided, it must have a fileno method which returns a valid file-descriptor number (the class uses mmap internally which requires a “real” file).

The disk image is expected to be partitioned with either an MBR partition table or a GPT. The partitions within the image can be enumerated with the partitions attribute. The instance can (and should) be used as a context manager; exiting the context will call the close() method implicitly.

If specified, sector_size is the size of sectors (in bytes) within the disk image. This defaults to 512 bytes, and should almost always be left alone. The access parameter controls the access used when constructing the memory mapping. This defaults to mmap.ACCESS_READ for read-only access. If you wish to write to file-systems within the disk image, change this to mmap.ACCESS_WRITE. You may also use mmap.ACCESS_COPY for read-write mappings that don’t actually affect the underlying disk image.

Note

Please note that this library provides no means to re-partition disk images, just the ability to re-write files within FAT partitions.

close()[source]

Destroys the memory mapping used on the file provided. If the file was opened by this class, it will also be closed. This method is idempotent and is implicitly called when the instance is used as a context manager.

Note

All mappings derived from this one must be closed before calling this method. By far the easiest means of arranging this is to consistently use context managers with all instances derived from this.

property partitions

Provides access to the partitions in the image as a Mapping of partition number to DiskPartition instances.

Warning

Disk partition numbers start from 1 and need not be contiguous, or ordered.

For example, it is perfectly valid to have partition 1 occur later on disk than partition 2, for partition 3 to be undefined, and partition 4 to be defined between partition 1 and 2. The partition number is essentially little more than an arbitrary key.

In the case of MBR partition tables, it is particularly common to have missing partition numbers as the primary layout only permits 4 partitions. Hence, the “extended partitions” scheme numbers partitions from 5. However, if not all primary partitions are defined, there will be a “jump” from, say, partition 2 to partition 5.

property signature

The identifying signature of the disk. In the case of a GPT partitioned disk, this is a UUID. In the case of MBR, this is a 32-bit integer number.

property style

The style of partition table in use on the disk image. Will be one of the strings, ‘gpt’ or ‘mbr’.

DiskPartition

class nobodd.disk.DiskPartition(mem, label, type)[source]

Represents an individual disk partition within a DiskImage.

Instances of this class are returned as the values of the mapping provided by DiskImage.partitions. Instances can (and should) be used as a context manager to implicitly close references upon exiting the context.

close()[source]

Release the internal memoryview reference. This method is idempotent and is implicitly called when the instance is used as a context manager.

property data

Returns a buffer (specifically, a memoryview) covering the contents of the partition in the owning DiskImage.

property label

The label of the partition. GPT partitions may have a 36 character unicode label. MBR partitions do not have a label, so the string “Partition {num}” will be used instead (where {num} is the partition number).

property type

The type of the partition. For GPT partitions, this will be a uuid.UUID instance. For MBR partitions, this will be an int.

Internal Classes

You should not need to use these classes directly; they will be instantiated automatically when querying the DiskImage.partitions attribute according to the detected table format.

class nobodd.disk.DiskPartitionsGPT(mem, sector_size=512)[source]

Provides a Mapping from partition number to DiskPartition instances for a GPT.

mem is the buffer covering the whole disk image. sector_size specifies the sector size of the disk image, which should almost always be left at the default of 512 bytes.

class nobodd.disk.DiskPartitionsMBR(mem, sector_size=512)[source]

Provides a Mapping from partition number to DiskPartition instances for a MBR.

mem is the buffer covering the whole disk image. sector_size specifies the sector size of the disk image, which should almost always be left at the default of 512 bytes.