def sevenzip(interactive: bool, compress_type: str, inputfilepath: str, outputfilepath: str=None): if string_is_empty(inputfilepath): raise Exception("No input file path provided") if string_is_empty(compress_type): if interactive is True: compress_type = strip( input( "Type the name of the compression algorithm (7z or zip)\n" ) ).lower() else: compress_type = "zip" if string_is_empty(compress_type): raise Exception("No compression algorithm chosen") if compress_type != "zip" and compress_type != "7z": raise Exception("Wrong compression algorithm (use 7z or zip)") if string_is_empty(outputfilepath): if interactive is True: outputfilepath = strip(input("Type the path of the compressed image file\n")) else: outputfilepath = inputfilepath + "." + compress_type if string_is_empty(outputfilepath): raise Exception("File path empty") cancelled = False p = Path(outputfilepath) if p.exists(): yn = singlecharinput( "The file '{}' exists. Do you want to delete it?".format( outputfilepath ), ConsoleColors.WARNING ) if yn == "n": cancelled = True print(ConsoleColor.colorline("Cancelling compress process", ConsoleColors.OKBLUE)) else: print(ConsoleColor.colorline("Deleting '{}'".format(outputfilepath), ConsoleColors.FAIL)) if Path(outputfilepath).exists(): print(ConsoleColor.colorline( "Could not delete '{}'".format( outputfilepath ), ConsoleColors.FAIL) ) cancelled = True if cancelled is False: sz = local["7z"] sz.run(["a", str(p.absolute()), inputfilepath])
def parse_device_sizeinfo(line: str) -> Dict: if string_is_empty(line): return None p = line.find("bytes") c = find_char_backwards(line, ",", len(line) - p) fsize = int(strip(line[(p - c):p])) return {"size_b": fsize, "size_h": bytes_to_unit(fsize, True)}
def fdisk_size_to_bytesize(fdisksize: str) -> int: sfdisksize = strip(fdisksize) ffdisksize = None t = -1 if sfdisksize.find("T") > -1: t = 0 elif sfdisksize.find("G") > -1: t = 1 elif sfdisksize.find("M") > -1: t = 2 if t > -1: sfdisksize = sfdisksize[0:len(sfdisksize) - 1].replace(",", ".") ffdisksize = float(sfdisksize) if t == 0: return int(ffdisksize * FileSizes.TB_BYTE_SIZE.value) elif t == 1: return int(ffdisksize * FileSizes.GB_BYTE_SIZE.value) elif t == 2: return int(ffdisksize * FileSizes.MB_BYTE_SIZE.value) else: return int(sfdisksize)
def set_device(self, devicepath: str = None) -> None: device_str = None if not string_is_empty(devicepath): self._devicepath = Path(devicepath) else: device_str = strip( input( "Type the path of device (e.g. /dev/sde) or partition (e.g. /dev/sde1) you want to backup:\n" )) if string_is_empty(device_str): raise Exception("Device-String is empty") devok = False for dev in self._devices: if string_equal_utf8(dev["dev"], device_str, False): devok = True if devok is False: if "partitions" in dev: for devpart in dev["partitions"]: if devpart["dev"] == device_str: devok = True break if devok is True: break if not devok: raise Exception("Device or partition '{}' not found".format( self._device_str)) else: self._devicepath = Path(device_str)
def parse_dd_info(line): bytestrpos = line.find(" ") bytestr = strip(line[0:bytestrpos]) byteint = int(bytestr) brackpos = line.find(")") tmstartpos = line.find(",", brackpos) nextcommapos = line.find(",", tmstartpos + 1) charbeforecomma = line[nextcommapos - 1:nextcommapos] if charbeforecomma == "s" or charbeforecomma == "m" or charbeforecomma == "h": tm = strip(line[tmstartpos + 1:nextcommapos]) else: nextnextcommapos = line.find(",", nextcommapos + 1) tm = strip(line[nextcommapos - 2:nextnextcommapos]) tm_comma_pos = tm.find(",") is_secs = "s" in tm is_mins = "m" in tm is_hours = "h" in tm is_commatime = False if is_mins or is_hours: if tm_comma_pos > -1: tm_1 = tm[0:tm_comma_pos].strip() tm_2 = float("0." + tm[tm_comma_pos + 1:].strip("m" if is_mins else "h").strip()) if is_mins: factor = 60 else: factor = 3600 tm_1 = int(tm_1) * factor tm_2 = int(tm_2 * factor) tm = tm_1 + tm_2 is_commatime = True if is_commatime is False: if is_secs: if tm_comma_pos > -1: tm = int(tm[0:tm_comma_pos]) else: tm = int(tm.strip("s").strip()) elif is_mins: tm = int(tm.strip("m").strip()) * 60 elif is_hours: tm = int(tm.strip("m").strip()) * 60 return {"size_b": byteint, "time": int(tm), "time_h": humantime(tm)}
def set_image_path(self, image_path: str = None) -> bool: is_dir_msg = "Image path '{}' is not accepted, as it is a directory!" is_dir = False if not string_is_empty(image_path): if is_directory_path(image_path): is_dir = True else: self._imagepath = Path(image_path) return True else: imagepathok = False imagefile = None try: while imagepathok is False: fpi = input( "Type the filepath of the image you want to create (empty to cancel image creation):\n" ) imagefilepath = strip(fpi) if string_is_empty(imagefilepath): raise Exception("_cic_") if is_directory_path(imagefilepath): is_dir = True else: imagefile = Path(imagefilepath) if imagefile.is_dir(): is_dir = True else: imagepathok = True except Exception as e: if str(e) == "_cic_": return False finally: if imagepathok is True: self._imagepath = imagefile return True if is_dir is True: raise Exception( "Image path '{}' points to a directory. Needs to be a file!")
def start_dd(self, interactive: bool = False, ddbatchsize: str = None, finished_handler: Callable = None) -> int: retcode = None devpath = str(self._devicepath.absolute()) imagepath = str(self._imagepath.absolute()) param_if = "if={}".format(devpath.replace(" ", "\\ ")) param_of = "of={}".format(imagepath.replace(" ", "\\ ")) param_status = "status=progress" # todo: make configurable batch size if ddbatchsize is not None: param_bs = "bs={}".format(ddbatchsize) else: param_bs = "bs=1M" if interactive is True: yn = "y" else: print( ConsoleColor.colorline( "Will execute \"{}\"".format("sudo dd {} {} {} {}".format( param_if, param_of, param_status, param_bs)), ConsoleColors.OKGREEN)) yn = singlecharinput( "Confirm the creation of image '{}' from device '{}' (y/n)!". format(imagepath, devpath), ConsoleColors.OKGREEN) if yn == "n": if interactive is True: print( ConsoleColor.colorline( "Cancelled image creation on your wish", ConsoleColors.OKBLUE)) return -1 elif yn == "y": sudo = local["sudo"] dd = local["dd"] starttime = datetime.now() p = sudo[dd[param_if, param_of, param_status, param_bs]].popen(stderr=PIPE) line = '' # retcode = 0 # Intention is not to get the first "\r" from dd-output # sleep(1) if interactive is True: print() target_image_sizehuman = self.get_target_image_sizehuman() target_image_sizebytes = self.get_target_image_sizebytes() if interactive is False: p._proc.communicate() else: while True: retcode = p.poll() if retcode is None: out = p.stderr.read(1).decode("utf-8", errors="replace") if out == '': break else: if out == '\r': line = strip(line) if not string_is_empty(line): dd_info = parse_dd_info(line) currenttime = datetime.now() deltatime = currenttime - starttime print( "{0:10}{1:4}{2:9}{3:3}{4:10}{5:4}{6:8}{7:3}{8}" .format( bytes_to_unit( dd_info["size_b"], True, True, False), "of", target_image_sizehuman, "|", dd_info["time_h"], "of", humantime( predict_job_time( dd_info["time"], target_image_sizebytes, dd_info["size_b"])), "|", "Total time: {}".format( humantime(deltatime. total_seconds()))), end="\r") line = '' else: line = line + out else: break retcode = retcode if retcode is not None else p._proc.returncode if interactive is True: print() currenttime = datetime.now() deltatime = currenttime - starttime print( ConsoleColor.colorline( "Total time: {}".format( humantime(deltatime.total_seconds())), ConsoleColors.OKGREEN)) st = stat(imagepath) print( ConsoleColor.colorline( "Final image size: {}".format( bytes_to_unit(st.st_size, True, True, False)), ConsoleColors.OKGREEN)) if retcode == 0: print( ConsoleColor.colorline("Successfully created image!", ConsoleColors.OKGREEN)) else: print( ConsoleColor.colorline( "No Result from dd (image might be ok)!", ConsoleColors.WARNING)) finished_handler(retcode, imagepath) return retcode
def is_directory_path(path: str): if not string_is_empty(path): c = len(path) return strip(path)[c-1:c] == sep return False