diff options
-rwxr-xr-x | backend/magiback | 37 | ||||
-rwxr-xr-x | backend/raw_write.py | 18 | ||||
-rwxr-xr-x | isodumper | 2 | ||||
-rwxr-xr-x | lib/isodumper.py | 465 | ||||
-rwxr-xr-x | lib/raw_format.py | 81 |
5 files changed, 312 insertions, 291 deletions
diff --git a/backend/magiback b/backend/magiback index 7485773..49162b3 100755 --- a/backend/magiback +++ b/backend/magiback @@ -54,8 +54,8 @@ class Isodumper(raw_write.Dumper): """ def __init__(self): super().__init__() - APP="isodumper" - DIR="/usr/share/locale" + APP = "isodumper" + DIR = "/usr/share/locale" # Call translation catalog gettext.install(APP, localedir=DIR,) self.finished = threading.Event() @@ -73,10 +73,9 @@ class Isodumper(raw_write.Dumper): self.writing_perm = False self.writing_target = "" - - def do_write(self,source, target, size, dbus_context): + def do_write(self, source, target, size, dbus_context): self.finished.clear() - if check_permission('org.mageia.Magiback.Isodumper.write',dbus_context): + if check_permission('org.mageia.Magiback.Isodumper.write', dbus_context): self.thread = threading.Thread(target=self._do_write, args=(source, target, size, )) self.thread.start() logging.debug("Writing thread started") @@ -89,7 +88,7 @@ class Isodumper(raw_write.Dumper): def do_persistence(self, target, label, key): self.finished.clear() - if self.writing_perm and self.writing_target == target : + if self.writing_perm and self.writing_target == target: self.thread = threading.Thread(target=self._do_persistence, args=(target, label, key)) self.thread.start() logging.debug("Persistence thread started") @@ -126,19 +125,21 @@ class Isodumper(raw_write.Dumper): self.key_thread = threading.Thread(target=self._get_sum, args=(source,)) self.key_thread.start() - def check_write(self,target, source): + def check_write(self, target, source): if hasattr(self, 'key_thread'): self.key_thread.join() self.thread = threading.Thread(target=self._check_write, args=(target, source,)) self.thread.start() def run(self): - self.loop.run() + self.loop.run() + def check_permission(action, dbus_context): - """ Check permission - """ - return dbus_context.is_authorized(action, {'polkit.icon_name': 'isodumper.png',}, interactive=True) + """ Check permission + """ + return dbus_context.is_authorized(action, {'polkit.icon_name': 'isodumper.png', }, interactive=True) + class ConfFile(object): """ @@ -159,11 +160,11 @@ class ConfFile(object): def __init__(self): super().__init__() - def setName(self,file_name): + def setName(self, file_name): self.file_name = file_name def getFile(self): - with open(self.file_name,'r') as tcf : + with open(self.file_name, 'r') as tcf: # read the file content="" while 1: @@ -174,20 +175,20 @@ class ConfFile(object): return content def saveFile(self, tc, dbus_context): - if check_permission('org.mageia.Magiback.write',dbus_context): + if check_permission('org.mageia.Magiback.write', dbus_context): try: - with open(self.file_name,'w') as tcf : + with open(self.file_name, 'w') as tcf: tcf.write(tc) except: return False return True + if __name__ == '__main__': print("Running Magiback service.") bus = SystemBus() - conf_file = ConfFile() - bus.publish(DEAMON_ORG, conf_file, - ("Isodumper", Isodumper())) + conf_file = ConfFile() + bus.publish(DEAMON_ORG, conf_file, ("Isodumper", Isodumper())) loop = GLib.MainLoop() loop.run() logging.shutdown() diff --git a/backend/raw_write.py b/backend/raw_write.py index cd80b85..8338a07 100755 --- a/backend/raw_write.py +++ b/backend/raw_write.py @@ -23,19 +23,21 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +import gettext +import hashlib +import io +import logging ########### # imports # ########### -#import locale +# import locale import os -import io import sys -import gettext -from subprocess import call, Popen, PIPE -import hashlib -import gnupg import time -import logging +from subprocess import Popen, PIPE + +import gnupg + class Dumper(object): @@ -211,7 +213,7 @@ class Dumper(object): def udev_wait(self, operation): wait = Popen(["udevadm","settle","--timeout=15"], stderr=PIPE) - outs, errs = wait.communicate() + wait.communicate() working=True while working: time.sleep(0.5) @@ -4,10 +4,12 @@ import manatools.args as args from isodumper import version import yui + class ParseCLI(args.AppArgs): def __init(self, command): super().__init__(command) + # Suppress YUI log from console (mga#26681) yui.YUILog.setLogFileName("/dev/null") diff --git a/lib/isodumper.py b/lib/isodumper.py index ffc56cc..d8b4a8f 100755 --- a/lib/isodumper.py +++ b/lib/isodumper.py @@ -1,6 +1,6 @@ -#coding:utf-8 +# coding:utf-8 -#!/usr/bin/python3 +# !/usr/bin/python3 # # Copyright (c) 2007-2009 Canonical Ltd. # @@ -28,12 +28,13 @@ # ensure we're using the latest build, if called from our build environment import sys import importlib + try: from isodumper import version except: import version -sys.path.insert(0,'../../../build/swig/python3') +sys.path.insert(0, '../../../build/swig/python3') importlib.reload(sys) ########### # imports # @@ -51,13 +52,11 @@ import psutil import manatools.args as args - class NoUDisks2(Exception): pass class UDisks2(object): - BLOCK = 'org.freedesktop.UDisks2.Block' DRIVE = 'org.freedesktop.UDisks2.Drive' SERVICE = 'org.freedesktop.UDisks2' @@ -66,37 +65,38 @@ class UDisks2(object): self.bus = SystemBus() try: self.iface = self.bus.get(self.SERVICE) - except : + except: raise NoUDisks2() self._udisks2_obj_manager = self.iface["org.freedesktop.DBus.ObjectManager"] def find_devices(self): objects = self._udisks2_obj_manager.GetManagedObjects() - re_drive = re.compile('(?P<path>.*?/drives/(?P<id>.*))') - re_block = re.compile('(?P<path>.*?/block_devices/(?P<id>.*))') - devs= [m.groupdict() for m in - [re_drive.match(path) for path in (objects.keys())] - if m] + re_drive = re.compile("(?P<path>.*?/drives/(?P<id>.*))") + re_block = re.compile("(?P<path>.*?/block_devices/(?P<id>.*))") + devs = [m.groupdict() for m in + [re_drive.match(path) for path in (objects.keys())] + if m] blocks = [m.groupdict() for m in - [re_block.match(path) for path in (objects.keys())] - if m] - list=[] + [re_block.match(path) for path in (objects.keys())] + if m] + list = [] for block in blocks: if not (self.SERVICE + '.Partition' in objects[block['path']]): # we skip partition blocks for dev in devs: - if dev['path'] == objects[block['path']][self.BLOCK]['Drive']: # we look for device which is referenced in Drive attribute of the current block - dev_obj =objects[dev['path']][self.DRIVE] + if dev['path'] == objects[block['path']][self.BLOCK]['Drive']: + # we look for device which is referenced in Drive attribute of the current block + dev_obj = objects[dev['path']][self.DRIVE] if (dev_obj['ConnectionBus'] == 'usb' or dev_obj['ConnectionBus'] == 'sdio') and \ - (dev_obj['Removable'] == 1 or dev_obj['MediaRemovable'] == 1 ): # we keep only blocks where device ConnectionBus is sdio or usb - item=[] + (dev_obj['Removable'] == 1 or dev_obj[ + 'MediaRemovable'] == 1): # we keep only blocks where device ConnectionBus is sdio or usb + item = [] vend = dev_obj['Vendor'] if vend == "": name = dev_obj['Model'] else: - name = vend + " "+ dev_obj['Model'] - dev_name = block['path'].split('/')[-1] - path = '/dev/'+block['path'].split('/')[-1] + name = vend + " " + dev_obj['Model'] + path = '/dev/' + block['path'].split('/')[-1] size = dev_obj['Size'] item.append(name) item.append(path) @@ -108,23 +108,21 @@ class UDisks2(object): # keep only the end, like sdb target = os.path.basename(target) objects = self._udisks2_obj_manager.GetManagedObjects() - re_drive = re.compile('(?P<path>.*?/drives/(?P<id>.*))') re_block = re.compile('(?P<path>.*?/block_devices/(?P<id>.*))') blocks = [m.groupdict() for m in - [re_block.match(path) for path in (objects.keys())] - if m] + [re_block.match(path) for path in (objects.keys())] + if m] for block in blocks: if (self.SERVICE + '.Partition' in objects[block['path']]): # we skip non partition blocks # Table should be something like '/org/freedesktop/UDisks2/block_devices/sdb' - if objects[block['path']][self.SERVICE + '.Partition']['Table'].split('/')[-1] == target : - print("Unmounting: {}".format(block['path'].split('/')[-1])) - if (self.SERVICE + '.Encrypted' in objects[block['path']]): # Is the partition encrypted ? + if objects[block['path']][self.SERVICE + '.Partition']['Table'].split('/')[-1] == target: + if (self.SERVICE + '.Encrypted' in objects[block['path']]): # Is the partition encrypted ? path_to_encrypted = objects[block['path']][self.SERVICE + '.Encrypted']['CleartextDevice'] print(path_to_encrypted) - if path_to_encrypted != '/' : + if path_to_encrypted != '/': iface = self.bus.get(self.SERVICE, path_to_encrypted) fs = iface[self.SERVICE + '.Filesystem'] - if fs.MountPoints : # partition is mounted + if fs.MountPoints: # partition is mounted fs.Unmount({}) iface = self.bus.get(self.SERVICE, block['path']) fs = iface[self.SERVICE + '.Encrypted'] @@ -132,63 +130,65 @@ class UDisks2(object): else: iface = self.bus.get(self.SERVICE, block['path']) fs = iface[self.SERVICE + '.Filesystem'] - if fs.MountPoints : # partition is mounted + if fs.MountPoints: # partition is mounted fs.Unmount({}) return True, "" def eject(self, device): ''' device is expected like /dev/sda''' block = os.path.basename(device) - iface = self.bus.get(self.SERVICE,'/org/freedesktop/UDisks2/block_devices/' + block) - drive = iface.Get(self.BLOCK,"Drive") + iface = self.bus.get(self.SERVICE, '/org/freedesktop/UDisks2/block_devices/' + block) + drive = iface.Get(self.BLOCK, "Drive") i_drive = self.bus.get(self.SERVICE, drive) i_drive.Eject({}) + class Info(object): - def __init__(self,title,richtext,text): - self.title=title - self.richtext=richtext - self.text=text + def __init__(self, title, richtext, text): + self.title = title + self.richtext = richtext + self.text = text + class ParseCLI(args.AppArgs): def __init(self, command): super().__init__(command) + class IsoDumper(object): def get_devices(self): - self.list=self.u.find_devices() - while len(self.list)==0: + self.list = self.u.find_devices() + while len(self.list) == 0: if self.nodevDialog(): self.list = self.u.find_devices() else: return False - break - self.devicelist.addItem("",False) - if len(self.list)>0: + self.devicelist.addItem("", False) + if len(self.list) > 0: for name, path, size in self.list: - if size != 0 : - self.devicelist.addItem(str(name+' ('+path.lstrip()+') ' + self.sizeof_fmt(size)),False) + if size != 0: + self.devicelist.addItem(str(name + ' (' + path.lstrip() + ') ' + self.sizeof_fmt(size)), False) return True def udev_wait(self, operation): - wait = Popen(["udevadm","settle","--timeout=15"], stderr=PIPE) - outs, errs = wait.communicate() - working=True + wait = Popen(["udevadm", "settle", "--timeout=15"], stderr=PIPE) + wait.communicate() + working = True while working: time.sleep(0.5) wait.poll() - rc=wait.returncode + rc = wait.returncode if not (rc is None): wait = None - working= False + working = False if rc != 0: self.return_state = False self.return_message = _("Timeout reached when {}".format(operation)) return False return True - def update_list(self ): + def update_list(self): self.devicelist.deleteAllItems() self.get_devices() self.img_name = "" @@ -199,42 +199,43 @@ class IsoDumper(object): def device_selected(self): selitem = self.devicelist.selectedItem() - if selitem != None: + if selitem is not None: self.dev = selitem.label() for name, path, size in self.list: - if self.dev.startswith(name+' ('+path.lstrip()): - self.deviceSize=size - self.device_name=name.rstrip().replace(' ', '') - self.logger(_('Target Device: ')+ self.dev) + if self.dev.startswith(name + ' (' + path.lstrip()): + self.deviceSize = size + self.device_name = name.rstrip().replace(' ', '') + self.logger(_('Target Device: ') + self.dev) self.formatbt.setEnabled() self.ima.setEnabled() self.backup_select.setEnabled() break - def sizeof_fmt(self, num): + @staticmethod + def sizeof_fmt(num): # I18N these are units for files size - for unit in [_('B'),_('KiB'),_('MiB'),_('GiB'),_('TiB')]: + for unit in [_('B'), _('KiB'), _('MiB'), _('GiB'), _('TiB')]: if abs(num) < 1024.0: return "%3.3f %s" % (num, unit) num /= 1024.0 return "%.1f %s" % (num, _('TiB')) def backup_choosed(self): - # Add .img if not specified - if not self.backup_img_name.lower().endswith('.img'): - self.backup_img_name=self.backup_img_name+".img" - head, tail = os.path.split(self.backup_img_name) - self.backup_dest=self.backup_img_name - self.backup_select.setLabel(tail) - self.dialog.recalcLayout() - self.backupbt.setEnabled() - - def do_format(self,format_type,name): + # Add .img if not specified + if not self.backup_img_name.lower().endswith('.img'): + self.backup_img_name = self.backup_img_name + ".img" + head, tail = os.path.split(self.backup_img_name) + self.backup_dest = self.backup_img_name + self.backup_select.setLabel(tail) + self.dialog.recalcLayout() + self.backupbt.setEnabled() + + def do_format(self, format_type, name): target = self.dev.split('(')[1].split(')')[0] - info = Info(_("Formatting confirmation"),True,self.warning) + info = Info(_("Formatting confirmation"), True, self.warning) if self.ask_YesOrNo(info): - rc=self.raw_format(target, format_type, name) - self.operation=False + rc = self.raw_format(target, format_type, name) + self.operation = False if rc == 0: message = _('The device was formatted successfully.') self.logger(message) @@ -274,55 +275,61 @@ class IsoDumper(object): self.dialog.pollEvent() def raw_format(self, usb_path, fstype, label): - self.operation=True + self.operation = True if os.geteuid() > 0: - launcher='pkexec' - self.process = Popen([launcher,'/usr/bin/python3', '-u', '/usr/lib/isodumper/raw_format.py','-d',usb_path,'-f',fstype, '-l', label, '-u', str(os.geteuid()), '-g', str(os.getgid())], shell=False, stdout=PIPE, preexec_fn=os.setsid) + launcher = 'pkexec' + self.process = Popen( + [launcher, '/usr/bin/python3', '-u', '/usr/lib/isodumper/raw_format.py', '-d', usb_path, '-f', fstype, + '-l', label, '-u', str(os.geteuid()), '-g', str(os.getgid())], shell=False, stdout=PIPE, + preexec_fn=os.setsid) else: - self.process = Popen(['/usr/bin/python3', '-u', '/usr/lib/isodumper/raw_format.py','-d',usb_path,'-f',fstype, '-l', label, '-u', str(os.geteuid()), '-g', str(os.getgid())], shell=False, stdout=PIPE, preexec_fn=os.setsid) - working=True + self.process = Popen( + ['/usr/bin/python3', '-u', '/usr/lib/isodumper/raw_format.py', '-d', usb_path, '-f', fstype, '-l', + label, '-u', str(os.geteuid()), '-g', str(os.getgid())], shell=False, stdout=PIPE, + preexec_fn=os.setsid) + working = True while working: time.sleep(0.5) self.process.poll() - rc=self.process.returncode + rc = self.process.returncode if rc is None: - working=True + working = True else: self.process = None - working= False + working = False return rc def backup_go(self): dest = self.backup_img_name if os.path.exists(dest): - info = Info(_("Backup confirmation"),True,_("Do you want to overwrite the file?")) - if not(self.ask_YesOrNo(info)): + info = Info(_("Backup confirmation"), True, _("Do you want to overwrite the file?")) + if not (self.ask_YesOrNo(info)): self.returncode = 1 return True st = os.statvfs(os.path.dirname(dest)) free = st.f_bavail * st.f_frsize - if free<self.deviceSize : - sizeM=str(self.deviceSize/(1024*1024)) - message=_("The destination directory is too small to receive the backup (%s Mb needed)")%(sizeM) + if free < self.deviceSize: + sizeM = str(self.deviceSize / (1024 * 1024)) + message = _("The destination directory is too small to receive the backup (%s Mb needed)") % (sizeM) self.logger(message) self.emergency(message) else: - self.returncode=0 + self.returncode = 0 source = self.dev.split('(')[1].split(')')[0] - self.logger(_('Backup to:')+' '+dest) + self.logger(_('Backup to:') + ' ' + dest) bus = SystemBus() - iface = bus.get("org.mageia.Magiback","Isodumper") + iface = bus.get("org.mageia.Magiback", "Isodumper") # Writing step iface.do_write(source, dest, self.deviceSize) - progress = iface.progress - while not iface.done : + while not iface.done: progress = iface.progress self.progress.setValue(progress) self.dialog.pollEvent() time.sleep(.2) success, message = iface.end() if success: - self.logger(_('{source} successfully written to {target}').format( source=source.split('/')[-1], target=dest)) + self.logger( + _('{source} successfully written to {target}').format(source=source.split('/')[-1], target=dest)) self.progress.setEnabled() self.progress.setValue(100) self.dialog.pollEvent() @@ -346,18 +353,20 @@ class IsoDumper(object): self.logger(message) self.emergency(message) else: - info = Info(_("Writing confirmation"),True,self.warning) + info = Info(_("Writing confirmation"), True, self.warning) if self.ask_YesOrNo(info): - if self.deviceSize> 1024*1024*1024*32 : - info = Info(_("Warning"),True,_('The device is bigger than 32 Gbytes. Are you sure you want use it?')) + if self.deviceSize > 1024 * 1024 * 1024 * 32: + info = Info(_("Warning"), True, + _('The device is bigger than 32 Gbytes. Are you sure you want use it?')) if self.ask_YesOrNo(info): pass else: return self.ima.setDisabled() self.writebt.setDisabled() - self.progress.setLabel(_('Writing {source} to {target}').format(source=source.split('/')[-1],target=target.split('/')[-1])) - self.logger(_('Executing copy from ')+source+_(' to ')+target) + self.progress.setLabel(_('Writing {source} to {target}').format(source=source.split('/')[-1], + target=target.split('/')[-1])) + self.logger(_('Executing copy from ') + source + _(' to ') + target) bus = SystemBus() iface = bus.get("org.mageia.Magiback", "Isodumper") success, message = self.u.do_unmount(target) @@ -367,22 +376,24 @@ class IsoDumper(object): iface.do_write(source, target, b) iface.get_sum(source) progress = iface.progress - while not iface.done : + while not iface.done: progress = iface.progress self.progress.setValue(progress) self.dialog.pollEvent() time.sleep(.5) success, message = iface.end() if success: - self.logger(_('Image {source} successfully written to {target}').format( source=source.split('/')[-1], target=target)) - self.logger(_('Bytes written: ')+str(b)) - self.progress.setLabel(_('Checking ')+target.split('/')[-1]) + self.logger( + _('Image {source} successfully written to {target}').format(source=source.split('/')[-1], + target=target)) + self.logger(_('Bytes written: ') + str(b)) + self.progress.setLabel(_('Checking ') + target.split('/')[-1]) self.progress.setValue(0) self.dialog.pollEvent() # Checking iface.check_write(target, source) progress = iface.progress - while progress < 100 : + while progress < 100: progress = iface.progress self.progress.setValue(progress) self.dialog.pollEvent() @@ -398,11 +409,11 @@ class IsoDumper(object): self.progress.setValue(0) if self.cryptcb.isChecked(): if self.cryptkey.value() == "": - self.logger(_("No key for encrypted partition provided. Adding the partition aborted.")) + self.logger( + _("No key for encrypted partition provided. Adding the partition aborted.")) else: - iface.do_persistence(target,"mgalive-persist", self.cryptkey.value()) - progress = iface.progress - while not iface.done : + iface.do_persistence(target, "mgalive-persist", self.cryptkey.value()) + while not iface.done: progress = iface.progress self.progress.setValue(progress) self.dialog.pollEvent() @@ -413,8 +424,7 @@ class IsoDumper(object): self.logger(iface.message) else: iface.do_persistence(target, "mgalive-persist", "") - progress = iface.progress - while not iface.done : + while not iface.done: progress = iface.progress self.progress.setValue(progress) self.dialog.pollEvent() @@ -438,33 +448,32 @@ class IsoDumper(object): self.restore() def success(self): - self.operation=False + self.operation = False self.final_unsensitive() - info = Info(_("Success"),True,_("The operation completed successfully.\n\ + info = Info(_("Success"), True, _("The operation completed successfully.\n\ You are free to unplug it now, a logfile \n\ (/home/-user- or /root)/.isodumper/isodumper.log will be saved when\n\ you close the application.")) - if self.ask_OK(info) : - return - + if self.ask_OK(info): + return def confirm_close(self, *args): - if self.operation==False: # no writing , backup nor format running + if not self.operation: # no writing , backup nor format running self.close() - else: # writing , backup or format running - info = Info(_("Warning"),True,_("Writing is in progress. Exiting during writing \n\ + else: # writing , backup or format running + info = Info(_("Warning"), True, _("Writing is in progress. Exiting during writing \n\ will make the device or the backup unusable.\n\ Are you sure you want to quit during writing?")) - if self.ask_YesOrNo(info) : + if self.ask_YesOrNo(info): return True else: return False - def emergency(self,message): - self.operation=False - self.returncode=1 + def emergency(self, message): + self.operation = False + self.returncode = 1 self.final_unsensitive() - info = Info(_("Error"),True,message) + info = Info(_("Error"), True, message) self.ask_OK(info) def final_unsensitive(self): @@ -490,56 +499,61 @@ class IsoDumper(object): self.dialog = None def write_logfile(self): - logpath = os.path.join(os.path.expanduser('~'),'.isodumper') - if not(os.path.isdir(logpath)): - os.mkdir(logpath) - logfile=open(logpath+'/isodumper.log',"w", encoding="utf-8") + logpath = os.path.join(os.path.expanduser('~'), '.isodumper') + if not (os.path.isdir(logpath)): + os.mkdir(logpath) + logfile = open(logpath + '/isodumper.log', "w", encoding="utf-8") logfile.write(self.logview.logText()) logfile.close() print((self.logview.logText())) def logger(self, text): - self.logview.appendLines(text+"\n") + self.logview.appendLines(text + "\n") def activate_devicelist(self): self.devicelist.setEnabled() - self.logger(_('Image ')+": "+ self.img_name) -# self.chooser.set_tooltip_text(self.img_name) + self.logger(_('Image ') + ": " + self.img_name) + + # self.chooser.set_tooltip_text(self.img_name) def help_dialog(self): - info = Info(_("IsoDumper"),True,_("Mageia IsoDumper")+"<BR />\ -----------------<BR />"+ -_("This GUI program is primarily for safely writing a bootable ISO image to a USB flash drive, \ + info = Info(_("IsoDumper"), True, _("Mageia IsoDumper") + "<BR />\ +----------------<BR />" + + _("This GUI program is primarily for safely writing a bootable ISO image to a USB flash drive, \ an operation devious & potentially hazardous when done by hand. As a bonus, it can also back up the \ entire previous contents of the flash drive onto the hard disc, and restore the flash drive \ -to its previous state subsequently.")+"<BR />"+ -_("It gives also a feature for formatting the USB device.")+"<BR /><BR />"+ -_("IsoDumper can be launched either from the menus, or a user console with the command 'isodumper'.")+"<BR />"+ -_("The root password is solicited when this is necessary for the program's operation.")+" <BR />"+ -_("The flash drive can be inserted beforehand or once the program is started. In the latter case, a \ +to its previous state subsequently.") + "<BR />" + + _("It gives also a feature for formatting the USB device.") + "<BR /><BR />" + + _( + "IsoDumper can be launched either from the menus, or a user console with the command 'isodumper'.") + "<BR />" + + _( + "The root password is solicited when this is necessary for the program's operation.") + " <BR />" + + _("The flash drive can be inserted beforehand or once the program is started. In the latter case, a \ dialogue will say that there is no flash drive inserted, and allow a 'retry' to find it once it is. <BR />\ -(You may have to close any automatically opened File Manager window).")+"<BR /><BR />"+ -_("The fields of the main window are as follows:<BR />\ +(You may have to close any automatically opened File Manager window).") + "<BR /><BR />" + + _("The fields of the main window are as follows:<BR />\ - Device to work on: the device of the USB flash drive, a drop-down list to choose from.<BR />\ - Write Image: to choose the source ISO image *.iso (or flash drive backup file *.img) to write out.<BR />\ -- Write to device: This button launches the operation - with a prior warning dialogue.") +"<BR />"+ -_("- Add a persistent partition: the remaining space will be used in a new partition where data from the Live system can be written and recovered between sessions.")+ "<BR />"+ -_("- Encrypt: the persistent partition will be encrypted with the key provided in <i>Key</i> field.")+ "<BR />"+ -_("The operation is shown in the progress bar beneath.")+"<BR />"+ -_("- Backup to: define the name and placement of the backup image file. The current flash drive \ +- Write to device: This button launches the operation - with a prior warning dialogue.") + "<BR />" + + _( + "- Add a persistent partition: the remaining space will be used in a new partition where data from the Live system can be written and recovered between sessions.") + "<BR />" + + _( + "- Encrypt: the persistent partition will be encrypted with the key provided in <i>Key</i> field.") + "<BR />" + + _("The operation is shown in the progress bar beneath.") + "<BR />" + + _("- Backup to: define the name and placement of the backup image file. The current flash drive \ will be backed up to a disc file. Note that the entire flash drive is preserved, regardless of its \ actual contents; ensure that you have the necessary free disc space (the same size as the USB device). \ -This backup file can be used later to restore the flash drive by selecting it as the source *.img file to write out.")+"<BR />"+ -_("- Backup the device: launch the backup operation.")+"<BR />"+ -_("- Format the device: create an unique partition on the entire volume in the specified format in FAT, \ -exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog box.")+"<BR />") - if self.ask_OK(info) : - return +This backup file can be used later to restore the flash drive by selecting it as the source *.img file to write out.") + "<BR />" + + _("- Backup the device: launch the backup operation.") + "<BR />" + + _("- Format the device: create an unique partition on the entire volume in the specified format in FAT, \ +exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog box.") + "<BR />") + if self.ask_OK(info): + return def __init__(self): - APP="isodumper" - DIR="/usr/share/locale" + APP = "isodumper" + DIR = "/usr/share/locale" # Call translation catalog gettext.install(APP, localedir=DIR, names=('ngettext',)) @@ -547,20 +561,19 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog current_pid = psutil.Process().pid for pid in psutil.pids(): p = psutil.Process(pid) - if p.name() == "isodumper" and p.pid != current_pid : - info = Info(_("Error"),True,_("There is another instance of Isodumper already running.")) + if p.name() == "isodumper" and p.pid != current_pid: + info = Info(_("Error"), True, _("There is another instance of Isodumper already running.")) self.ask_OK(info) yui.YUILoader.deleteUI() exit() - # TODO Read log level from command line # define size of the selected device - self.deviceSize=0 + self.deviceSize = 0 # Operation running - self.operation=False + self.operation = False self.ChooseImage = _("Choose an image") self.warning = _("Warning\nThis will destroy all data on the target device,\n\ @@ -595,69 +608,70 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog self.ancrage = self.atelier.createReplacePoint(self.dialog) self.box = self.atelier.createVBox(self.ancrage) self.bannerbox = self.atelier.createHBox(self.box) - self.banner=self.atelier.createImage(self.bannerbox,"/usr/share/isodumper/header.svg") + self.banner = self.atelier.createImage(self.bannerbox, "/usr/share/isodumper/header.svg") self.devicebox = self.atelier.createHBox(self.box) - self.devicelist=self.atelier.createComboBox(self.devicebox,_("Device to work on:"),False) + self.devicelist = self.atelier.createComboBox(self.devicebox, _("Device to work on:"), False) self.devicelist.setNotify() - self.devicelist.setStretchable(0,True) + self.devicelist.setStretchable(0, True) self.writebox = self.atelier.createHBox(self.box) - self.atelier.createLabel(self.writebox,_("Write Image:")) + self.atelier.createLabel(self.writebox, _("Write Image:")) # add file picker for image file - self.ima=self.atelier.createPushButton(self.writebox,self.ChooseImage) - self.ima.setStretchable(0,True) + self.ima = self.atelier.createPushButton(self.writebox, self.ChooseImage) + self.ima.setStretchable(0, True) self.ima.setDisabled() self.atelier.createHStretch(self.writebox) - self.writebt = self.atelier.createPushButton(self.writebox, _("&Write to device" )) + self.writebt = self.atelier.createPushButton(self.writebox, _("&Write to device")) self.writebt.setDisabled() self.persistencebox = self.atelier.createHBox(self.box) self.persistencecol1 = self.atelier.createVBox(self.persistencebox) self.persistencecol2 = self.atelier.createVBox(self.persistencebox) - self.persistencecb = self.atelier.createCheckBox(self.persistencecol1, _("Add a persistent partition in the remaining space")) + self.persistencecb = self.atelier.createCheckBox(self.persistencecol1, + _("Add a persistent partition in the remaining space")) self.persistencebox2 = self.atelier.createHBox(self.box) self.cryptcb = self.atelier.createCheckBox(self.persistencecol1, _("Encrypt partition")) - self.cryptkey = self.atelier.createInputField(self.persistencecol2, _("Key:"),passwordMode = True) + self.cryptkey = self.atelier.createInputField(self.persistencecol2, _("Key:"), passwordMode=True) self.persistencecb.setDisabled() self.persistencecb.setNotify() self.cryptcb.setDisabled() self.cryptcb.setNotify() self.cryptkey.setDisabled() self.backupbox = self.atelier.createHBox(self.box) - self.atelier.createLabel(self.backupbox,_("Backup to:")) + self.atelier.createLabel(self.backupbox, _("Backup to:")) # add file picker for backup file name - self.backup_select=self.atelier.createPushButton(self.backupbox,self.ChooseImage) - self.backup_select.setStretchable(0,True) + self.backup_select = self.atelier.createPushButton(self.backupbox, self.ChooseImage) + self.backup_select.setStretchable(0, True) self.backup_select.setDisabled() self.atelier.createHStretch(self.backupbox) - self.backupbt = self.atelier.createPushButton(self.backupbox, _("Backup the device" )) + self.backupbt = self.atelier.createPushButton(self.backupbox, _("Backup the device")) self.backupbt.setDisabled() self.formatbox = self.atelier.createHBox(self.box) - self.atelier.createLabel(self.formatbox,_("Format the device in FAT, exFAT, NTFS or ext:")) + self.atelier.createLabel(self.formatbox, _("Format the device in FAT, exFAT, NTFS or ext:")) self.atelier.createHStretch(self.formatbox) - self.formatbt = self.atelier.createPushButton(self.formatbox, _("Format the device" )) + self.formatbt = self.atelier.createPushButton(self.formatbox, _("Format the device")) self.formatbt.setDisabled() self.progressbox = self.atelier.createHBox(self.box) - self.progress = self.atelier.createProgressBar(self.progressbox,_("Progress"),100) - self.progress.setStretchable(0,True) + self.progress = self.atelier.createProgressBar(self.progressbox, _("Progress"), 100) + self.progress.setStretchable(0, True) self.reportbox = self.atelier.createHBox(self.box) - self.reportbox.setWeight(1,30) - self.logview = self.atelier.createLogView(self.reportbox,_("Report"), 10) - self.logview.setStretchable(0,True) + self.reportbox.setWeight(1, 30) + self.logview = self.atelier.createLogView(self.reportbox, _("Report"), 10) + self.logview.setStretchable(0, True) self.buttonsbox = self.atelier.createHBox(self.box) - self.refreshbt = self.atelier.createPushButton(self.devicebox, _("Refresh" )) - self.refreshbt.setStretchable(0,True) - self.aboutbt = self.atelier.createPushButton(self.buttonsbox, _("About" )) - self.aboutbt.setStretchable(0,True) - self.helpbt = self.atelier.createPushButton(self.buttonsbox, _("Help" )) - self.helpbt.setStretchable(0,True) - self.quitbt = self.atelier.createPushButton(self.buttonsbox, _("Quit" )) - self.quitbt.setStretchable(0,True) + self.refreshbt = self.atelier.createPushButton(self.devicebox, _("Refresh")) + self.refreshbt.setStretchable(0, True) + self.aboutbt = self.atelier.createPushButton(self.buttonsbox, _("About")) + self.aboutbt.setStretchable(0, True) + self.helpbt = self.atelier.createPushButton(self.buttonsbox, _("Help")) + self.helpbt.setStretchable(0, True) + self.quitbt = self.atelier.createPushButton(self.buttonsbox, _("Quit")) + self.quitbt.setStretchable(0, True) self.u = None try: self.u = UDisks2() - except : - message = _('UDisks2 is not available on your system') - self.logger(message) - self.emergency(message) + except: + message = _('UDisks2 is not available on your system') + self.logger(message) + self.emergency(message) if not self.get_devices(): self.dialog.destroy() yui.YUILoader.deleteUI() @@ -667,23 +681,23 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog self.ancrage.showChild() def ask_format(self): - atelier = yui.YUI.widgetFactory() + atelier = yui.YUI.widgetFactory() dialog = atelier.createPopupDialog() - vb=atelier.createVBox(dialog) - label = atelier.createInputField(vb,_("Label for the device:")) + vb = atelier.createVBox(dialog) + label = atelier.createInputField(vb, _("Label for the device:")) cr = atelier.createRadioButtonGroup(vb) vb_c = atelier.createVBox(cr) vb_c1 = atelier.createHBox(vb_c) - format_fat = atelier.createRadioButton(atelier.createLeft(vb_c1),_("FAT 32 (Windows)")) + format_fat = atelier.createRadioButton(atelier.createLeft(vb_c1), _("FAT 32 (Windows)")) vb_c4 = atelier.createHBox(vb_c) - format_exfat = atelier.createRadioButton(atelier.createLeft(vb_c4),_("exFAT (Windows)")) + format_exfat = atelier.createRadioButton(atelier.createLeft(vb_c4), _("exFAT (Windows)")) vb_c2 = atelier.createHBox(vb_c) - format_ntfs = atelier.createRadioButton(atelier.createLeft(vb_c2),_("NTFS (Windows)")) + format_ntfs = atelier.createRadioButton(atelier.createLeft(vb_c2), _("NTFS (Windows)")) vb_c3 = atelier.createHBox(vb_c) - format_ext = atelier.createRadioButton(atelier.createLeft(vb_c3),_("ext4 (Linux)")) + format_ext = atelier.createRadioButton(atelier.createLeft(vb_c3), _("ext4 (Linux)")) bb = atelier.createHBox(vb) - executebt = atelier.createPushButton(bb,_("Execute")) - cancelbt = atelier.createPushButton(bb,_("Cancel")) + executebt = atelier.createPushButton(bb, _("Execute")) + cancelbt = atelier.createPushButton(bb, _("Cancel")) dialog.open() returncode = True while True: @@ -713,10 +727,9 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog break dialog.destroy() if returncode: - return True,format_type,format_label + return True, format_type, format_label else: - return False," "," " - + return False, " ", " " def ask_OK(self, info): yui.YUI.widgetFactory @@ -725,7 +738,7 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog dlg.setTitle(info.title) dlg.setText(info.text, info.richtext) dlg.setButtonLabel(_("OK"), yui.YMGAMessageBox.B_ONE) - dlg.setMinSize(60, 10); + dlg.setMinSize(60, 10) return dlg.show() == yui.YMGAMessageBox.B_ONE def ask_YesOrNo(self, info): @@ -735,30 +748,32 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog dlg.setTitle(info.title) dlg.setText(info.text, info.richtext) dlg.setButtonLabel(_("Yes"), yui.YMGAMessageBox.B_ONE) - dlg.setButtonLabel(_("No"), yui.YMGAMessageBox.B_TWO) - dlg.setMinSize(60, 8); + dlg.setButtonLabel(_("No"), yui.YMGAMessageBox.B_TWO) + dlg.setMinSize(60, 8) return dlg.show() == yui.YMGAMessageBox.B_ONE def aboutDialog(self): - yui.YUI.widgetFactory; + yui.YUI.widgetFactory mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga")) dlg = mgafactory.createAboutDialog("Isodumper", version.RELEASE, "GPLv2", - _("Oliver Grawert<BR />Papoteur<BR />Pictures : Timothée Giet"), _("A tool for writing ISO images to a device")+"<BR />http://gitweb.mageia.org/software/isodumper", "") - dlg.show(); + _("Oliver Grawert<BR />Papoteur<BR />Pictures : Timothée Giet"), _( + "A tool for writing ISO images to a device") + "<BR />http://gitweb.mageia.org/software/isodumper", "") + dlg.show() def nodevDialog(self): yui.YUI.widgetFactory mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga")) dlg = mgafactory.createDialogBox(yui.YMGAMessageBox.B_TWO) dlg.setTitle("IsoDumper") - dlg.setText(_("Warning\nNo target devices were found.\nYou need to plug in a USB Key to which the image can be written.")) + dlg.setText(_( + "Warning\nNo target devices were found.\nYou need to plug in a USB Key to which the image can be written.")) dlg.setButtonLabel(_("Refresh"), yui.YMGAMessageBox.B_ONE) - dlg.setButtonLabel(_("Cancel"), yui.YMGAMessageBox.B_TWO) - dlg.setMinSize(60, 8); + dlg.setButtonLabel(_("Cancel"), yui.YMGAMessageBox.B_TWO) + dlg.setMinSize(60, 8) return dlg.show() == yui.YMGAMessageBox.B_ONE def handleevent(self): - self.traitement=None + self.traitement = None while True: event = self.dialog.waitForEvent() if event.eventType() == yui.YEvent.CancelEvent: @@ -768,43 +783,43 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog self.close() break if event.widget() == self.ima: - self.img_name=yui.YUI.app().askForExistingFile("","*.iso *.img",self.ChooseImage) - if self.img_name != "" : - self.ima.setLabel(os.path.basename(self.img_name)) - self.dialog.recalcLayout() - self.writebt.setEnabled() - self.activate_devicelist() - self.persistencecb.setEnabled() + self.img_name = yui.YUI.app().askForExistingFile("", "*.iso *.img", self.ChooseImage) + if self.img_name != "": + self.ima.setLabel(os.path.basename(self.img_name)) + self.dialog.recalcLayout() + self.writebt.setEnabled() + self.activate_devicelist() + self.persistencecb.setEnabled() if event.widget() == self.persistencecb: print(self.persistencecb.value) - if self.persistencecb.isChecked() : + if self.persistencecb.isChecked(): self.cryptcb.setEnabled() else: self.cryptcb.setDisabled() self.cryptkey.setDisabled() self.cryptcb.setChecked(False) if event.widget() == self.cryptcb: - if self.cryptcb.isChecked() : + if self.cryptcb.isChecked(): self.cryptkey.setEnabled() else: self.cryptkey.setDisabled() if event.widget() == self.writebt: - self.wip_unsensitive() - self.do_write() - self.restore() + self.wip_unsensitive() + self.do_write() + self.restore() if event.widget() == self.backupbt: self.wip_unsensitive() self.backup_go() self.restore() if event.widget() == self.backup_select: - self.backup_img_name=yui.YUI.app().askForSaveFileName("","*.img",_("Backup to:")) + self.backup_img_name = yui.YUI.app().askForSaveFileName("", "*.img", _("Backup to:")) if self.backup_img_name != '': - self.backup_choosed() + self.backup_choosed() if event.widget() == self.formatbt: - code,format_type,name = self.ask_format() - if code: - self.do_format(format_type,name) - self.restore() + code, format_type, name = self.ask_format() + if code: + self.do_format(format_type, name) + self.restore() if event.widget() == self.devicelist: self.device_selected() try: @@ -828,7 +843,7 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog def run(self): try: self.handleevent() - except Exception as e: + except Exception: import traceback traceback.print_exc() yui.YDialog.deleteAllDialogs() diff --git a/lib/raw_format.py b/lib/raw_format.py index 54e7bcb..b3bdb42 100755 --- a/lib/raw_format.py +++ b/lib/raw_format.py @@ -22,42 +22,44 @@ # # Author isodumper software= papoteur <papoteur@mageialinux-online.org> -import os, sys +import sys import getopt from subprocess import call sys.path.append('/usr/lib/isodumper') + def do_umount(target): - mounts = get_mounted(target) - if mounts: - print('Unmounting all partitions of '+target+':') - for mount in mounts: - print('Trying to unmount '+mount[0]+'...') - try: - retcode = call('umount '+mount[0], shell=True) - if retcode < 0: - print('Error, umount '+mount[0]+' was terminated by signal '+str(retcode)) - sys.exit(6) - else: - if retcode == 0: - print(mount[0]+' successfully unmounted') - else: - print('Error, umount '+mount[0]+' returned '+str(retcode)) - sys.exit(6) - except OSError as e: - print('Execution failed: '+str(e)) + mounts = get_mounted(target) + if mounts: + print('Unmounting all partitions of ' + target + ':') + for mount in mounts: + print('Trying to unmount ' + mount[0] + '...') + try: + retcode = call('umount ' + mount[0], shell=True) + if retcode < 0: + print('Error, umount ' + mount[0] + ' was terminated by signal ' + str(retcode)) sys.exit(6) + else: + if retcode == 0: + print(mount[0] + ' successfully unmounted') + else: + print('Error, umount ' + mount[0] + ' returned ' + str(retcode)) + sys.exit(6) + except OSError as e: + print('Execution failed: ' + str(e)) + sys.exit(6) def get_mounted(target): - try: - lines = [line.strip("\n").split(" ") for line in open ("/etc/mtab", "r").readlines()] - return [mount for mount in lines if mount[0].startswith(target)] - except: - print('Could not read mtab !') - sys.exit(6) + try: + lines = [line.strip("\n").split(" ") for line in open("/etc/mtab", "r").readlines()] + return [mount for mount in lines if mount[0].startswith(target)] + except: + print('Could not read mtab !') + sys.exit(6) + def raw_format(device_path, fstype, volume_label, uid, gid): import parted @@ -79,17 +81,17 @@ def raw_format(device_path, fstype, volume_label, uid, gid): regions = disk.getFreeSpaceRegions() if len(regions) > 0: - #print "Build partition" + # print "Build partition" # Define size start = parted.sizeToSectors(1, "MiB", device.sectorSize) - #print "start %s" % start + # print "start %s" % start end = device.getLength() - start - 1024 - #print end + # print end # Alignment - #cylinder = device.endSectorToCylinder(end) - #end = device.endCylinderToSector(cylinder) - #print end + # cylinder = device.endSectorToCylinder(end) + # end = device.endCylinderToSector(cylinder) + # print end try: geometry = parted.Geometry(device=device, start=start, end=end) except: @@ -120,13 +122,11 @@ def raw_format(device_path, fstype, volume_label, uid, gid): sys.exit(0) - - - def main(): # parse command line options try: - opts, args = getopt.getopt(sys.argv[1:], "hd:f:l:u:g:", ["help", "device=","filesystem=","label=","uid=","gid="]) + opts, args = getopt.getopt(sys.argv[1:], "hd:f:l:u:g:", + ["help", "device=", "filesystem=", "label=", "uid=", "gid="]) except getopt.error as msg: print(msg) print("for help use --help") @@ -134,7 +134,7 @@ def main(): for o, a in opts: if o in ("-h", "--help"): - print("Usage: %s -d device -f filesystem -l volume_label\n" % sys.argv[0]) + print("Usage: %s -d device -f filesystem -l volume_label\n"% sys.argv[0]) print("-d|--device : device path") print("-f|--filesystem : filesystem\n") print("-l|--label : volume label\n") @@ -145,7 +145,7 @@ def main(): elif o in ("-d"): device = a elif o in ("-f"): - if a not in [ "fat32","exfat", "ntfs", "ext4" ]: + if a not in ["fat32", "exfat", "ntfs", "ext4"]: print("Specify fat32, exfat, ntfs or ext4") sys.exit(3) fstype = a @@ -158,11 +158,12 @@ def main(): argc = len(sys.argv) if argc < 11: - print("Too few arguments") - print("for help use --help") - exit(2) + print("Too few arguments") + print("for help use --help") + exit(2) raw_format(device, fstype, label, uid, gid) + if __name__ == "__main__": main() |