BBSIZE = 8192 # size of boot area with label
SBSIZE = 8192 # max size of fs superblock
+DISKMAGIC = 0x82564557
+
class MBR(object):
"""Represents a Master Boot Record."""
return "%s\n%s\n%s\n" % (title, len(title) * "=", ret)
-class Disklabel:
- """Represents an BSD Disklabel"""
+class PartitionTableBase(object):
+ """Base Class for disklabel partition tables"""
+ format = ""
- def __init__(self, disk):
- """Create a DiskLabel instance"""
- self.disk = disk
+ Partition = namedtuple('Partition', '')
+
+ def __init__(self, ptable, pnumber):
+ """Create a Partition Table instance"""
+ self.part = []
+
+ size = struct.calcsize(self.format)
+
+ raw = cStringIO.StringIO(ptable)
+ try:
+ for i in range(pnumber):
+ p = self.Partition(
+ *struct.unpack(self.format, raw.read(size)))
+ self.part.append(p)
+ finally:
+ raw.close()
+
+ def __str__(self):
+ """Print the Partition table"""
+ val = ""
+ for i in range(len(self.part)):
+ val += "%c: %s\n" % (chr(ord('a') + i), str(self.part[i]))
+ return val
+
+ def pack(self):
+ """Packs the partition table into a binary string."""
+ ret = ""
+ for i in range(len(self.part)):
+ ret += struct.pack(self.format, *self.part[i])
+ return ret
+
+
+class Disk(object):
+ """Represents an BSD Disk"""
+
+ def __init__(self, device):
+ """Create a Disk instance"""
+ self.device = device
self.part_num = None
self.disklabel = None
- with open(disk, "rb") as d:
+ with open(device, "rb") as d:
sector0 = d.read(BLOCKSIZE)
self.mbr = MBR(sector0)
assert self.disklabel is not None, "No *BSD partition found"
def write(self):
- """Write the disklabel back to the media"""
- with open(self.disk, 'rw+b') as d:
+ """Write the changes back to the media"""
+ with open(self.device, 'rw+b') as d:
d.write(self.mbr.pack())
d.seek(self.mbr.part[self.part_num].first_sector * BLOCKSIZE)
def __str__(self):
return str(self.mbr) + str(self.disklabel)
- def enlarge_disk(self, new_size):
- """Enlarge the size of the disk and return the last usable sector"""
+ def enlarge(self, new_size):
+ """Enlarge the disk and return the last usable sector"""
# Fix the disklabel
- end = self.disklabel.enlarge_disk(new_size)
+ end = self.disklabel.enlarge(new_size)
# Fix the MBR
start = self.mbr.part[self.part_num].first_sector
self.disklabel.enlarge_last_partition()
-class BSD_Disklabel:
- pass
+class BSD_Disklabel(object):
+ """Represents an BSD Disklabel"""
+ class PartitionTable(PartitionTableBase):
+ """Represents a BSD Partition Table"""
+ format = "<IIIBBH"
+ """
+ Partition Entry:
+ Offset Length Contents
+ 0 4 Number of sectors in partition
+ 4 4 Starting sector
+ 8 4 Filesystem basic fragment size
+ 12 1 Filesystem type
+ 13 1 Filesystem fragments per block
+ 14 2 Filesystem cylinders per group
+ """
-class OpenBSD_Disklabel:
- """Represents an OpenBSD Disklabel"""
- format = "<IHH16s16sIIIIII8sIHHIII20sHH16sIHHII364s"
+ Partition = namedtuple(
+ 'Partition', 'size, offset, fsize, fstype, frag, cpg')
+
+ format = "<IHH16s16sIIIIIIHHIHHHHIII20s20sIHHII64s"
"""
Offset Length Contents
0 4 Magic
24 16 Pack Identifier
32 4 Bytes per sector
36 4 Data sectors per track
- 40 4 Tracks per cilinder
+ 40 4 Tracks per cylinder
44 4 Data cylinders per unit
- 48 4 Data sectors per cylynder
+ 48 4 Data sectors per cylinder
52 4 Data sectors per unit
- 56 8 Unique label identifier
- 64 4 Alt cylinders per unit
- 68 2 Start of useable region (high part)
- 70 2 Size of usable region (high part)
- 72 4 Start of useable region
- 76 4 End of usable region
+ 56 2 Spare sectors per track
+ 58 2 Spare sectors per cylinder
+ 60 4 Alternative cylinders per unit
+ 64 2 Rotation Speed
+ 66 2 Hardware sector interleave
+ 68 2 Sector 0 skew, per track
+ 70 2 Sector 0 skew, per cylinder
+ 72 4 Head switch time
+ 76 4 Track-to-track seek
80 4 Generic Flags
84 5*4 Drive-type specific information
- 104 2 Number of data sectors (high part)
- 106 2 Version
- 108 4*4 Reserved for future use
- 124 4 Magic number
- 128 2 Xor of data Inclu. partitions
- 130 2 Number of partitions in following
+ 104 5*4 Reserved for future use
+ 124 4 Magic Number
+ 128 2 Xor of data including partitions
+ 130 2 Number of partitions following
132 4 size of boot area at sn0, bytes
136 4 Max size of fs superblock, bytes
140 16*16 Partition Table
"""
- class PartitionTable:
+
+class OpenBSD_Disklabel(object):
+ """Represents an OpenBSD Disklabel"""
+
+ class PartitionTable(PartitionTableBase):
"""Reprepsents an OpenBSD Partition Table"""
format = "<IIHHBBH"
"""
Partition = namedtuple(
'Partition', 'size, offset, offseth, sizeh, fstype, frag, cpg')
- def __init__(self, ptable, pnumber):
- """Create a Partition Table instance"""
- self.part = []
-
- size = struct.calcsize(self.format)
-
- raw = cStringIO.StringIO(ptable)
- try:
- for i in range(pnumber):
- p = self.Partition(
- *struct.unpack(self.format, raw.read(size)))
- self.part.append(p)
- finally:
- raw.close()
-
- def __str__(self):
- """Print the Partition table"""
- val = ""
- for i in range(len(self.part)):
- val += "%c: %s\n" % (chr(ord('a') + i), str(self.part[i]))
- return val
-
- def pack(self):
- """Packs the partition table into a binary string."""
- ret = ""
- for i in range(len(self.part)):
- ret += struct.pack(self.format,
- self.part[i].size,
- self.part[i].offset,
- self.part[i].offseth,
- self.part[i].sizeh,
- self.part[i].fstype,
- self.part[i].frag,
- self.part[i].cpg)
- return ret
-
def setpsize(self, i, size):
"""Set size for partition i"""
tmp = self.part[i]
"""Get offset for partition i"""
return (self.part[i].offseth << 32) + self.part[i].offset
- DISKMAGIC = 0x82564557
-
+ format = "<IHH16s16sIIIIII8sIHHIII20sHH16sIHHII364s"
+ """
+ Offset Length Contents
+ 0 4 Magic
+ 4 2 Drive Type
+ 6 2 Subtype
+ 8 16 Type Name
+ 24 16 Pack Identifier
+ 32 4 Bytes per sector
+ 36 4 Data sectors per track
+ 40 4 Tracks per cylinder
+ 44 4 Data cylinders per unit
+ 48 4 Data sectors per cylinder
+ 52 4 Data sectors per unit
+ 56 8 Unique label identifier
+ 64 4 Alt cylinders per unit
+ 68 2 Start of useable region (high part)
+ 70 2 Size of usable region (high part)
+ 72 4 Start of useable region
+ 76 4 End of usable region
+ 80 4 Generic Flags
+ 84 5*4 Drive-type specific information
+ 104 2 Number of data sectors (high part)
+ 106 2 Version
+ 108 4*4 Reserved for future use
+ 124 4 Magic number
+ 128 2 Xor of data including partitions
+ 130 2 Number of partitions in following
+ 132 4 size of boot area at sn0, bytes
+ 136 4 Max size of fs superblock, bytes
+ 140 16*16 Partition Table
+ """
def __init__(self, device):
"""Create a DiskLabel instance"""
self.sbsize,
ptable_raw) = struct.unpack(self.format, sector1)
- assert self.magic == self.DISKMAGIC, "Disklabel is not valid"
+ assert self.magic == DISKMAGIC, "Disklabel is not valid"
self.ptable = self.PartitionTable(ptable_raw, self.npartitions)
"""Get size of usable region"""
return (self.bendh << 32) + self.bend
- def enlarge_disk(self, new_size):
+ def enlarge(self, new_size):
"""Enlarge the size of the disk and return the last usable sector"""
assert new_size >= self.getdsize(), \
if len(args) != 1:
parser.error("Wrong number of arguments")
- disklabel = Disklabel(args[0])
+ disk = Disk(args[0])
if options.list:
- print disklabel
+ print disk
sys.exit(0)
if options.duid:
- print "%s" % "".join(x.encode('hex') for x in disklabel.uid)
+ print "%s" % "".join(x.encode('hex') for x in disk.uid)
sys.exit(0)
if options.last_part:
- print "%c" % chr(ord('a') + disklabel.get_last_partition_id())
+ print "%c" % chr(ord('a') + disk.get_last_partition_id())
if options.disk_size is not None:
- disklabel.enlarge_disk(options.disk_size)
+ disk.enlarge(options.disk_size)
if options.enlarge_partition:
- disklabel.enlarge_last_partition()
+ disk.enlarge_last_partition()
- disklabel.write()
+ disk.write()
sys.exit(0)