def get_disk_mount(disk_id): TEMP_DIR = 'C:\\temp\\kano-burner\\' disk_mount = '' # mount point e.g. C:\ or D:\ # extract the id of the physical disk, required by diskpart # e.g. \\?\Device\Harddisk[id]\Partition0 id = int(disk_id.split("Harddisk")[1][0]) # access by string index alone is dangerous! # create a diskpart script to find the mount point for the given disk diskpart_detail_script = 'select disk {} \ndetail disk'.format(id) write_file_contents(TEMP_DIR + "detail_disk.txt", diskpart_detail_script) # run the created diskpart script cmd = 'diskpart /s {}'.format(TEMP_DIR + "detail_disk.txt") output, error, return_code = run_cmd_no_pipe(cmd) if not return_code: debugger('Ran diskpart detail script') else: debugger('[ERROR] ' + error.strip('\n')) return # now the mount point is the third word on the last line of the output disk_mount = output.splitlines()[-1].split()[2] return disk_mount
def close_all_explorer_windows(): cmd = '{}\\nircmd.exe win close class "CabinetWClass"'.format(_nircmd_path) _, error, return_code = run_cmd_no_pipe(cmd) if not return_code: debugger('Closed all Explorer windows') else: debugger('[ERROR]: ' + error.strip('\n'))
def unzip_kano_os(os_path, dest_path): cmd = '"{}\\7za.exe" e "{}" -o"{}"'.format(_7zip_path, os_path, dest_path) _, output, return_code = run_cmd_no_pipe(cmd) if not return_code: debugger('Unzipped Kano OS successfully') else: debugger('[ERROR]: ' + output.strip('\n'))
def unmount_disk(disk_mount): cmd = "mountvol {}:\\ /D".format(disk_mount) error, _, return_code = run_cmd_no_pipe(cmd) if not return_code: debugger('{}:\\ successfully unmounted'.format(disk_mount)) else: debugger('[ERROR]: ' + error.strip('\n'))
def test_write(disk_mount): cmd = '{}\\dd.exe if=/dev/random of=\\\\.\\{}: bs=4M count=10'.format(_dd_path, disk_mount) _, output, return_code = run_cmd_no_pipe(cmd) if not return_code: debugger('Written 40M random data to {}:\\'.format(disk_mount)) else: debugger('[ERROR]: ' + output.strip('\n'))
def mount_disk(disk_id): # the following may not work if the disk has been unmounted, consider caching disk_mount = get_disk_mount(disk_id) disk_volume = get_disk_volume(disk_id, disk_mount) cmd = "mountvol {}:\\ {}".format(disk_mount, disk_volume) _, error, return_code = run_cmd_no_pipe(cmd) if not return_code: debugger('{} successfully mounted'.format(disk_mount)) else: debugger('[ERROR]: ' + error.strip('\n'))
def is_installed(programs_list): cmd = 'where.exe {}'.format(' '.join(programs_list)) output, error, return_code = run_cmd_no_pipe(cmd) if return_code: debugger('[ERROR] ' + error.strip('\n')) return True # if something goes wrong here, it shouldn't be catastrophic programs_found = 0 for line in output.splitlines(): if line and 'not find' not in line: programs_found += 1 return programs_found == len(programs_list)
def is_sufficient_space(required_mb): cmd = "dir {}".format(temp_path) output, _, _ = run_cmd_no_pipe(cmd) try: # grab the last line from the output free_space_line = output.splitlines()[-1] # grab the number in bytes, remove comma delimiters, and convert to MB free_space_mb = float(free_space_line.split()[2].replace(',', '')) / BYTES_IN_MEGABYTE except: debugger('[ERROR] Failed parsing the line ' + output) return True debugger('Free space {0:.2f} MB in {1}'.format(free_space_mb, temp_path)) return free_space_mb > required_mb
def get_disk_volume(disk_id, disk_mount): disk_volume = '' # a unique ID e.g. \\?\Volume{5fd765ff-068e-11e4-bc8d-806e6f6e6963}\ # we now need to link the mount point to the volume id that is actually used cmd = '{}\\dd.exe --list'.format(_dd_path) _, output, return_code = run_cmd_no_pipe(cmd) # we will process the output line by line to find the line containing the mount point # the line at [index - 3] from the respective one contains the volume id output_lines = output.splitlines() disk_mount_dd = '\\\\.\\{}:'.format(disk_mount.lower()) for index in range(0, len(output_lines)): if disk_mount_dd in output_lines[index]: disk_volume = output_lines[index - 3].strip() break return disk_volume
def format_disk(disk_id): # TODO: look into cmd = 'format {}: /Q /X'.format(disk_mount) TEMP_DIR = 'C:\\temp\\kano-burner\\' # extract the id of the physical disk, required by diskpart # e.g. \\?\Device\Harddisk[id]\Partition0 id = int(disk_id.split("Harddisk")[1][0]) # access by string index alone is dangerous! # create a diskpart script to format the given disk diskpart_format_script = 'select disk {} \nclean'.format(id) write_file_contents(TEMP_DIR + "format_disk.txt", diskpart_format_script) # run the created diskpart script cmd = 'diskpart /s {}'.format(TEMP_DIR + "format_disk.txt") _, error, return_code = run_cmd_no_pipe(cmd) if not return_code: debugger('Formatted disk {} with diskpart'.format(id)) else: debugger('[ERROR] ' + error.strip('\n'))
def format_disk(disk_id): # TODO: look into cmd = 'format {}: /Q /X'.format(disk_mount) # extract the id of the physical disk, required by diskpart # e.g. \\?\Device\Harddisk[id]\Partition0 id = int(disk_id['id_num']) # access by string index alone is dangerous! # create a diskpart script to format the given disk diskpart_format_script = 'select disk {} \nclean'.format(id) diskpart_script_path = os.path.join(temp_path, "format_disk.txt") write_file_contents(diskpart_format_script, diskpart_script_path) # run the created diskpart script cmd = 'diskpart /s {}'.format(diskpart_script_path) _, error, return_code = run_cmd_no_pipe(cmd) time.sleep(15) # diskpart requires a timeout between calls if not return_code: debugger('Formatted disk {} with diskpart'.format(id)) else: debugger('[ERROR] ' + error.strip('\n')) raise disk_error(FORMAT_ERROR)
def get_disks_list(): ''' This method is used by the BurnerGUI when the user clicks the ComboBox. It grabs all disk physical ids, names, and sizes with one command and then parses the output. Sizes will be converted to GB (not GiB). NOTE: We do no return all disks that are found! Example: disk id: \\?\Device\Harddisk2\Partition0 disk name: Sandisk Media USB disk size: 16.03 disk volume: \\?\Volume{5fd765ff-068e-11e4-bc8d-806e6f6e6963}\ physical disk: \\.\PHYSICALDRIVE2 NOTE: physical drive id and device id match! ''' disks = list() cmd = "wmic diskdrive get deviceid, mediatype, model, size /format:list" output, error, return_code = run_cmd_no_pipe(cmd) if return_code: debugger('[ERROR] ' + error.strip('\n')) # remove random empty lines in the output output_lines = [line for line in output.splitlines() if line] for index in range(0, len(output_lines)): if output_lines[index].startswith("DeviceID="): # grab the disk id from e.g. \\.\PHYSICALDRIVE[0] and use Partition0 # which for dd is the entire disk, not some partition on the disk drive_loc = output_lines[index].lower().find( 'physicaldrive') + len('physicaldrive') id_num = output_lines[index][drive_loc:] id_str = "\\\\?\\Device\\Harddisk{}\\Partition0".format(id_num) disk_id = {'id_num': id_num, 'id_str': id_str} # media type media_type = output_lines[index + 1].split('=')[1] # for the disk model, remove the last word which is always 'device' model = output_lines[index + 2].split('=')[1] disk_name = ' '.join(model.split()[:-1]) # the size may not be listed (i.e. ''), in which case we assume # the device is not plugged in e.g. an empty USB SD card reader disk_size = -1 try: size_bytes = float(output_lines[index + 3].split('=')[1]) disk_size = size_bytes / BYTES_IN_GIGABYTE except: pass # append all data here, this would need changing if logic changes disk = {'id': disk_id, 'name': disk_name, 'size': disk_size} # make sure we do not list any potential hard drive or too small SD card if (disk['size'] < 3.5 or disk['size'] > 16.5 or disk['size'] == -1 or media_type.startswith('Fixed')): debugger('Ignoring {}'.format(disk)) else: debugger('Listing {}'.format(disk)) disks.append(disk) return disks
def get_disks_list(): ''' This method is used by the BurnerGUI when the user clicks the ComboBox. It grabs all disk physical ids, names, and sizes with one command and then parses the output. Sizes will be converted to GB (not GiB). NOTE: We do no return all disks that are found! Example: disk id: \\?\Device\Harddisk2\Partition0 disk name: Sandisk Media USB disk size: 16.03 disk volume: \\?\Volume{5fd765ff-068e-11e4-bc8d-806e6f6e6963}\ physical disk: \\.\PHYSICALDRIVE2 NOTE: physical drive id and device id match! ''' disks = list() cmd = "wmic diskdrive get deviceid, mediatype, model, size /format:list" output, error, return_code = run_cmd_no_pipe(cmd) if return_code: debugger('[ERROR] ' + error.strip('\n')) # remove random empty lines in the output output_lines = [line for line in output.splitlines() if line] for index in range(0, len(output_lines)): if output_lines[index].startswith("DeviceID="): # grab the disk id from e.g. \\.\PHYSICALDRIVE[0] and use Partition0 # which for dd is the entire disk, not some partition on the disk drive_loc = output_lines[index].lower().find('physicaldrive') + len('physicaldrive') id_num = output_lines[index][drive_loc:] id_str = "\\\\?\\Device\\Harddisk{}\\Partition0".format(id_num) disk_id = {'id_num': id_num, 'id_str': id_str} # media type media_type = output_lines[index +1].split('=')[1] # for the disk model, remove the last word which is always 'device' model = output_lines[index + 2].split('=')[1] disk_name = ' '.join(model.split()[:-1]) # the size may not be listed (i.e. ''), in which case we assume # the device is not plugged in e.g. an empty USB SD card reader disk_size = -1 try: size_bytes = float(output_lines[index + 3].split('=')[1]) disk_size = size_bytes / BYTES_IN_GIGABYTE except: pass # append all data here, this would need changing if logic changes disk = { 'id': disk_id, 'name': disk_name, 'size': disk_size } # make sure we do not list any potential hard drive or too small SD card if (disk['size'] < 3.5 or disk['size'] > 16.5 or disk['size'] == -1 or media_type.startswith('Fixed')): debugger('Ignoring {}'.format(disk)) else: debugger('Listing {}'.format(disk)) disks.append(disk) return disks