root / snf-image-helper / disklabel.py @ 63656985
History | View | Annotate | Download (23.5 kB)
1 | de34e7aa | Nikos Skalkotos | #!/usr/bin/env python
|
---|---|---|---|
2 | 1bda0902 | Nikos Skalkotos | #
|
3 | de34e7aa | Nikos Skalkotos | # -*- coding: utf-8 -*-
|
4 | de34e7aa | Nikos Skalkotos | #
|
5 | de34e7aa | Nikos Skalkotos | # Copyright (C) 2013 GRNET S.A.
|
6 | de34e7aa | Nikos Skalkotos | #
|
7 | de34e7aa | Nikos Skalkotos | # This program is free software; you can redistribute it and/or modify
|
8 | de34e7aa | Nikos Skalkotos | # it under the terms of the GNU General Public License as published by
|
9 | de34e7aa | Nikos Skalkotos | # the Free Software Foundation; either version 2 of the License, or
|
10 | de34e7aa | Nikos Skalkotos | # (at your option) any later version.
|
11 | de34e7aa | Nikos Skalkotos | #
|
12 | de34e7aa | Nikos Skalkotos | # This program is distributed in the hope that it will be useful, but
|
13 | de34e7aa | Nikos Skalkotos | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | de34e7aa | Nikos Skalkotos | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | de34e7aa | Nikos Skalkotos | # General Public License for more details.
|
16 | de34e7aa | Nikos Skalkotos | #
|
17 | de34e7aa | Nikos Skalkotos | # You should have received a copy of the GNU General Public License
|
18 | de34e7aa | Nikos Skalkotos | # along with this program; if not, write to the Free Software
|
19 | de34e7aa | Nikos Skalkotos | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
20 | de34e7aa | Nikos Skalkotos | # 02110-1301, USA.
|
21 | de34e7aa | Nikos Skalkotos | |
22 | 34fd52a7 | Nikos Skalkotos | """This module provides the code for handling BSD disklabels"""
|
23 | de34e7aa | Nikos Skalkotos | |
24 | de34e7aa | Nikos Skalkotos | import struct |
25 | de34e7aa | Nikos Skalkotos | import sys |
26 | 34fd52a7 | Nikos Skalkotos | import os |
27 | de34e7aa | Nikos Skalkotos | import cStringIO |
28 | de34e7aa | Nikos Skalkotos | import optparse |
29 | de34e7aa | Nikos Skalkotos | |
30 | de34e7aa | Nikos Skalkotos | from collections import namedtuple |
31 | de34e7aa | Nikos Skalkotos | |
32 | de34e7aa | Nikos Skalkotos | BLOCKSIZE = 512
|
33 | de34e7aa | Nikos Skalkotos | |
34 | de34e7aa | Nikos Skalkotos | LABELSECTOR = 1
|
35 | de34e7aa | Nikos Skalkotos | LABELOFFSET = 0
|
36 | de34e7aa | Nikos Skalkotos | |
37 | de34e7aa | Nikos Skalkotos | BBSIZE = 8192 # size of boot area with label |
38 | de34e7aa | Nikos Skalkotos | SBSIZE = 8192 # max size of fs superblock |
39 | de34e7aa | Nikos Skalkotos | |
40 | be5f0160 | Nikos Skalkotos | DISKMAGIC = 0x82564557
|
41 | be5f0160 | Nikos Skalkotos | |
42 | de34e7aa | Nikos Skalkotos | |
43 | de34e7aa | Nikos Skalkotos | class MBR(object): |
44 | de34e7aa | Nikos Skalkotos | """Represents a Master Boot Record."""
|
45 | de34e7aa | Nikos Skalkotos | class Partition(object): |
46 | de34e7aa | Nikos Skalkotos | """Represents a partition entry in MBR"""
|
47 | de34e7aa | Nikos Skalkotos | format = "<B3sB3sLL"
|
48 | de34e7aa | Nikos Skalkotos | |
49 | de34e7aa | Nikos Skalkotos | def __init__(self, raw_part): |
50 | de34e7aa | Nikos Skalkotos | """Create a Partition instance"""
|
51 | de34e7aa | Nikos Skalkotos | ( |
52 | de34e7aa | Nikos Skalkotos | self.status,
|
53 | de34e7aa | Nikos Skalkotos | self.start,
|
54 | de34e7aa | Nikos Skalkotos | self.type,
|
55 | de34e7aa | Nikos Skalkotos | self.end,
|
56 | de34e7aa | Nikos Skalkotos | self.first_sector,
|
57 | de34e7aa | Nikos Skalkotos | self.sector_count
|
58 | de34e7aa | Nikos Skalkotos | ) = struct.unpack(self.format, raw_part)
|
59 | de34e7aa | Nikos Skalkotos | |
60 | de34e7aa | Nikos Skalkotos | def pack(self): |
61 | de34e7aa | Nikos Skalkotos | """Pack the partition values into a binary string"""
|
62 | de34e7aa | Nikos Skalkotos | return struct.pack(self.format, |
63 | de34e7aa | Nikos Skalkotos | self.status,
|
64 | de34e7aa | Nikos Skalkotos | self.start,
|
65 | de34e7aa | Nikos Skalkotos | self.type,
|
66 | de34e7aa | Nikos Skalkotos | self.end,
|
67 | de34e7aa | Nikos Skalkotos | self.first_sector,
|
68 | de34e7aa | Nikos Skalkotos | self.sector_count)
|
69 | de34e7aa | Nikos Skalkotos | |
70 | de34e7aa | Nikos Skalkotos | @staticmethod
|
71 | de34e7aa | Nikos Skalkotos | def size(): |
72 | de34e7aa | Nikos Skalkotos | """Returns the size of an MBR partition entry"""
|
73 | de34e7aa | Nikos Skalkotos | return struct.calcsize(MBR.Partition.format)
|
74 | de34e7aa | Nikos Skalkotos | |
75 | de34e7aa | Nikos Skalkotos | def __str__(self): |
76 | de34e7aa | Nikos Skalkotos | start = self.unpack_chs(self.start) |
77 | de34e7aa | Nikos Skalkotos | end = self.unpack_chs(self.end) |
78 | de34e7aa | Nikos Skalkotos | return "%d %s %d %s %d %d" % (self.status, start, self.type, end, |
79 | de34e7aa | Nikos Skalkotos | self.first_sector, self.sector_count) |
80 | de34e7aa | Nikos Skalkotos | |
81 | de34e7aa | Nikos Skalkotos | @staticmethod
|
82 | de34e7aa | Nikos Skalkotos | def unpack_chs(chs): |
83 | de34e7aa | Nikos Skalkotos | """Unpacks a CHS address string to a tuple."""
|
84 | de34e7aa | Nikos Skalkotos | |
85 | de34e7aa | Nikos Skalkotos | assert len(chs) == 3 |
86 | de34e7aa | Nikos Skalkotos | |
87 | de34e7aa | Nikos Skalkotos | head = struct.unpack('<B', chs[0])[0] |
88 | de34e7aa | Nikos Skalkotos | sector = struct.unpack('<B', chs[1])[0] & 0x3f |
89 | de34e7aa | Nikos Skalkotos | cylinder = (struct.unpack('<B', chs[1])[0] & 0xC0) << 2 | \ |
90 | de34e7aa | Nikos Skalkotos | struct.unpack('<B', chs[2])[0] |
91 | de34e7aa | Nikos Skalkotos | |
92 | de34e7aa | Nikos Skalkotos | return (cylinder, head, sector)
|
93 | de34e7aa | Nikos Skalkotos | |
94 | de34e7aa | Nikos Skalkotos | @staticmethod
|
95 | de34e7aa | Nikos Skalkotos | def pack_chs(cylinder, head, sector): |
96 | de34e7aa | Nikos Skalkotos | """Packs a CHS tuple to an address string."""
|
97 | de34e7aa | Nikos Skalkotos | |
98 | de34e7aa | Nikos Skalkotos | assert 1 <= sector <= 63 |
99 | de34e7aa | Nikos Skalkotos | assert 0 <= head <= 255 |
100 | 0d413fc6 | Nikos Skalkotos | assert 0 <= cylinder |
101 | 0d413fc6 | Nikos Skalkotos | |
102 | 0d413fc6 | Nikos Skalkotos | # If the cylinders overflow then put the value (1023, 254, 63) to
|
103 | 0d413fc6 | Nikos Skalkotos | # the tuple. At least this is what OpenBSD does.
|
104 | 0d413fc6 | Nikos Skalkotos | if cylinder > 1023: |
105 | 0d413fc6 | Nikos Skalkotos | cylinder = 1023
|
106 | 0d413fc6 | Nikos Skalkotos | head = 254
|
107 | 0d413fc6 | Nikos Skalkotos | sector = 63
|
108 | de34e7aa | Nikos Skalkotos | |
109 | de34e7aa | Nikos Skalkotos | byte0 = head |
110 | de34e7aa | Nikos Skalkotos | byte1 = (cylinder >> 2) & 0xC0 | sector |
111 | de34e7aa | Nikos Skalkotos | byte2 = cylinder & 0xff
|
112 | de34e7aa | Nikos Skalkotos | |
113 | de34e7aa | Nikos Skalkotos | return struct.pack('<BBB', byte0, byte1, byte2) |
114 | de34e7aa | Nikos Skalkotos | |
115 | de34e7aa | Nikos Skalkotos | format = "<444s2x16s16s16s16s2s"
|
116 | de34e7aa | Nikos Skalkotos | """
|
117 | de34e7aa | Nikos Skalkotos | Offset Length Contents
|
118 | de34e7aa | Nikos Skalkotos | 0 440(max. 446) code area
|
119 | de34e7aa | Nikos Skalkotos | 440 2(optional) disk signature
|
120 | de34e7aa | Nikos Skalkotos | 444 2 Usually nulls
|
121 | de34e7aa | Nikos Skalkotos | 446 16 Partition 0
|
122 | de34e7aa | Nikos Skalkotos | 462 16 Partition 1
|
123 | de34e7aa | Nikos Skalkotos | 478 16 Partition 2
|
124 | de34e7aa | Nikos Skalkotos | 494 16 Partition 3
|
125 | de34e7aa | Nikos Skalkotos | 510 2 MBR signature
|
126 | de34e7aa | Nikos Skalkotos | """
|
127 | de34e7aa | Nikos Skalkotos | def __init__(self, block): |
128 | de34e7aa | Nikos Skalkotos | """Create an MBR instance"""
|
129 | de34e7aa | Nikos Skalkotos | raw_part = {} |
130 | de34e7aa | Nikos Skalkotos | (self.code_area,
|
131 | de34e7aa | Nikos Skalkotos | raw_part[0],
|
132 | de34e7aa | Nikos Skalkotos | raw_part[1],
|
133 | de34e7aa | Nikos Skalkotos | raw_part[2],
|
134 | de34e7aa | Nikos Skalkotos | raw_part[3],
|
135 | de34e7aa | Nikos Skalkotos | self.signature) = struct.unpack(self.format, block) |
136 | de34e7aa | Nikos Skalkotos | |
137 | de34e7aa | Nikos Skalkotos | self.part = {}
|
138 | de34e7aa | Nikos Skalkotos | for i in range(4): |
139 | de34e7aa | Nikos Skalkotos | self.part[i] = self.Partition(raw_part[i]) |
140 | de34e7aa | Nikos Skalkotos | |
141 | de34e7aa | Nikos Skalkotos | @staticmethod
|
142 | de34e7aa | Nikos Skalkotos | def size(): |
143 | de34e7aa | Nikos Skalkotos | """Return the size of a Master Boot Record."""
|
144 | de34e7aa | Nikos Skalkotos | return struct.calcsize(MBR.format)
|
145 | de34e7aa | Nikos Skalkotos | |
146 | de34e7aa | Nikos Skalkotos | def pack(self): |
147 | de34e7aa | Nikos Skalkotos | """Pack an MBR to a binary string."""
|
148 | de34e7aa | Nikos Skalkotos | return struct.pack(self.format, |
149 | de34e7aa | Nikos Skalkotos | self.code_area,
|
150 | de34e7aa | Nikos Skalkotos | self.part[0].pack(), |
151 | de34e7aa | Nikos Skalkotos | self.part[1].pack(), |
152 | de34e7aa | Nikos Skalkotos | self.part[2].pack(), |
153 | de34e7aa | Nikos Skalkotos | self.part[3].pack(), |
154 | de34e7aa | Nikos Skalkotos | self.signature)
|
155 | de34e7aa | Nikos Skalkotos | |
156 | de34e7aa | Nikos Skalkotos | def __str__(self): |
157 | de34e7aa | Nikos Skalkotos | ret = ""
|
158 | de34e7aa | Nikos Skalkotos | for i in range(4): |
159 | de34e7aa | Nikos Skalkotos | ret += "Partition %d: %s\n" % (i, self.part[i]) |
160 | de34e7aa | Nikos Skalkotos | ret += "Signature: %s %s\n" % (hex(ord(self.signature[0])), |
161 | de34e7aa | Nikos Skalkotos | hex(ord(self.signature[1]))) |
162 | 34fd52a7 | Nikos Skalkotos | title = "Master Boot Record"
|
163 | 34fd52a7 | Nikos Skalkotos | return "%s\n%s\n%s\n" % (title, len(title) * "=", ret) |
164 | de34e7aa | Nikos Skalkotos | |
165 | de34e7aa | Nikos Skalkotos | |
166 | be5f0160 | Nikos Skalkotos | class PartitionTableBase(object): |
167 | be5f0160 | Nikos Skalkotos | """Base Class for disklabel partition tables"""
|
168 | be5f0160 | Nikos Skalkotos | format = ""
|
169 | 34fd52a7 | Nikos Skalkotos | |
170 | be5f0160 | Nikos Skalkotos | Partition = namedtuple('Partition', '') |
171 | be5f0160 | Nikos Skalkotos | |
172 | be5f0160 | Nikos Skalkotos | def __init__(self, ptable, pnumber): |
173 | be5f0160 | Nikos Skalkotos | """Create a Partition Table instance"""
|
174 | be5f0160 | Nikos Skalkotos | self.part = []
|
175 | be5f0160 | Nikos Skalkotos | |
176 | be5f0160 | Nikos Skalkotos | size = struct.calcsize(self.format)
|
177 | be5f0160 | Nikos Skalkotos | |
178 | be5f0160 | Nikos Skalkotos | raw = cStringIO.StringIO(ptable) |
179 | be5f0160 | Nikos Skalkotos | try:
|
180 | be5f0160 | Nikos Skalkotos | for i in range(pnumber): |
181 | be5f0160 | Nikos Skalkotos | p = self.Partition(
|
182 | be5f0160 | Nikos Skalkotos | *struct.unpack(self.format, raw.read(size)))
|
183 | be5f0160 | Nikos Skalkotos | self.part.append(p)
|
184 | be5f0160 | Nikos Skalkotos | finally:
|
185 | be5f0160 | Nikos Skalkotos | raw.close() |
186 | be5f0160 | Nikos Skalkotos | |
187 | be5f0160 | Nikos Skalkotos | def __str__(self): |
188 | be5f0160 | Nikos Skalkotos | """Print the Partition table"""
|
189 | be5f0160 | Nikos Skalkotos | val = ""
|
190 | be5f0160 | Nikos Skalkotos | for i in range(len(self.part)): |
191 | be5f0160 | Nikos Skalkotos | val += "%c: %s\n" % (chr(ord('a') + i), str(self.part[i])) |
192 | be5f0160 | Nikos Skalkotos | return val
|
193 | be5f0160 | Nikos Skalkotos | |
194 | be5f0160 | Nikos Skalkotos | def pack(self): |
195 | be5f0160 | Nikos Skalkotos | """Packs the partition table into a binary string."""
|
196 | be5f0160 | Nikos Skalkotos | ret = ""
|
197 | be5f0160 | Nikos Skalkotos | for i in range(len(self.part)): |
198 | be5f0160 | Nikos Skalkotos | ret += struct.pack(self.format, *self.part[i]) |
199 | be5f0160 | Nikos Skalkotos | return ret
|
200 | be5f0160 | Nikos Skalkotos | |
201 | be5f0160 | Nikos Skalkotos | |
202 | be5f0160 | Nikos Skalkotos | class Disk(object): |
203 | be5f0160 | Nikos Skalkotos | """Represents an BSD Disk"""
|
204 | be5f0160 | Nikos Skalkotos | |
205 | be5f0160 | Nikos Skalkotos | def __init__(self, device): |
206 | be5f0160 | Nikos Skalkotos | """Create a Disk instance"""
|
207 | be5f0160 | Nikos Skalkotos | self.device = device
|
208 | 34fd52a7 | Nikos Skalkotos | self.part_num = None |
209 | 34fd52a7 | Nikos Skalkotos | self.disklabel = None |
210 | 34fd52a7 | Nikos Skalkotos | |
211 | be5f0160 | Nikos Skalkotos | with open(device, "rb") as d: |
212 | 34fd52a7 | Nikos Skalkotos | sector0 = d.read(BLOCKSIZE) |
213 | 34fd52a7 | Nikos Skalkotos | self.mbr = MBR(sector0)
|
214 | 34fd52a7 | Nikos Skalkotos | |
215 | 34fd52a7 | Nikos Skalkotos | for i in range(4): |
216 | 34fd52a7 | Nikos Skalkotos | ptype = self.mbr.part[i].type
|
217 | 34fd52a7 | Nikos Skalkotos | if ptype in (0xa5, 0xa6, 0xa9): |
218 | 34fd52a7 | Nikos Skalkotos | d.seek(BLOCKSIZE * self.mbr.part[i].first_sector)
|
219 | 34fd52a7 | Nikos Skalkotos | self.part_num = i
|
220 | 34fd52a7 | Nikos Skalkotos | if ptype == 0xa5: # FreeBSD |
221 | 34fd52a7 | Nikos Skalkotos | self.disklabel = BSD_Disklabel(d)
|
222 | 34fd52a7 | Nikos Skalkotos | elif ptype == 0xa6: # OpenBSD |
223 | 34fd52a7 | Nikos Skalkotos | self.disklabel = OpenBSD_Disklabel(d)
|
224 | 34fd52a7 | Nikos Skalkotos | else: # NetBSD |
225 | 34fd52a7 | Nikos Skalkotos | self.disklabel = BSD_Disklabel(d)
|
226 | 34fd52a7 | Nikos Skalkotos | break
|
227 | 34fd52a7 | Nikos Skalkotos | |
228 | 34fd52a7 | Nikos Skalkotos | assert self.disklabel is not None, "No *BSD partition found" |
229 | 34fd52a7 | Nikos Skalkotos | |
230 | 34fd52a7 | Nikos Skalkotos | def write(self): |
231 | be5f0160 | Nikos Skalkotos | """Write the changes back to the media"""
|
232 | be5f0160 | Nikos Skalkotos | with open(self.device, 'rw+b') as d: |
233 | 34fd52a7 | Nikos Skalkotos | d.write(self.mbr.pack())
|
234 | 34fd52a7 | Nikos Skalkotos | |
235 | 34fd52a7 | Nikos Skalkotos | d.seek(self.mbr.part[self.part_num].first_sector * BLOCKSIZE) |
236 | 34fd52a7 | Nikos Skalkotos | self.disklabel.write_to(d)
|
237 | 34fd52a7 | Nikos Skalkotos | |
238 | 34fd52a7 | Nikos Skalkotos | def __str__(self): |
239 | 34fd52a7 | Nikos Skalkotos | return str(self.mbr) + str(self.disklabel) |
240 | 34fd52a7 | Nikos Skalkotos | |
241 | be5f0160 | Nikos Skalkotos | def enlarge(self, new_size): |
242 | be5f0160 | Nikos Skalkotos | """Enlarge the disk and return the last usable sector"""
|
243 | 34fd52a7 | Nikos Skalkotos | |
244 | 34fd52a7 | Nikos Skalkotos | # Fix the disklabel
|
245 | be5f0160 | Nikos Skalkotos | end = self.disklabel.enlarge(new_size)
|
246 | 34fd52a7 | Nikos Skalkotos | |
247 | 34fd52a7 | Nikos Skalkotos | # Fix the MBR
|
248 | 34fd52a7 | Nikos Skalkotos | start = self.mbr.part[self.part_num].first_sector |
249 | 34fd52a7 | Nikos Skalkotos | self.mbr.part[self.part_num].sector_count = end - start + 1 |
250 | 34fd52a7 | Nikos Skalkotos | |
251 | 34fd52a7 | Nikos Skalkotos | cylinder = end // (self.disklabel.ntracks * self.disklabel.nsectors) |
252 | 34fd52a7 | Nikos Skalkotos | header = (end // self.disklabel.nsectors) % self.disklabel.ntracks |
253 | 34fd52a7 | Nikos Skalkotos | sector = (end % self.disklabel.nsectors) + 1 |
254 | 34fd52a7 | Nikos Skalkotos | chs = MBR.Partition.pack_chs(cylinder, header, sector) |
255 | 34fd52a7 | Nikos Skalkotos | self.mbr.part[self.part_num].end = chs |
256 | 34fd52a7 | Nikos Skalkotos | |
257 | 34fd52a7 | Nikos Skalkotos | def enlarge_last_partition(self): |
258 | 34fd52a7 | Nikos Skalkotos | self.disklabel.enlarge_last_partition()
|
259 | 34fd52a7 | Nikos Skalkotos | |
260 | 34fd52a7 | Nikos Skalkotos | |
261 | 63656985 | Nikos Skalkotos | class DisklabelBase(object): |
262 | 63656985 | Nikos Skalkotos | """Disklabel base class"""
|
263 | 63656985 | Nikos Skalkotos | |
264 | 63656985 | Nikos Skalkotos | def __init__(self, device): |
265 | 63656985 | Nikos Skalkotos | """Create a Disklabel instance"""
|
266 | 63656985 | Nikos Skalkotos | raise NotImplementedError |
267 | 63656985 | Nikos Skalkotos | |
268 | 63656985 | Nikos Skalkotos | def pack(self, checksum=None): |
269 | 63656985 | Nikos Skalkotos | """Return a binary copy of the Disklabel block"""
|
270 | 63656985 | Nikos Skalkotos | raise NotImplementedError |
271 | 63656985 | Nikos Skalkotos | |
272 | 63656985 | Nikos Skalkotos | def compute_checksum(self): |
273 | 63656985 | Nikos Skalkotos | """Compute the checksum of the disklabel"""
|
274 | 63656985 | Nikos Skalkotos | |
275 | 63656985 | Nikos Skalkotos | raw = cStringIO.StringIO(self.pack(0)) |
276 | 63656985 | Nikos Skalkotos | checksum = 0
|
277 | 63656985 | Nikos Skalkotos | try:
|
278 | 63656985 | Nikos Skalkotos | uint16 = raw.read(2)
|
279 | 63656985 | Nikos Skalkotos | while uint16 != "": |
280 | 63656985 | Nikos Skalkotos | checksum ^= struct.unpack('<H', uint16)[0] |
281 | 63656985 | Nikos Skalkotos | uint16 = raw.read(2)
|
282 | 63656985 | Nikos Skalkotos | finally:
|
283 | 63656985 | Nikos Skalkotos | raw.close() |
284 | 63656985 | Nikos Skalkotos | |
285 | 63656985 | Nikos Skalkotos | return checksum
|
286 | 63656985 | Nikos Skalkotos | |
287 | 63656985 | Nikos Skalkotos | def enlarge(self, new_size): |
288 | 63656985 | Nikos Skalkotos | """Enlarge the disk and return the last usable sector"""
|
289 | 63656985 | Nikos Skalkotos | raise NotImplementedError |
290 | 63656985 | Nikos Skalkotos | |
291 | 63656985 | Nikos Skalkotos | def write_to(self, device): |
292 | 63656985 | Nikos Skalkotos | """Write the disklabel to a device"""
|
293 | 63656985 | Nikos Skalkotos | raise NotImplementedError |
294 | 63656985 | Nikos Skalkotos | |
295 | 63656985 | Nikos Skalkotos | def enlarge_last_partition(self): |
296 | 63656985 | Nikos Skalkotos | """Enlarge the last partition to consume all the usable space"""
|
297 | 63656985 | Nikos Skalkotos | raise NotImplementedError |
298 | 63656985 | Nikos Skalkotos | |
299 | 63656985 | Nikos Skalkotos | def __str__(self): |
300 | 63656985 | Nikos Skalkotos | """Print the Disklabel"""
|
301 | 63656985 | Nikos Skalkotos | raise NotImplementedError |
302 | 63656985 | Nikos Skalkotos | |
303 | 63656985 | Nikos Skalkotos | |
304 | 63656985 | Nikos Skalkotos | class BSD_Disklabel(DisklabelBase): |
305 | be5f0160 | Nikos Skalkotos | """Represents an BSD Disklabel"""
|
306 | 34fd52a7 | Nikos Skalkotos | |
307 | be5f0160 | Nikos Skalkotos | class PartitionTable(PartitionTableBase): |
308 | be5f0160 | Nikos Skalkotos | """Represents a BSD Partition Table"""
|
309 | be5f0160 | Nikos Skalkotos | format = "<IIIBBH"
|
310 | be5f0160 | Nikos Skalkotos | """
|
311 | be5f0160 | Nikos Skalkotos | Partition Entry:
|
312 | be5f0160 | Nikos Skalkotos | Offset Length Contents
|
313 | be5f0160 | Nikos Skalkotos | 0 4 Number of sectors in partition
|
314 | be5f0160 | Nikos Skalkotos | 4 4 Starting sector
|
315 | be5f0160 | Nikos Skalkotos | 8 4 Filesystem basic fragment size
|
316 | be5f0160 | Nikos Skalkotos | 12 1 Filesystem type
|
317 | be5f0160 | Nikos Skalkotos | 13 1 Filesystem fragments per block
|
318 | be5f0160 | Nikos Skalkotos | 14 2 Filesystem cylinders per group
|
319 | be5f0160 | Nikos Skalkotos | """
|
320 | 34fd52a7 | Nikos Skalkotos | |
321 | be5f0160 | Nikos Skalkotos | Partition = namedtuple( |
322 | be5f0160 | Nikos Skalkotos | 'Partition', 'size, offset, fsize, fstype, frag, cpg') |
323 | be5f0160 | Nikos Skalkotos | |
324 | be5f0160 | Nikos Skalkotos | format = "<IHH16s16sIIIIIIHHIHHHHIII20s20sIHHII64s"
|
325 | de34e7aa | Nikos Skalkotos | """
|
326 | de34e7aa | Nikos Skalkotos | Offset Length Contents
|
327 | de34e7aa | Nikos Skalkotos | 0 4 Magic
|
328 | de34e7aa | Nikos Skalkotos | 4 2 Drive Type
|
329 | de34e7aa | Nikos Skalkotos | 6 2 Subtype
|
330 | de34e7aa | Nikos Skalkotos | 8 16 Type Name
|
331 | de34e7aa | Nikos Skalkotos | 24 16 Pack Identifier
|
332 | de34e7aa | Nikos Skalkotos | 32 4 Bytes per sector
|
333 | de34e7aa | Nikos Skalkotos | 36 4 Data sectors per track
|
334 | be5f0160 | Nikos Skalkotos | 40 4 Tracks per cylinder
|
335 | de34e7aa | Nikos Skalkotos | 44 4 Data cylinders per unit
|
336 | be5f0160 | Nikos Skalkotos | 48 4 Data sectors per cylinder
|
337 | de34e7aa | Nikos Skalkotos | 52 4 Data sectors per unit
|
338 | be5f0160 | Nikos Skalkotos | 56 2 Spare sectors per track
|
339 | be5f0160 | Nikos Skalkotos | 58 2 Spare sectors per cylinder
|
340 | be5f0160 | Nikos Skalkotos | 60 4 Alternative cylinders per unit
|
341 | be5f0160 | Nikos Skalkotos | 64 2 Rotation Speed
|
342 | be5f0160 | Nikos Skalkotos | 66 2 Hardware sector interleave
|
343 | be5f0160 | Nikos Skalkotos | 68 2 Sector 0 skew, per track
|
344 | be5f0160 | Nikos Skalkotos | 70 2 Sector 0 skew, per cylinder
|
345 | be5f0160 | Nikos Skalkotos | 72 4 Head switch time
|
346 | be5f0160 | Nikos Skalkotos | 76 4 Track-to-track seek
|
347 | de34e7aa | Nikos Skalkotos | 80 4 Generic Flags
|
348 | de34e7aa | Nikos Skalkotos | 84 5*4 Drive-type specific information
|
349 | be5f0160 | Nikos Skalkotos | 104 5*4 Reserved for future use
|
350 | be5f0160 | Nikos Skalkotos | 124 4 Magic Number
|
351 | be5f0160 | Nikos Skalkotos | 128 2 Xor of data including partitions
|
352 | be5f0160 | Nikos Skalkotos | 130 2 Number of partitions following
|
353 | de34e7aa | Nikos Skalkotos | 132 4 size of boot area at sn0, bytes
|
354 | de34e7aa | Nikos Skalkotos | 136 4 Max size of fs superblock, bytes
|
355 | de34e7aa | Nikos Skalkotos | 140 16*16 Partition Table
|
356 | de34e7aa | Nikos Skalkotos | """
|
357 | de34e7aa | Nikos Skalkotos | |
358 | be5f0160 | Nikos Skalkotos | |
359 | 63656985 | Nikos Skalkotos | class OpenBSD_Disklabel(DisklabelBase): |
360 | be5f0160 | Nikos Skalkotos | """Represents an OpenBSD Disklabel"""
|
361 | be5f0160 | Nikos Skalkotos | |
362 | be5f0160 | Nikos Skalkotos | class PartitionTable(PartitionTableBase): |
363 | de34e7aa | Nikos Skalkotos | """Reprepsents an OpenBSD Partition Table"""
|
364 | de34e7aa | Nikos Skalkotos | format = "<IIHHBBH"
|
365 | de34e7aa | Nikos Skalkotos | """
|
366 | de34e7aa | Nikos Skalkotos | Partition Entry:
|
367 | de34e7aa | Nikos Skalkotos | Offset Length Contents
|
368 | de34e7aa | Nikos Skalkotos | 0 4 Number of sectors in the partition
|
369 | de34e7aa | Nikos Skalkotos | 4 4 Starting sector
|
370 | de34e7aa | Nikos Skalkotos | 8 2 Starting sector (high part)
|
371 | de34e7aa | Nikos Skalkotos | 10 2 Number of sectors (high part)
|
372 | de34e7aa | Nikos Skalkotos | 12 1 Filesystem type
|
373 | de34e7aa | Nikos Skalkotos | 13 1 Filesystem Fragment per block
|
374 | de34e7aa | Nikos Skalkotos | 14 2 FS cylinders per group
|
375 | de34e7aa | Nikos Skalkotos | """
|
376 | de34e7aa | Nikos Skalkotos | |
377 | de34e7aa | Nikos Skalkotos | Partition = namedtuple( |
378 | de34e7aa | Nikos Skalkotos | 'Partition', 'size, offset, offseth, sizeh, fstype, frag, cpg') |
379 | de34e7aa | Nikos Skalkotos | |
380 | de34e7aa | Nikos Skalkotos | def setpsize(self, i, size): |
381 | de34e7aa | Nikos Skalkotos | """Set size for partition i"""
|
382 | de34e7aa | Nikos Skalkotos | tmp = self.part[i]
|
383 | de34e7aa | Nikos Skalkotos | self.part[i] = self.Partition(size & 0xffffffff, tmp.offset, |
384 | de34e7aa | Nikos Skalkotos | tmp.offseth, size >> 32, tmp.fstype,
|
385 | de34e7aa | Nikos Skalkotos | tmp.frag, tmp.cpg) |
386 | de34e7aa | Nikos Skalkotos | |
387 | de34e7aa | Nikos Skalkotos | def getpsize(self, i): |
388 | 34fd52a7 | Nikos Skalkotos | """Get size for partition i"""
|
389 | de34e7aa | Nikos Skalkotos | return (self.part[i].sizeh << 32) + self.part[i].size |
390 | de34e7aa | Nikos Skalkotos | |
391 | de34e7aa | Nikos Skalkotos | def setpoffset(self, i, offset): |
392 | 34fd52a7 | Nikos Skalkotos | """Set offset for partition i"""
|
393 | de34e7aa | Nikos Skalkotos | tmp = self.part[i]
|
394 | de34e7aa | Nikos Skalkotos | self.part[i] = self.Partition(tmp.size, offset & 0xffffffff, |
395 | de34e7aa | Nikos Skalkotos | offset >> 32, tmp.sizeh, tmp.frag,
|
396 | de34e7aa | Nikos Skalkotos | tmp.cpg) |
397 | de34e7aa | Nikos Skalkotos | |
398 | de34e7aa | Nikos Skalkotos | def getpoffset(self, i): |
399 | 34fd52a7 | Nikos Skalkotos | """Get offset for partition i"""
|
400 | de34e7aa | Nikos Skalkotos | return (self.part[i].offseth << 32) + self.part[i].offset |
401 | de34e7aa | Nikos Skalkotos | |
402 | be5f0160 | Nikos Skalkotos | format = "<IHH16s16sIIIIII8sIHHIII20sHH16sIHHII364s"
|
403 | be5f0160 | Nikos Skalkotos | """
|
404 | be5f0160 | Nikos Skalkotos | Offset Length Contents
|
405 | be5f0160 | Nikos Skalkotos | 0 4 Magic
|
406 | be5f0160 | Nikos Skalkotos | 4 2 Drive Type
|
407 | be5f0160 | Nikos Skalkotos | 6 2 Subtype
|
408 | be5f0160 | Nikos Skalkotos | 8 16 Type Name
|
409 | be5f0160 | Nikos Skalkotos | 24 16 Pack Identifier
|
410 | be5f0160 | Nikos Skalkotos | 32 4 Bytes per sector
|
411 | be5f0160 | Nikos Skalkotos | 36 4 Data sectors per track
|
412 | be5f0160 | Nikos Skalkotos | 40 4 Tracks per cylinder
|
413 | be5f0160 | Nikos Skalkotos | 44 4 Data cylinders per unit
|
414 | be5f0160 | Nikos Skalkotos | 48 4 Data sectors per cylinder
|
415 | be5f0160 | Nikos Skalkotos | 52 4 Data sectors per unit
|
416 | be5f0160 | Nikos Skalkotos | 56 8 Unique label identifier
|
417 | be5f0160 | Nikos Skalkotos | 64 4 Alt cylinders per unit
|
418 | be5f0160 | Nikos Skalkotos | 68 2 Start of useable region (high part)
|
419 | be5f0160 | Nikos Skalkotos | 70 2 Size of usable region (high part)
|
420 | be5f0160 | Nikos Skalkotos | 72 4 Start of useable region
|
421 | be5f0160 | Nikos Skalkotos | 76 4 End of usable region
|
422 | be5f0160 | Nikos Skalkotos | 80 4 Generic Flags
|
423 | be5f0160 | Nikos Skalkotos | 84 5*4 Drive-type specific information
|
424 | be5f0160 | Nikos Skalkotos | 104 2 Number of data sectors (high part)
|
425 | be5f0160 | Nikos Skalkotos | 106 2 Version
|
426 | be5f0160 | Nikos Skalkotos | 108 4*4 Reserved for future use
|
427 | be5f0160 | Nikos Skalkotos | 124 4 Magic number
|
428 | be5f0160 | Nikos Skalkotos | 128 2 Xor of data including partitions
|
429 | be5f0160 | Nikos Skalkotos | 130 2 Number of partitions in following
|
430 | be5f0160 | Nikos Skalkotos | 132 4 size of boot area at sn0, bytes
|
431 | be5f0160 | Nikos Skalkotos | 136 4 Max size of fs superblock, bytes
|
432 | be5f0160 | Nikos Skalkotos | 140 16*16 Partition Table
|
433 | be5f0160 | Nikos Skalkotos | """
|
434 | 34fd52a7 | Nikos Skalkotos | def __init__(self, device): |
435 | 34fd52a7 | Nikos Skalkotos | """Create a DiskLabel instance"""
|
436 | de34e7aa | Nikos Skalkotos | |
437 | 34fd52a7 | Nikos Skalkotos | device.seek(BLOCKSIZE, os.SEEK_CUR) |
438 | 34fd52a7 | Nikos Skalkotos | # The offset of the disklabel from the beginning of the partition is
|
439 | 34fd52a7 | Nikos Skalkotos | # one sector
|
440 | 34fd52a7 | Nikos Skalkotos | sector1 = device.read(BLOCKSIZE) |
441 | de34e7aa | Nikos Skalkotos | |
442 | de34e7aa | Nikos Skalkotos | (self.magic,
|
443 | de34e7aa | Nikos Skalkotos | self.dtype,
|
444 | de34e7aa | Nikos Skalkotos | self.subtype,
|
445 | de34e7aa | Nikos Skalkotos | self.typename,
|
446 | de34e7aa | Nikos Skalkotos | self.packname,
|
447 | de34e7aa | Nikos Skalkotos | self.secsize,
|
448 | de34e7aa | Nikos Skalkotos | self.nsectors,
|
449 | de34e7aa | Nikos Skalkotos | self.ntracks,
|
450 | de34e7aa | Nikos Skalkotos | self.ncylinders,
|
451 | de34e7aa | Nikos Skalkotos | self.secpercyl,
|
452 | de34e7aa | Nikos Skalkotos | self.secperunit,
|
453 | de34e7aa | Nikos Skalkotos | self.uid,
|
454 | de34e7aa | Nikos Skalkotos | self.acylinders,
|
455 | de34e7aa | Nikos Skalkotos | self.bstarth,
|
456 | de34e7aa | Nikos Skalkotos | self.bendh,
|
457 | de34e7aa | Nikos Skalkotos | self.bstart,
|
458 | de34e7aa | Nikos Skalkotos | self.bend,
|
459 | de34e7aa | Nikos Skalkotos | self.flags,
|
460 | de34e7aa | Nikos Skalkotos | self.drivedata,
|
461 | de34e7aa | Nikos Skalkotos | self.secperunith,
|
462 | de34e7aa | Nikos Skalkotos | self.version,
|
463 | de34e7aa | Nikos Skalkotos | self.spare,
|
464 | de34e7aa | Nikos Skalkotos | self.magic2,
|
465 | de34e7aa | Nikos Skalkotos | self.checksum,
|
466 | de34e7aa | Nikos Skalkotos | self.npartitions,
|
467 | de34e7aa | Nikos Skalkotos | self.bbsize,
|
468 | de34e7aa | Nikos Skalkotos | self.sbsize,
|
469 | 34fd52a7 | Nikos Skalkotos | ptable_raw) = struct.unpack(self.format, sector1)
|
470 | de34e7aa | Nikos Skalkotos | |
471 | be5f0160 | Nikos Skalkotos | assert self.magic == DISKMAGIC, "Disklabel is not valid" |
472 | de34e7aa | Nikos Skalkotos | |
473 | de34e7aa | Nikos Skalkotos | self.ptable = self.PartitionTable(ptable_raw, self.npartitions) |
474 | de34e7aa | Nikos Skalkotos | |
475 | de34e7aa | Nikos Skalkotos | def pack(self, checksum=None): |
476 | de34e7aa | Nikos Skalkotos | return struct.pack(self.format, |
477 | de34e7aa | Nikos Skalkotos | self.magic,
|
478 | de34e7aa | Nikos Skalkotos | self.dtype,
|
479 | de34e7aa | Nikos Skalkotos | self.subtype,
|
480 | de34e7aa | Nikos Skalkotos | self.typename,
|
481 | de34e7aa | Nikos Skalkotos | self.packname,
|
482 | de34e7aa | Nikos Skalkotos | self.secsize,
|
483 | de34e7aa | Nikos Skalkotos | self.nsectors,
|
484 | de34e7aa | Nikos Skalkotos | self.ntracks,
|
485 | de34e7aa | Nikos Skalkotos | self.ncylinders,
|
486 | de34e7aa | Nikos Skalkotos | self.secpercyl,
|
487 | de34e7aa | Nikos Skalkotos | self.secperunit,
|
488 | de34e7aa | Nikos Skalkotos | self.uid,
|
489 | de34e7aa | Nikos Skalkotos | self.acylinders,
|
490 | de34e7aa | Nikos Skalkotos | self.bstarth,
|
491 | de34e7aa | Nikos Skalkotos | self.bendh,
|
492 | de34e7aa | Nikos Skalkotos | self.bstart,
|
493 | de34e7aa | Nikos Skalkotos | self.bend,
|
494 | de34e7aa | Nikos Skalkotos | self.flags,
|
495 | de34e7aa | Nikos Skalkotos | self.drivedata,
|
496 | de34e7aa | Nikos Skalkotos | self.secperunith,
|
497 | de34e7aa | Nikos Skalkotos | self.version,
|
498 | de34e7aa | Nikos Skalkotos | self.spare,
|
499 | de34e7aa | Nikos Skalkotos | self.magic2,
|
500 | de34e7aa | Nikos Skalkotos | self.checksum if checksum is None else checksum, |
501 | de34e7aa | Nikos Skalkotos | self.npartitions,
|
502 | de34e7aa | Nikos Skalkotos | self.bbsize,
|
503 | de34e7aa | Nikos Skalkotos | self.sbsize,
|
504 | de34e7aa | Nikos Skalkotos | self.ptable.pack() +
|
505 | ee78390c | Nikos Skalkotos | ((364 - self.npartitions * 16) * '\x00')) |
506 | de34e7aa | Nikos Skalkotos | |
507 | de34e7aa | Nikos Skalkotos | def setdsize(self, dsize): |
508 | de34e7aa | Nikos Skalkotos | """Set disk size"""
|
509 | de34e7aa | Nikos Skalkotos | self.secperunith = dsize >> 32 |
510 | de34e7aa | Nikos Skalkotos | self.secperunit = dsize & 0xffffffff |
511 | de34e7aa | Nikos Skalkotos | |
512 | de34e7aa | Nikos Skalkotos | def getdsize(self): |
513 | de34e7aa | Nikos Skalkotos | """Get disk size"""
|
514 | de34e7aa | Nikos Skalkotos | return (self.secperunith << 32) + self.secperunit |
515 | de34e7aa | Nikos Skalkotos | |
516 | de34e7aa | Nikos Skalkotos | def setbstart(self, bstart): |
517 | de34e7aa | Nikos Skalkotos | """Set start of useable region"""
|
518 | de34e7aa | Nikos Skalkotos | self.bstarth = bstart >> 32 |
519 | de34e7aa | Nikos Skalkotos | self.bstart = bstart & 0xffffffff |
520 | de34e7aa | Nikos Skalkotos | |
521 | de34e7aa | Nikos Skalkotos | def getbstart(self): |
522 | de34e7aa | Nikos Skalkotos | """Get start of usable region"""
|
523 | de34e7aa | Nikos Skalkotos | return (self.bstarth << 32) + self.bstart |
524 | de34e7aa | Nikos Skalkotos | |
525 | de34e7aa | Nikos Skalkotos | def setbend(self, bend): |
526 | 34fd52a7 | Nikos Skalkotos | """Set size of useable region"""
|
527 | de34e7aa | Nikos Skalkotos | self.bendh = bend >> 32 |
528 | de34e7aa | Nikos Skalkotos | self.bend = bend & 0xffffffff |
529 | de34e7aa | Nikos Skalkotos | |
530 | de34e7aa | Nikos Skalkotos | def getbend(self): |
531 | 34fd52a7 | Nikos Skalkotos | """Get size of usable region"""
|
532 | de34e7aa | Nikos Skalkotos | return (self.bendh << 32) + self.bend |
533 | de34e7aa | Nikos Skalkotos | |
534 | be5f0160 | Nikos Skalkotos | def enlarge(self, new_size): |
535 | 63656985 | Nikos Skalkotos | """Enlarge the disk and return the last usable sector"""
|
536 | de34e7aa | Nikos Skalkotos | |
537 | 34fd52a7 | Nikos Skalkotos | assert new_size >= self.getdsize(), \ |
538 | 34fd52a7 | Nikos Skalkotos | "New size cannot be smaller that %s" % self.getdsize() |
539 | de34e7aa | Nikos Skalkotos | |
540 | de34e7aa | Nikos Skalkotos | # Fix the disklabel
|
541 | de34e7aa | Nikos Skalkotos | self.setdsize(new_size)
|
542 | de34e7aa | Nikos Skalkotos | self.ncylinders = self.getdsize() // (self.nsectors * self.ntracks) |
543 | de34e7aa | Nikos Skalkotos | self.setbend(self.ncylinders * self.nsectors * self.ntracks) |
544 | de34e7aa | Nikos Skalkotos | |
545 | de34e7aa | Nikos Skalkotos | # Partition 'c' descriptes the entire disk
|
546 | de34e7aa | Nikos Skalkotos | self.ptable.setpsize(2, new_size) |
547 | de34e7aa | Nikos Skalkotos | |
548 | 34fd52a7 | Nikos Skalkotos | # Update the checksum
|
549 | de34e7aa | Nikos Skalkotos | self.checksum = self.compute_checksum() |
550 | de34e7aa | Nikos Skalkotos | |
551 | 34fd52a7 | Nikos Skalkotos | # getbend() gives back the size of the usable region and not the end of
|
552 | 34fd52a7 | Nikos Skalkotos | # the usable region. I named it like this because this is how it is
|
553 | 34fd52a7 | Nikos Skalkotos | # named in OpenBSD. To get the last usable sector you need to reduce
|
554 | 34fd52a7 | Nikos Skalkotos | # this value by one.
|
555 | 34fd52a7 | Nikos Skalkotos | return self.getbend() - 1 |
556 | 34fd52a7 | Nikos Skalkotos | |
557 | 34fd52a7 | Nikos Skalkotos | def write_to(self, device): |
558 | 34fd52a7 | Nikos Skalkotos | """Write the disklabel to a device"""
|
559 | de34e7aa | Nikos Skalkotos | |
560 | 34fd52a7 | Nikos Skalkotos | # The disklabel starts at sector 1
|
561 | 34fd52a7 | Nikos Skalkotos | device.seek(BLOCKSIZE, os.SEEK_CUR) |
562 | 34fd52a7 | Nikos Skalkotos | device.write(self.pack())
|
563 | de34e7aa | Nikos Skalkotos | |
564 | de34e7aa | Nikos Skalkotos | def get_last_partition_id(self): |
565 | de34e7aa | Nikos Skalkotos | """Returns the id of the last partition"""
|
566 | de34e7aa | Nikos Skalkotos | part = 0
|
567 | de34e7aa | Nikos Skalkotos | end = 0
|
568 | de34e7aa | Nikos Skalkotos | # Don't check partition 'c' which is the whole disk
|
569 | de34e7aa | Nikos Skalkotos | for i in filter(lambda x: x != 2, range(self.npartitions)): |
570 | de34e7aa | Nikos Skalkotos | curr_end = self.ptable.getpsize(i) + self.ptable.getpoffset(i) |
571 | de34e7aa | Nikos Skalkotos | if end < curr_end:
|
572 | de34e7aa | Nikos Skalkotos | end = curr_end |
573 | de34e7aa | Nikos Skalkotos | part = i |
574 | de34e7aa | Nikos Skalkotos | |
575 | de34e7aa | Nikos Skalkotos | assert end > 0, "No partition found" |
576 | de34e7aa | Nikos Skalkotos | |
577 | de34e7aa | Nikos Skalkotos | return part
|
578 | de34e7aa | Nikos Skalkotos | |
579 | de34e7aa | Nikos Skalkotos | def enlarge_last_partition(self): |
580 | de34e7aa | Nikos Skalkotos | """Enlarge the last partition to cover up all the free space"""
|
581 | de34e7aa | Nikos Skalkotos | |
582 | de34e7aa | Nikos Skalkotos | part_num = self.get_last_partition_id()
|
583 | de34e7aa | Nikos Skalkotos | |
584 | de34e7aa | Nikos Skalkotos | end = self.ptable.getpsize(part_num) + self.ptable.getpoffset(part_num) |
585 | de34e7aa | Nikos Skalkotos | |
586 | de34e7aa | Nikos Skalkotos | assert end > 0, "No partition found" |
587 | de34e7aa | Nikos Skalkotos | |
588 | de34e7aa | Nikos Skalkotos | if self.ptable.part[part_num].fstype == 1: # Swap partition. |
589 | de34e7aa | Nikos Skalkotos | #TODO: Maybe create a warning?
|
590 | de34e7aa | Nikos Skalkotos | return
|
591 | de34e7aa | Nikos Skalkotos | |
592 | de34e7aa | Nikos Skalkotos | if end > (self.getbend() - 1024): |
593 | de34e7aa | Nikos Skalkotos | return
|
594 | de34e7aa | Nikos Skalkotos | |
595 | de34e7aa | Nikos Skalkotos | self.ptable.setpsize(
|
596 | de34e7aa | Nikos Skalkotos | part_num, self.getbend() - self.ptable.getpoffset(part_num) - 1024) |
597 | de34e7aa | Nikos Skalkotos | |
598 | de34e7aa | Nikos Skalkotos | self.checksum = self.compute_checksum() |
599 | de34e7aa | Nikos Skalkotos | |
600 | de34e7aa | Nikos Skalkotos | def __str__(self): |
601 | de34e7aa | Nikos Skalkotos | """Print the Disklabel"""
|
602 | de34e7aa | Nikos Skalkotos | |
603 | 34fd52a7 | Nikos Skalkotos | title = "Disklabel"
|
604 | de34e7aa | Nikos Skalkotos | return \
|
605 | 34fd52a7 | Nikos Skalkotos | "%s\n%s\n" % (title, len(title) * "=") + \ |
606 | de34e7aa | Nikos Skalkotos | "Magic Number: 0x%x\n" % self.magic + \ |
607 | de34e7aa | Nikos Skalkotos | "Drive type: %d\n" % self.dtype + \ |
608 | de34e7aa | Nikos Skalkotos | "Subtype: %d\n" % self.subtype + \ |
609 | abe2770c | Nikos Skalkotos | "Typename: %s\n" % self.typename.strip('\x00').strip() + \ |
610 | abe2770c | Nikos Skalkotos | "Pack Identifier: %s\n" % self.packname.strip('\x00').strip() + \ |
611 | de34e7aa | Nikos Skalkotos | "Number of bytes per sector: %d\n" % self.secsize + \ |
612 | de34e7aa | Nikos Skalkotos | "Number of data sectors per track: %d\n" % self.nsectors + \ |
613 | de34e7aa | Nikos Skalkotos | "Number of tracks per cylinder: %d\n" % self.ntracks + \ |
614 | de34e7aa | Nikos Skalkotos | "Number of data cylinders per unit: %d\n" % self.ncylinders + \ |
615 | de34e7aa | Nikos Skalkotos | "Number of data sectors per cylinder: %d\n" % self.secpercyl + \ |
616 | de34e7aa | Nikos Skalkotos | "Number of data sectors per unit: %d\n" % self.secperunit + \ |
617 | de34e7aa | Nikos Skalkotos | "DUID: %s\n" % "".join(x.encode('hex') for x in self.uid) + \ |
618 | de34e7aa | Nikos Skalkotos | "Alt. cylinders per unit: %d\n" % self.acylinders + \ |
619 | de34e7aa | Nikos Skalkotos | "Start of useable region (high part): %d\n" % self.bstarth + \ |
620 | de34e7aa | Nikos Skalkotos | "Size of useable region (high part): %d\n" % self.bendh + \ |
621 | de34e7aa | Nikos Skalkotos | "Start of useable region: %d\n" % self.bstart + \ |
622 | de34e7aa | Nikos Skalkotos | "End of usable region: %d\n" % self.bend + \ |
623 | de34e7aa | Nikos Skalkotos | "Generic Flags: %r\n" % self.flags + \ |
624 | de34e7aa | Nikos Skalkotos | "Drive data: %r\n" % self.drivedata + \ |
625 | de34e7aa | Nikos Skalkotos | "Number of data sectors (high part): %d\n" % self.secperunith + \ |
626 | de34e7aa | Nikos Skalkotos | "Version: %d\n" % self.version + \ |
627 | de34e7aa | Nikos Skalkotos | "Reserved for future use: %r\n" % self.spare + \ |
628 | de34e7aa | Nikos Skalkotos | "The magic number again: 0x%x\n" % self.magic2 + \ |
629 | de34e7aa | Nikos Skalkotos | "Checksum: %d\n" % self.checksum + \ |
630 | de34e7aa | Nikos Skalkotos | "Number of partitions: %d\n" % self.npartitions + \ |
631 | de34e7aa | Nikos Skalkotos | "Size of boot aread at sn0: %d\n" % self.bbsize + \ |
632 | de34e7aa | Nikos Skalkotos | "Max size of fs superblock: %d\n" % self.sbsize + \ |
633 | de34e7aa | Nikos Skalkotos | "%s" % self.ptable |
634 | de34e7aa | Nikos Skalkotos | |
635 | de34e7aa | Nikos Skalkotos | |
636 | de34e7aa | Nikos Skalkotos | if __name__ == '__main__': |
637 | de34e7aa | Nikos Skalkotos | |
638 | de34e7aa | Nikos Skalkotos | usage = "Usage: %prog [options] <input_media>"
|
639 | de34e7aa | Nikos Skalkotos | parser = optparse.OptionParser(usage=usage) |
640 | de34e7aa | Nikos Skalkotos | |
641 | de34e7aa | Nikos Skalkotos | parser.add_option("-l", "--list", action="store_true", dest="list", |
642 | de34e7aa | Nikos Skalkotos | default=False,
|
643 | de34e7aa | Nikos Skalkotos | help="list the disklabel on the specified media")
|
644 | 1de1eff5 | Nikos Skalkotos | parser.add_option("--get-last-partition", action="store_true", |
645 | 1de1eff5 | Nikos Skalkotos | dest="last_part", default=False, |
646 | de34e7aa | Nikos Skalkotos | help="print the label of the last partition")
|
647 | 1de1eff5 | Nikos Skalkotos | parser.add_option("--get-duid", action="store_true", dest="duid", |
648 | de34e7aa | Nikos Skalkotos | default=False,
|
649 | de34e7aa | Nikos Skalkotos | help="print the disklabel unique identifier")
|
650 | de34e7aa | Nikos Skalkotos | parser.add_option("-d", "--enlarge-disk", type="int", dest="disk_size", |
651 | de34e7aa | Nikos Skalkotos | default=None, metavar="SIZE", |
652 | de34e7aa | Nikos Skalkotos | help="Enlarge the disk to this SIZE (in sectors)")
|
653 | de34e7aa | Nikos Skalkotos | parser.add_option( |
654 | de34e7aa | Nikos Skalkotos | "-p", "--enlarge-partition", action="store_true", |
655 | de34e7aa | Nikos Skalkotos | dest="enlarge_partition", default=False, |
656 | de34e7aa | Nikos Skalkotos | help="Enlarge the last partition to cover up the free space")
|
657 | de34e7aa | Nikos Skalkotos | |
658 | de34e7aa | Nikos Skalkotos | options, args = parser.parse_args(sys.argv[1:])
|
659 | de34e7aa | Nikos Skalkotos | |
660 | de34e7aa | Nikos Skalkotos | if len(args) != 1: |
661 | de34e7aa | Nikos Skalkotos | parser.error("Wrong number of arguments")
|
662 | de34e7aa | Nikos Skalkotos | |
663 | be5f0160 | Nikos Skalkotos | disk = Disk(args[0])
|
664 | de34e7aa | Nikos Skalkotos | |
665 | de34e7aa | Nikos Skalkotos | if options.list:
|
666 | be5f0160 | Nikos Skalkotos | print disk
|
667 | de34e7aa | Nikos Skalkotos | sys.exit(0)
|
668 | de34e7aa | Nikos Skalkotos | |
669 | de34e7aa | Nikos Skalkotos | if options.duid:
|
670 | be5f0160 | Nikos Skalkotos | print "%s" % "".join(x.encode('hex') for x in disk.uid) |
671 | de34e7aa | Nikos Skalkotos | sys.exit(0)
|
672 | de34e7aa | Nikos Skalkotos | |
673 | de34e7aa | Nikos Skalkotos | if options.last_part:
|
674 | be5f0160 | Nikos Skalkotos | print "%c" % chr(ord('a') + disk.get_last_partition_id()) |
675 | de34e7aa | Nikos Skalkotos | |
676 | de34e7aa | Nikos Skalkotos | if options.disk_size is not None: |
677 | be5f0160 | Nikos Skalkotos | disk.enlarge(options.disk_size) |
678 | de34e7aa | Nikos Skalkotos | |
679 | de34e7aa | Nikos Skalkotos | if options.enlarge_partition:
|
680 | be5f0160 | Nikos Skalkotos | disk.enlarge_last_partition() |
681 | de34e7aa | Nikos Skalkotos | |
682 | be5f0160 | Nikos Skalkotos | disk.write() |
683 | de34e7aa | Nikos Skalkotos | |
684 | de34e7aa | Nikos Skalkotos | sys.exit(0)
|
685 | de34e7aa | Nikos Skalkotos | |
686 | de34e7aa | Nikos Skalkotos | # vim: set sta sts=4 shiftwidth=4 sw=4 et ai : |