Revision 501e19ec
b/snf-image-helper/disklabel.py | ||
---|---|---|
28 | 28 |
import optparse |
29 | 29 |
|
30 | 30 |
from collections import namedtuple |
31 |
from collections import OrderedDict |
|
31 | 32 |
|
32 | 33 |
BLOCKSIZE = 512 |
33 | 34 |
|
... | ... | |
48 | 49 |
|
49 | 50 |
def __init__(self, raw_part): |
50 | 51 |
"""Create a Partition instance""" |
51 |
( |
|
52 |
self.status, |
|
53 |
self.start, |
|
54 |
self.type, |
|
55 |
self.end, |
|
56 |
self.first_sector, |
|
57 |
self.sector_count |
|
58 |
) = struct.unpack(self.format, raw_part) |
|
52 |
(self.status, |
|
53 |
self.start, |
|
54 |
self.type, |
|
55 |
self.end, |
|
56 |
self.first_sector, |
|
57 |
self.sector_count |
|
58 |
) = struct.unpack(self.format, raw_part) |
|
59 | 59 |
|
60 | 60 |
def pack(self): |
61 | 61 |
"""Pack the partition values into a binary string""" |
... | ... | |
163 | 163 |
return "%s\n%s\n%s\n" % (title, len(title) * "=", ret) |
164 | 164 |
|
165 | 165 |
|
166 |
class PartitionTableBase(object): |
|
167 |
"""Base Class for disklabel partition tables""" |
|
168 |
format = "" |
|
169 |
|
|
170 |
Partition = namedtuple('Partition', '') |
|
171 |
|
|
172 |
def __init__(self, ptable, pnumber): |
|
173 |
"""Create a Partition Table instance""" |
|
174 |
self.part = [] |
|
175 |
|
|
176 |
size = struct.calcsize(self.format) |
|
177 |
|
|
178 |
raw = cStringIO.StringIO(ptable) |
|
179 |
try: |
|
180 |
for i in range(pnumber): |
|
181 |
p = self.Partition( |
|
182 |
*struct.unpack(self.format, raw.read(size))) |
|
183 |
self.part.append(p) |
|
184 |
finally: |
|
185 |
raw.close() |
|
186 |
|
|
187 |
def __str__(self): |
|
188 |
"""Print the Partition table""" |
|
189 |
val = "" |
|
190 |
for i in range(len(self.part)): |
|
191 |
val += "%c: %s\n" % (chr(ord('a') + i), str(self.part[i])) |
|
192 |
return val |
|
193 |
|
|
194 |
def pack(self): |
|
195 |
"""Packs the partition table into a binary string.""" |
|
196 |
ret = "" |
|
197 |
for i in range(len(self.part)): |
|
198 |
ret += struct.pack(self.format, *self.part[i]) |
|
199 |
return ret |
|
200 |
|
|
201 |
|
|
202 | 166 |
class Disk(object): |
203 | 167 |
"""Represents an BSD Disk""" |
204 | 168 |
|
... | ... | |
248 | 212 |
start = self.mbr.part[self.part_num].first_sector |
249 | 213 |
self.mbr.part[self.part_num].sector_count = end - start + 1 |
250 | 214 |
|
251 |
cylinder = end // (self.disklabel.ntracks * self.disklabel.nsectors) |
|
252 |
header = (end // self.disklabel.nsectors) % self.disklabel.ntracks |
|
253 |
sector = (end % self.disklabel.nsectors) + 1 |
|
215 |
ntracks = self.disklabel.field['ntracks'] |
|
216 |
nsectors = self.disklabel.field['nsectors'] |
|
217 |
|
|
218 |
cylinder = end // (ntracks * nsectors) |
|
219 |
header = (end // nsectors) % ntracks |
|
220 |
sector = (end % nsectors) + 1 |
|
254 | 221 |
chs = MBR.Partition.pack_chs(cylinder, header, sector) |
255 | 222 |
self.mbr.part[self.part_num].end = chs |
256 | 223 |
|
257 | 224 |
def enlarge_last_partition(self): |
225 |
"""Enlarge the last partition to cover up all the free space""" |
|
258 | 226 |
self.disklabel.enlarge_last_partition() |
259 | 227 |
|
228 |
def get_last_partition_id(self): |
|
229 |
"""Get the ID of the last partition""" |
|
230 |
return self.disklabel.get_last_partition_id() |
|
231 |
|
|
232 |
def get_duid(self): |
|
233 |
return self.disklabel.field['uid'] |
|
234 |
|
|
260 | 235 |
|
261 | 236 |
class DisklabelBase(object): |
262 | 237 |
"""Disklabel base class""" |
... | ... | |
267 | 242 |
|
268 | 243 |
def pack(self, checksum=None): |
269 | 244 |
"""Return a binary copy of the Disklabel block""" |
270 |
raise NotImplementedError |
|
245 |
|
|
246 |
out = OrderedDict() |
|
247 |
for k, v in self.field.items(): |
|
248 |
out[k] = v |
|
249 |
|
|
250 |
if checksum is not None: |
|
251 |
out['checksum'] = checksum |
|
252 |
|
|
253 |
return struct.pack(self.format, * out.values() + [self.ptable.pack()]) |
|
271 | 254 |
|
272 | 255 |
def compute_checksum(self): |
273 | 256 |
"""Compute the checksum of the disklabel""" |
... | ... | |
290 | 273 |
|
291 | 274 |
def write_to(self, device): |
292 | 275 |
"""Write the disklabel to a device""" |
293 |
raise NotImplementedError |
|
276 |
|
|
277 |
# The disklabel starts at sector 1 |
|
278 |
device.seek(BLOCKSIZE, os.SEEK_CUR) |
|
279 |
device.write(self.pack()) |
|
294 | 280 |
|
295 | 281 |
def enlarge_last_partition(self): |
296 | 282 |
"""Enlarge the last partition to consume all the usable space""" |
297 | 283 |
raise NotImplementedError |
298 | 284 |
|
285 |
def get_last_partition_id(self): |
|
286 |
"""Get the ID of the last partition""" |
|
287 |
raise NotImplementedError |
|
288 |
|
|
299 | 289 |
def __str__(self): |
300 | 290 |
"""Print the Disklabel""" |
301 | 291 |
raise NotImplementedError |
302 | 292 |
|
303 | 293 |
|
294 |
class PartitionTableBase(object): |
|
295 |
"""Base Class for disklabel partition tables""" |
|
296 |
|
|
297 |
@property |
|
298 |
def format(self): |
|
299 |
"""Partition table format string""" |
|
300 |
raise NotImplementedError |
|
301 |
|
|
302 |
Partition = namedtuple('Partition', '') |
|
303 |
|
|
304 |
def __init__(self, ptable, pnumber): |
|
305 |
"""Create a Partition Table instance""" |
|
306 |
self.part = [] |
|
307 |
|
|
308 |
size = struct.calcsize(self.format) |
|
309 |
|
|
310 |
raw = cStringIO.StringIO(ptable) |
|
311 |
try: |
|
312 |
for i in range(pnumber): |
|
313 |
p = self.Partition( |
|
314 |
*struct.unpack(self.format, raw.read(size))) |
|
315 |
self.part.append(p) |
|
316 |
finally: |
|
317 |
raw.close() |
|
318 |
|
|
319 |
def __str__(self): |
|
320 |
"""Print the Partition table""" |
|
321 |
val = "" |
|
322 |
for i in range(len(self.part)): |
|
323 |
val += "%c: %s\n" % (chr(ord('a') + i), str(self.part[i])) |
|
324 |
return val |
|
325 |
|
|
326 |
def pack(self): |
|
327 |
"""Packs the partition table into a binary string.""" |
|
328 |
ret = "" |
|
329 |
for i in range(len(self.part)): |
|
330 |
ret += struct.pack(self.format, *self.part[i]) |
|
331 |
return ret + ((364 - len(self.part) * 16) * '\x00') |
|
332 |
|
|
333 |
|
|
304 | 334 |
class BSD_Disklabel(DisklabelBase): |
305 | 335 |
"""Represents an BSD Disklabel""" |
306 | 336 |
|
... | ... | |
321 | 351 |
Partition = namedtuple( |
322 | 352 |
'Partition', 'size, offset, fsize, fstype, frag, cpg') |
323 | 353 |
|
324 |
format = "<IHH16s16sIIIIIIHHIHHHHIII20s20sIHHII64s" |
|
354 |
format = "<IHH16s16sIIIIIIHHIHHHHIII20s20sIHHII364s"
|
|
325 | 355 |
""" |
326 | 356 |
Offset Length Contents |
327 | 357 |
0 4 Magic |
... | ... | |
362 | 392 |
class PartitionTable(PartitionTableBase): |
363 | 393 |
"""Reprepsents an OpenBSD Partition Table""" |
364 | 394 |
format = "<IIHHBBH" |
395 |
|
|
365 | 396 |
""" |
366 | 397 |
Partition Entry: |
367 | 398 |
Offset Length Contents |
... | ... | |
380 | 411 |
def setpsize(self, i, size): |
381 | 412 |
"""Set size for partition i""" |
382 | 413 |
tmp = self.part[i] |
383 |
self.part[i] = self.Partition(size & 0xffffffff, tmp.offset,
|
|
384 |
tmp.offseth, size >> 32, tmp.fstype,
|
|
385 |
tmp.frag, tmp.cpg)
|
|
414 |
self.part[i] = self.Partition( |
|
415 |
size & 0xffffffff, tmp.offset, tmp.offseth, size >> 32,
|
|
416 |
tmp.fstype, tmp.frag, tmp.cpg)
|
|
386 | 417 |
|
387 | 418 |
def getpsize(self, i): |
388 | 419 |
"""Get size for partition i""" |
... | ... | |
391 | 422 |
def setpoffset(self, i, offset): |
392 | 423 |
"""Set offset for partition i""" |
393 | 424 |
tmp = self.part[i] |
394 |
self.part[i] = self.Partition(tmp.size, offset & 0xffffffff,
|
|
395 |
offset >> 32, tmp.sizeh, tmp.frag,
|
|
396 |
tmp.cpg)
|
|
425 |
self.part[i] = self.Partition( |
|
426 |
tmp.size, offset & 0xffffffff, offset >> 32, tmp.sizeh,
|
|
427 |
tmp.frag, tmp.cpg)
|
|
397 | 428 |
|
398 | 429 |
def getpoffset(self, i): |
399 | 430 |
"""Get offset for partition i""" |
400 | 431 |
return (self.part[i].offseth << 32) + self.part[i].offset |
401 | 432 |
|
402 | 433 |
format = "<IHH16s16sIIIIII8sIHHIII20sHH16sIHHII364s" |
403 |
""" |
|
404 |
Offset Length Contents |
|
405 |
0 4 Magic |
|
406 |
4 2 Drive Type |
|
407 |
6 2 Subtype |
|
408 |
8 16 Type Name |
|
409 |
24 16 Pack Identifier |
|
410 |
32 4 Bytes per sector |
|
411 |
36 4 Data sectors per track |
|
412 |
40 4 Tracks per cylinder |
|
413 |
44 4 Data cylinders per unit |
|
414 |
48 4 Data sectors per cylinder |
|
415 |
52 4 Data sectors per unit |
|
416 |
56 8 Unique label identifier |
|
417 |
64 4 Alt cylinders per unit |
|
418 |
68 2 Start of useable region (high part) |
|
419 |
70 2 Size of usable region (high part) |
|
420 |
72 4 Start of useable region |
|
421 |
76 4 End of usable region |
|
422 |
80 4 Generic Flags |
|
423 |
84 5*4 Drive-type specific information |
|
424 |
104 2 Number of data sectors (high part) |
|
425 |
106 2 Version |
|
426 |
108 4*4 Reserved for future use |
|
427 |
124 4 Magic number |
|
428 |
128 2 Xor of data including partitions |
|
429 |
130 2 Number of partitions in following |
|
430 |
132 4 size of boot area at sn0, bytes |
|
431 |
136 4 Max size of fs superblock, bytes |
|
432 |
140 16*16 Partition Table |
|
433 |
""" |
|
434 |
|
|
434 | 435 |
def __init__(self, device): |
435 | 436 |
"""Create a DiskLabel instance""" |
436 | 437 |
|
... | ... | |
439 | 440 |
# one sector |
440 | 441 |
sector1 = device.read(BLOCKSIZE) |
441 | 442 |
|
442 |
(self.magic, |
|
443 |
self.dtype, |
|
444 |
self.subtype, |
|
445 |
self.typename, |
|
446 |
self.packname, |
|
447 |
self.secsize, |
|
448 |
self.nsectors, |
|
449 |
self.ntracks, |
|
450 |
self.ncylinders, |
|
451 |
self.secpercyl, |
|
452 |
self.secperunit, |
|
453 |
self.uid, |
|
454 |
self.acylinders, |
|
455 |
self.bstarth, |
|
456 |
self.bendh, |
|
457 |
self.bstart, |
|
458 |
self.bend, |
|
459 |
self.flags, |
|
460 |
self.drivedata, |
|
461 |
self.secperunith, |
|
462 |
self.version, |
|
463 |
self.spare, |
|
464 |
self.magic2, |
|
465 |
self.checksum, |
|
466 |
self.npartitions, |
|
467 |
self.bbsize, |
|
468 |
self.sbsize, |
|
469 |
ptable_raw) = struct.unpack(self.format, sector1) |
|
470 |
|
|
471 |
assert self.magic == DISKMAGIC, "Disklabel is not valid" |
|
472 |
|
|
473 |
self.ptable = self.PartitionTable(ptable_raw, self.npartitions) |
|
474 |
|
|
475 |
def pack(self, checksum=None): |
|
476 |
return struct.pack(self.format, |
|
477 |
self.magic, |
|
478 |
self.dtype, |
|
479 |
self.subtype, |
|
480 |
self.typename, |
|
481 |
self.packname, |
|
482 |
self.secsize, |
|
483 |
self.nsectors, |
|
484 |
self.ntracks, |
|
485 |
self.ncylinders, |
|
486 |
self.secpercyl, |
|
487 |
self.secperunit, |
|
488 |
self.uid, |
|
489 |
self.acylinders, |
|
490 |
self.bstarth, |
|
491 |
self.bendh, |
|
492 |
self.bstart, |
|
493 |
self.bend, |
|
494 |
self.flags, |
|
495 |
self.drivedata, |
|
496 |
self.secperunith, |
|
497 |
self.version, |
|
498 |
self.spare, |
|
499 |
self.magic2, |
|
500 |
self.checksum if checksum is None else checksum, |
|
501 |
self.npartitions, |
|
502 |
self.bbsize, |
|
503 |
self.sbsize, |
|
504 |
self.ptable.pack() + |
|
505 |
((364 - self.npartitions * 16) * '\x00')) |
|
443 |
d_ = OrderedDict() # Off Len Content |
|
444 |
(d_["magic"], # 0 4 Magic |
|
445 |
d_["dtype"], # 4 2 Drive Type |
|
446 |
d_["subtype"], # 6 2 Subtype |
|
447 |
d_["typename"], # 8 16 Type Name |
|
448 |
d_["packname"], # 24 16 Pack Identifier |
|
449 |
d_["secsize"], # 32 4 Bytes per sector |
|
450 |
d_["nsectors"], # 36 4 Data sectors per track |
|
451 |
d_["ntracks"], # 40 4 Tracks per cylinder |
|
452 |
d_["ncylinders"], # 44 4 Data cylinders per unit |
|
453 |
d_["secpercyl"], # 48 4 Data sectors per cylinder |
|
454 |
d_["secperunit"], # 52 4 Data sectors per unit |
|
455 |
d_["uid"], # 56 8 Unique label identifier |
|
456 |
d_["acylinders"], # 64 4 Alt cylinders per unit |
|
457 |
d_["bstarth"], # 68 2 Start of useable region (high part) |
|
458 |
d_["bendh"], # 70 2 Size of usable region (high part) |
|
459 |
d_["bstart"], # 72 4 Start of useable region |
|
460 |
d_["bend"], # 76 4 End of usable region |
|
461 |
d_["flags"], # 80 4 Generic Flags |
|
462 |
d_["drivedata"], # 84 5*4 Drive-type specific information |
|
463 |
d_["secperunith"], # 104 2 Number of data sectors (high part) |
|
464 |
d_["version"], # 106 2 Version |
|
465 |
d_["spare"], # 108 4*4 Reserved for future use |
|
466 |
d_["magic2"], # 124 4 Magic number |
|
467 |
d_["checksum"], # 128 2 Xor of data including partitions |
|
468 |
d_["npartitions"], # 130 2 Number of partitions in following |
|
469 |
d_["bbsize"], # 132 4 size of boot area at sn0, bytes |
|
470 |
d_["sbsize"], # 136 4 Max size of fs superblock, bytes |
|
471 |
ptable_raw # 140 16*16 Partition Table |
|
472 |
) = struct.unpack(self.format, sector1) |
|
473 |
|
|
474 |
assert d_['magic'] == d_['magic2'] == DISKMAGIC, "Disklabel not valid" |
|
475 |
self.ptable = self.PartitionTable(ptable_raw, d_['npartitions']) |
|
476 |
self.field = d_ |
|
506 | 477 |
|
507 | 478 |
def setdsize(self, dsize): |
508 | 479 |
"""Set disk size""" |
509 |
self.secperunith = dsize >> 32
|
|
510 |
self.secperunit = dsize & 0xffffffff
|
|
480 |
self.field['secperunith'] = dsize >> 32
|
|
481 |
self.field['secperunit'] = dsize & 0xffffffff
|
|
511 | 482 |
|
512 | 483 |
def getdsize(self): |
513 | 484 |
"""Get disk size""" |
514 |
return (self.secperunith << 32) + self.secperunit |
|
485 |
return (self.field['secperunith'] << 32) + self.field['secperunit'] |
|
486 |
|
|
487 |
dsize = property(getdsize, setdsize, None, "disk size") |
|
515 | 488 |
|
516 | 489 |
def setbstart(self, bstart): |
517 | 490 |
"""Set start of useable region""" |
518 |
self.bstarth = bstart >> 32
|
|
519 |
self.bstart = bstart & 0xffffffff
|
|
491 |
self.field['bstarth'] = bstart >> 32
|
|
492 |
self.field['bstart'] = bstart & 0xffffffff
|
|
520 | 493 |
|
521 | 494 |
def getbstart(self): |
522 | 495 |
"""Get start of usable region""" |
523 |
return (self.bstarth << 32) + self.bstart |
|
496 |
return (self.field['bstarth'] << 32) + self.field['bstart'] |
|
497 |
|
|
498 |
bstart = property(getbstart, setbstart, None, "usable region start") |
|
524 | 499 |
|
525 | 500 |
def setbend(self, bend): |
526 | 501 |
"""Set size of useable region""" |
527 |
self.bendh = bend >> 32
|
|
528 |
self.bend = bend & 0xffffffff
|
|
502 |
self.field['bendh'] = bend >> 32
|
|
503 |
self.field['bend'] = bend & 0xffffffff
|
|
529 | 504 |
|
530 | 505 |
def getbend(self): |
531 | 506 |
"""Get size of usable region""" |
532 |
return (self.bendh << 32) + self.bend |
|
507 |
return (self.field['bendh'] << 32) + self.field['bend'] |
|
508 |
|
|
509 |
bend = property(getbend, setbend, None, "usable region size") |
|
533 | 510 |
|
534 | 511 |
def enlarge(self, new_size): |
535 | 512 |
"""Enlarge the disk and return the last usable sector""" |
536 | 513 |
|
537 |
assert new_size >= self.getdsize(), \
|
|
538 |
"New size cannot be smaller that %s" % self.getdsize()
|
|
514 |
assert new_size >= self.dsize, \
|
|
515 |
"New size cannot be smaller that %s" % self.dsize
|
|
539 | 516 |
|
540 | 517 |
# Fix the disklabel |
541 |
self.setdsize(new_size) |
|
542 |
self.ncylinders = self.getdsize() // (self.nsectors * self.ntracks) |
|
543 |
self.setbend(self.ncylinders * self.nsectors * self.ntracks) |
|
518 |
self.dsize = new_size |
|
519 |
self.field['ncylinders'] = self.dsize // (self.field['nsectors'] * |
|
520 |
self.field['ntracks']) |
|
521 |
self.bend = (self.field['ncylinders'] * self.field['nsectors'] * |
|
522 |
self.field['ntracks']) |
|
544 | 523 |
|
545 | 524 |
# Partition 'c' descriptes the entire disk |
546 | 525 |
self.ptable.setpsize(2, new_size) |
... | ... | |
548 | 527 |
# Update the checksum |
549 | 528 |
self.checksum = self.compute_checksum() |
550 | 529 |
|
551 |
# getbend() gives back the size of the usable region and not the end of |
|
552 |
# the usable region. I named it like this because this is how it is |
|
553 |
# named in OpenBSD. To get the last usable sector you need to reduce |
|
554 |
# this value by one. |
|
555 |
return self.getbend() - 1 |
|
556 |
|
|
557 |
def write_to(self, device): |
|
558 |
"""Write the disklabel to a device""" |
|
559 |
|
|
560 |
# The disklabel starts at sector 1 |
|
561 |
device.seek(BLOCKSIZE, os.SEEK_CUR) |
|
562 |
device.write(self.pack()) |
|
530 |
# bend is the size and not the end of the usable region. I named it |
|
531 |
# like this because this is how it is named in OpenBSD. To get the last |
|
532 |
# usable sector you need to reduce this value by one. |
|
533 |
return self.bend - 1 |
|
563 | 534 |
|
564 | 535 |
def get_last_partition_id(self): |
565 | 536 |
"""Returns the id of the last partition""" |
566 | 537 |
part = 0 |
567 | 538 |
end = 0 |
568 | 539 |
# Don't check partition 'c' which is the whole disk |
569 |
for i in filter(lambda x: x != 2, range(self.npartitions)):
|
|
540 |
for i in filter(lambda x: x != 2, range(len(self.ptable.part))):
|
|
570 | 541 |
curr_end = self.ptable.getpsize(i) + self.ptable.getpoffset(i) |
571 | 542 |
if end < curr_end: |
572 | 543 |
end = curr_end |
... | ... | |
589 | 560 |
#TODO: Maybe create a warning? |
590 | 561 |
return |
591 | 562 |
|
592 |
if end > (self.getbend() - 1024):
|
|
563 |
if end > (self.bend - 1024):
|
|
593 | 564 |
return |
594 | 565 |
|
595 | 566 |
self.ptable.setpsize( |
596 |
part_num, self.getbend() - self.ptable.getpoffset(part_num) - 1024)
|
|
567 |
part_num, self.bend - self.ptable.getpoffset(part_num) - 1024)
|
|
597 | 568 |
|
598 |
self.checksum = self.compute_checksum()
|
|
569 |
self.field['checksum'] = self.compute_checksum()
|
|
599 | 570 |
|
600 | 571 |
def __str__(self): |
601 | 572 |
"""Print the Disklabel""" |
602 | 573 |
|
603 | 574 |
title = "Disklabel" |
575 |
typename = self.field['typename'].strip('\x00').strip() |
|
576 |
packname = self.field['packname'].strip('\x00').strip() |
|
577 |
duid = "".join(x.encode('hex') for x in self.field['uid']) |
|
604 | 578 |
return \ |
605 | 579 |
"%s\n%s\n" % (title, len(title) * "=") + \ |
606 |
"Magic Number: 0x%x\n" % self.magic + \
|
|
607 |
"Drive type: %d\n" % self.dtype + \
|
|
608 |
"Subtype: %d\n" % self.subtype + \
|
|
609 |
"Typename: %s\n" % self.typename.strip('\x00').strip() + \
|
|
610 |
"Pack Identifier: %s\n" % self.packname.strip('\x00').strip() + \
|
|
611 |
"Number of bytes per sector: %d\n" % self.secsize + \
|
|
612 |
"Number of data sectors per track: %d\n" % self.nsectors + \
|
|
613 |
"Number of tracks per cylinder: %d\n" % self.ntracks + \
|
|
614 |
"Number of data cylinders per unit: %d\n" % self.ncylinders + \
|
|
615 |
"Number of data sectors per cylinder: %d\n" % self.secpercyl + \
|
|
616 |
"Number of data sectors per unit: %d\n" % self.secperunit + \
|
|
617 |
"DUID: %s\n" % "".join(x.encode('hex') for x in self.uid) + \
|
|
618 |
"Alt. cylinders per unit: %d\n" % self.acylinders + \
|
|
619 |
"Start of useable region (high part): %d\n" % self.bstarth + \
|
|
620 |
"Size of useable region (high part): %d\n" % self.bendh + \
|
|
621 |
"Start of useable region: %d\n" % self.bstart + \
|
|
622 |
"End of usable region: %d\n" % self.bend + \
|
|
623 |
"Generic Flags: %r\n" % self.flags + \
|
|
624 |
"Drive data: %r\n" % self.drivedata + \
|
|
625 |
"Number of data sectors (high part): %d\n" % self.secperunith + \
|
|
626 |
"Version: %d\n" % self.version + \
|
|
627 |
"Reserved for future use: %r\n" % self.spare + \
|
|
628 |
"The magic number again: 0x%x\n" % self.magic2 + \
|
|
629 |
"Checksum: %d\n" % self.checksum + \
|
|
630 |
"Number of partitions: %d\n" % self.npartitions + \
|
|
631 |
"Size of boot aread at sn0: %d\n" % self.bbsize + \
|
|
632 |
"Max size of fs superblock: %d\n" % self.sbsize + \
|
|
580 |
"Magic Number: 0x%(magic)x\n" \
|
|
581 |
"Drive type: %(dtype)d\n" \
|
|
582 |
"Subtype: %(subtype)d\n" % self.field + \
|
|
583 |
"Typename: %s\n" % typename + \
|
|
584 |
"Pack Identifier: %s\n" % packname + \
|
|
585 |
"# of bytes per sector: %(secsize)d\n" \
|
|
586 |
"# of data sectors per track: %(nsectors)d\n" \
|
|
587 |
"# of tracks per cylinder: %(ntracks)d\n" \
|
|
588 |
"# of data cylinders per unit: %(ncylinders)d\n" \
|
|
589 |
"# of data sectors per cylinder: %(secpercyl)d\n" \
|
|
590 |
"# of data sectors per unit: %(secperunit)d\n" % self.field + \
|
|
591 |
"DUID: %s\n" % duid + \
|
|
592 |
"Alt. cylinders per unit: %(acylinders)d\n" \
|
|
593 |
"Start of useable region (high part): %(bstarth)d\n" \
|
|
594 |
"Size of useable region (high part): %(bendh)d\n" \
|
|
595 |
"Start of useable region: %(bstart)d\n" \
|
|
596 |
"End of usable region: %(bend)d\n" \
|
|
597 |
"Generic Flags: %(flags)r\n" \
|
|
598 |
"Drive data: %(drivedata)r\n" \
|
|
599 |
"Number of data sectors (high part): %(secperunith)d\n" \
|
|
600 |
"Version: %(version)d\n" \
|
|
601 |
"Reserved for future use: %(spare)r\n" \
|
|
602 |
"The magic number again: 0x%(magic2)x\n" \
|
|
603 |
"Checksum: %(checksum)d\n" \
|
|
604 |
"Number of partitions: %(npartitions)d\n" \
|
|
605 |
"Size of boot aread at sn0: %(bbsize)d\n" \
|
|
606 |
"Max size of fs superblock: %(sbsize)d\n" % self.field + \
|
|
633 | 607 |
"%s" % self.ptable |
634 | 608 |
|
635 | 609 |
|
... | ... | |
667 | 641 |
sys.exit(0) |
668 | 642 |
|
669 | 643 |
if options.duid: |
670 |
print "%s" % "".join(x.encode('hex') for x in disk.uid)
|
|
644 |
print "%s" % "".join(x.encode('hex') for x in disk.get_duid())
|
|
671 | 645 |
sys.exit(0) |
672 | 646 |
|
673 | 647 |
if options.last_part: |
Also available in: Unified diff