import subprocess import os SINGLE_DISK_OFFSET = 1572864 MAX_IMAGES_ON_DRIVE = 1000 def get_or_create_empty_image(index, temp_path, size=1440): filename = 'empty{}.ima'.format(index) filename = os.path.join(temp_path, filename) if os.path.isfile(filename): os.remove(filename) proc = subprocess.Popen(['mkfs.msdos', '-C', filename, str(size)]) rval = proc.wait() if rval != 0: raise Exception('Not created') return filename def format_images(device, indexes, temp_path, size=1440): for ipair in indexes: if isinstance(ipair, int): image = get_or_create_empty_image(ipair, temp_path, size) write_image(device, image, ipair) else: for i in range(ipair[0], ipair[1]): image = get_or_create_empty_image(i, temp_path, size) write_image(device, image, i) def write_image(device, path, index=0): """ Writes image from path to device at specified index :param device: :param index: :param path: :return: """ with open(device, 'r+b') as dfile: offset = SINGLE_DISK_OFFSET * index dfile.seek(offset) with open(path, 'rb') as ifile: fdata = ifile.read() dfile.write(fdata) def read_image(device, path, index=0): """ Reads image at specified index from device into path :param device: :param path: :param index: :return: """ with open(device, 'rb') as dfile: offset = SINGLE_DISK_OFFSET * index dfile.seek(offset) bootsector = dfile.read(512) if bootsector[-1] == 0xAA and bootsector[-2] == 0x55: # FAT12 image sectorsize = bootsector[0xB] + (bootsector[0xC] << 8) sectorcount = bootsector[0x13] + (bootsector[0x14] << 8) with open(path, 'xb') as ifile: dfile.seek(offset) fdata = dfile.read(sectorsize * sectorcount) ifile.write(fdata) def list_images(device): """ Reads device and lists all of images on it :param device: :return: (label, size) """ rval = [] with open(device, 'rb') as dfile: dfile.seek(0, 2) disks = min(dfile.tell() / SINGLE_DISK_OFFSET, MAX_IMAGES_ON_DRIVE) dfile.seek(0) while len(rval) < disks: bootsector = dfile.read(512) label = None if bootsector[0] == 0xEB or bootsector[0] == 0xE9: sectorsize = bootsector[0xB] + (bootsector[0xC] << 8) sectorcount = bootsector[0x13] + (bootsector[0x14] << 8) disksize = sectorsize * sectorcount if bootsector[0x26] == 0x29: # label probably exists. # As an additional precaution check fs type. # If it's valid, then get label, otherwise consider disk unlabeled if bootsector[0x36:0x3E] in (b'FAT12 ', b'FAT16 ', b'FAT '): label = bootsector[0x2B:0x36].decode(encoding='cp1251') dfile.seek(SINGLE_DISK_OFFSET - 512, 1) else: disksize = 0 dfile.seek(SINGLE_DISK_OFFSET - 512, 1) rval.append((label, disksize)) return rval