def add_partition(self, drv_name, cyl_range, dev_flags=0, flags=0, dos_type=DosType.DOS0, boot_pri=0): # cyl range is not free anymore or invalid if not self.check_cyl_range(*cyl_range): return False # no space left for partition block if not self._has_free_rdb_blocks(1): return False # allocate block for partition blk_num = self._alloc_rdb_blocks(1)[0] self.used_blks.append(blk_num) self._update_hi_blk() # crete a new parttion block pb = PartitionBlock(self.rawblk, blk_num) heads = self.rdb.phy_drv.heads blk_per_trk = self.rdb.phy_drv.secs dos_env = PartitionDosEnv(low_cyl=cyl_range[0], high_cyl=cyl_range[1], surfaces=heads, \ blk_per_trk=blk_per_trk, dos_type=dos_type, boot_pri=boot_pri) pb.create(drv_name, dos_env, flags=flags) pb.write() # link block if len(self.parts) == 0: # write into RDB self.rdb.part_list = blk_num else: # write into last partition block last_pb = self.parts[-1] last_pb.part_blk.next = blk_num last_pb.write() # always write RDB as allocated block is stored there, too self.rdb.write() # create partition object and add to partition list p = Partition(self.rawblk, blk_num, len(self.parts), blk_per_trk, self) p.read() self.parts.append(p) return True
def read(self): # read fs header self.part_blk = PartitionBlock(self.blkdev, self.blk_num) if not self.part_blk.read(): self.valid = False return False self.valid = True return True
def add_partition(self, drv_name, cyl_range, dev_flags=0, flags=0, dos_type=DosType.DOS0, boot_pri=0, more_dos_env=None, fs_block_size=None): # cyl range is not free anymore or invalid if not self.check_cyl_range(*cyl_range): return False # no space left for partition block if not self._has_free_rdb_blocks(1): return False # allocate block for partition blk_num = self._alloc_rdb_blocks(1)[0] self.used_blks.append(blk_num) self._update_hi_blk() # crete a new parttion block pb = PartitionBlock(self.rawblk, blk_num) # setup fs block size (may be multiple sectors) if not fs_block_size: fs_block_size = self.block_bytes sec_per_blk = int(fs_block_size / self.block_bytes) if sec_per_blk < 1 or sec_per_blk > 16: raise IOError("Invalid sec_per_blk: " + sec_per_blk) # block size in longs bsl = self.block_bytes >> 2 # setup dos env heads = self.rdb.phy_drv.heads blk_per_trk = self.rdb.phy_drv.secs dos_env = PartitionDosEnv(low_cyl=cyl_range[0], high_cyl=cyl_range[1], surfaces=heads, blk_per_trk=blk_per_trk, dos_type=dos_type, boot_pri=boot_pri, block_size=bsl, sec_per_blk=sec_per_blk) self._adjust_dos_env(dos_env, more_dos_env) pb.create(drv_name, dos_env, flags=flags) pb.write() # link block if len(self.parts) == 0: # write into RDB self.rdb.part_list = blk_num else: # write into last partition block last_pb = self.parts[-1] last_pb.part_blk.next = blk_num last_pb.write() # always write RDB as allocated block is stored there, too self.rdb.write() # flush out all changes before we read again self.rawblk.flush() # create partition object and add to partition list blk_per_cyl = blk_per_trk * heads p = Partition(self.rawblk, blk_num, len(self.parts), blk_per_cyl, self) p.read() self.parts.append(p) return True
class Partition: def __init__(self, blkdev, blk_num, num, cyl_blks, rdisk): self.blkdev = blkdev self.blk_num = blk_num self.num = num self.cyl_blks = cyl_blks self.rdisk = rdisk self.block_bytes = rdisk.block_bytes self.part_blk = None def get_next_partition_blk(self): if self.part_blk != None: return self.part_blk.next else: return 0xFFFFFFFF def get_blk_num(self): """return the block number of the partition block""" return self.blk_num def read(self): # read fs header self.part_blk = PartitionBlock(self.blkdev, self.blk_num) if not self.part_blk.read(): self.valid = False return False self.valid = True return True def create_blkdev(self, auto_close_rdb_blkdev=False): """create a block device for accessing this partition""" return PartBlockDevice(self.blkdev, self.part_blk, auto_close_rdb_blkdev) def write(self): self.part_blk.write() # ----- Query ----- def dump(self): self.part_blk.dump() def get_num_cyls(self): p = self.part_blk return p.dos_env.high_cyl - p.dos_env.low_cyl + 1 def get_num_blocks(self): """return total number of blocks in this partition""" return self.get_num_cyls() * self.cyl_blks def get_num_bytes(self): return self.get_num_blocks() * self.block_bytes def get_drive_name(self): return self.part_blk.drv_name def get_flags(self): return self.part_blk.flags def get_index(self): return self.num def get_cyl_range(self): de = self.part_blk.dos_env if de == None: return None else: return (de.low_cyl, de.high_cyl) def get_info(self, total_blks=0): """return a string line with typical info about this partition""" p = self.part_blk de = p.dos_env name = "'%s'" % p.drv_name part_blks = self.get_num_blocks() part_bytes = self.get_num_bytes() extra = "" if total_blks != 0: ratio = 100.0 * part_blks / total_blks extra += "%6.2f%% " % ratio # add dos type dos_type = de.dos_type extra += DosType.num_to_tag_str(dos_type) extra += "/0x%04x" % dos_type return "Partition: #%d %-06s %8d %8d %10d %s %s" % ( self.num, name, de.low_cyl, de.high_cyl, part_blks, ByteSize.to_byte_size_str(part_bytes), extra, ) def get_extra_infos(self): result = [] p = self.part_blk de = p.dos_env # layout result.append( "blk_longs=%d, sec/blk=%d, surf=%d, blk/trk=%d" % (de.block_size, de.sec_per_blk, de.surfaces, de.blk_per_trk)) result.append("fs_block_size=%d" % (de.block_size * 4 * de.sec_per_blk)) # max transfer result.append("max_transfer=0x%x" % de.max_transfer) result.append("mask=0x%x" % de.mask) result.append("num_buffer=%d" % de.num_buffer) # add flags flags = p.flags if flags & PartitionBlock.FLAG_BOOTABLE == PartitionBlock.FLAG_BOOTABLE: result.append("bootable=1 pri=%d" % de.boot_pri) else: result.append("bootable=0") if flags & PartitionBlock.FLAG_NO_AUTOMOUNT == PartitionBlock.FLAG_NO_AUTOMOUNT: result.append("automount=0") else: result.append("automount=1") return result # ----- Import/Export ----- def export_data(self, file_name): """Export contents of partition to file""" blkdev = self.create_blkdev() blkdev.open() num_blks = blkdev.num_blocks with open(file_name, "wb") as fh: for b in range(num_blks): data = blkdev.read_block(b) fh.write(data) blkdev.close() def import_data(self, file_name): """Import contents of partition from file""" part_dev = self.create_blkdev() part_dev.open() part_blks = part_dev.num_blocks blk_size = part_dev.block_bytes total = part_blks * blk_size # open image file_size = os.path.getsize(file_name) file_blks = file_size // blk_size if file_size % blk_size != 0: raise ValueError("image file not block size aligned!") # check sizes if total < file_size: raise ValueError( "import image too large: partition=%d != file=%d" % (total, file_size)) if total > file_size: raise ValueError( "import image too small: partition=%d != file=%d" % (total, file_size)) # copy image with open(file_name, "rb") as fh: for b in range(file_blks): data = fh.read(blk_size) part_dev.write_block(b, data) part_dev.close()
class Partition: def __init__(self, blkdev, blk_num, num, cyl_blks, rdisk): self.blkdev = blkdev self.blk_num = blk_num self.num = num self.cyl_blks = cyl_blks self.rdisk = rdisk self.part_blk = None def get_next_partition_blk(self): if self.part_blk != None: return self.part_blk.next else: return 0xffffffff def get_blk_num(self): """return the block number of the partition block""" return self.blk_num def read(self): # read fs header self.part_blk = PartitionBlock(self.blkdev, self.blk_num) if not self.part_blk.read(): self.valid = False return False self.valid = True return True def create_blkdev(self, auto_close_rdisk=False): """create a block device for accessing this partition""" rdisk = None if auto_close_rdisk: rdisk = self.rdisk return PartBlockDevice(self.blkdev, self.part_blk, rdisk) def write(self): self.part_blk.write() # ----- Query ----- def dump(self): self.part_blk.dump() def get_num_blocks(self): """return total number of blocks in this partition""" p = self.part_blk cyls = p.dos_env.high_cyl - p.dos_env.low_cyl + 1 return cyls * self.cyl_blks def get_num_bytes(self, block_size=512): return self.get_num_blocks() * block_size def get_drive_name(self): return self.part_blk.drv_name def get_index(self): return self.num def get_cyl_range(self): de = self.part_blk.dos_env if de == None: return None else: return (de.low_cyl, de.high_cyl) def get_info(self, total_blks=0): """return a string line with typical info about this partition""" p = self.part_blk de = p.dos_env name = "'%s'" % p.drv_name part_blks = self.get_num_blocks() part_bytes = self.get_num_bytes() extra = "" if total_blks != 0: ratio = 100.0 * part_blks / total_blks extra += "%6.2f%% " % ratio extra += DosType.num_to_tag_str(p.dos_env.dos_type) flags = p.flags if flags & PartitionBlock.FLAG_BOOTABLE == PartitionBlock.FLAG_BOOTABLE: extra += " bootable pri=%d" % de.boot_pri if flags & PartitionBlock.FLAG_NO_AUTOMOUNT == PartitionBlock.FLAG_NO_AUTOMOUNT: extra += " no_automount" return "Partition: #%d %-06s %8d %8d %10d %s %s" \ % (self.num, name, de.low_cyl, de.high_cyl, part_blks, ByteSize.to_byte_size_str(part_bytes), extra)
class Partition: def __init__(self, blkdev, blk_num, num, cyl_blks, rdisk): self.blkdev = blkdev self.blk_num = blk_num self.num = num self.cyl_blks = cyl_blks self.rdisk = rdisk self.block_bytes = rdisk.block_bytes self.part_blk = None def get_next_partition_blk(self): if self.part_blk != None: return self.part_blk.next else: return 0xffffffff def get_blk_num(self): """return the block number of the partition block""" return self.blk_num def read(self): # read fs header self.part_blk = PartitionBlock(self.blkdev, self.blk_num) if not self.part_blk.read(): self.valid = False return False self.valid = True return True def create_blkdev(self, auto_close_rdb_blkdev=False): """create a block device for accessing this partition""" return PartBlockDevice(self.blkdev, self.part_blk, auto_close_rdb_blkdev) def write(self): self.part_blk.write() # ----- Query ----- def dump(self): self.part_blk.dump() def get_num_cyls(self): p = self.part_blk return p.dos_env.high_cyl - p.dos_env.low_cyl + 1 def get_num_blocks(self): """return total number of blocks in this partition""" return self.get_num_cyls() * self.cyl_blks def get_num_bytes(self): return self.get_num_blocks() * self.block_bytes def get_drive_name(self): return self.part_blk.drv_name def get_flags(self): return self.part_blk.flags def get_index(self): return self.num def get_cyl_range(self): de = self.part_blk.dos_env if de == None: return None else: return (de.low_cyl, de.high_cyl) def get_info(self, total_blks=0): """return a string line with typical info about this partition""" p = self.part_blk de = p.dos_env name = "'%s'" % p.drv_name part_blks = self.get_num_blocks() part_bytes = self.get_num_bytes() extra = "" if total_blks != 0: ratio = 100.0 * part_blks / total_blks extra += "%6.2f%% " % ratio # add dos type dos_type = de.dos_type extra += DosType.num_to_tag_str(dos_type) extra += "/0x%04x" % dos_type return "Partition: #%d %-06s %8d %8d %10d %s %s" \ % (self.num, name, de.low_cyl, de.high_cyl, part_blks, ByteSize.to_byte_size_str(part_bytes), extra) def get_extra_infos(self): result = [] p = self.part_blk de = p.dos_env # layout result.append("blk_longs=%d, sec/blk=%d, surf=%d, blk/trk=%d" % \ (de.block_size, de.sec_per_blk, de.surfaces, de.blk_per_trk)) result.append("fs_block_size=%d" % (de.block_size * 4 * de.sec_per_blk)) # max transfer result.append("max_transfer=0x%x" % de.max_transfer) result.append("mask=0x%x" % de.mask) result.append("num_buffer=%d" % de.num_buffer) # add flags flags = p.flags if flags & PartitionBlock.FLAG_BOOTABLE == PartitionBlock.FLAG_BOOTABLE: result.append("bootable pri=%d" % de.boot_pri) else: result.append("not bootable") if flags & PartitionBlock.FLAG_NO_AUTOMOUNT == PartitionBlock.FLAG_NO_AUTOMOUNT: result.append("no automount") else: result.append("automount") return result