aboutsummaryrefslogtreecommitdiffstats
path: root/lib/isodumper.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isodumper.py')
-rw-r--r--[-rwxr-xr-x]lib/isodumper.py907
1 files changed, 513 insertions, 394 deletions
diff --git a/lib/isodumper.py b/lib/isodumper.py
index 590db25..b14ac50 100755..100644
--- a/lib/isodumper.py
+++ b/lib/isodumper.py
@@ -1,3 +1,5 @@
+#coding:utf-8
+
#!/usr/bin/python
#
# Copyright (c) 2007-2009 Canonical Ltd.
@@ -23,15 +25,33 @@
# Requires python-parted
-import gtk
-import gtk.glade
-import gobject
+# ensure we're using the latest build, if called from our build environment
+import sys
+
+sys.path.insert(0,'../../../build/swig/python')
+reload(sys)
+sys.setdefaultencoding("utf-8")
+###########
+# imports #
+###########
+import yui
+#import locale
+import time
+
+####################################
+# LOCALE (important for TERMINAL!) #
+####################################
+# set the locale to de/utf-8
+#locale.setlocale(locale.LC_ALL, "")
+#log = yui.YUILog.instance()
+#log.setLogFileName("debug.log")
+#log.enableDebugLogging( True )
+
import os, re
import io
import gettext
from gettext import gettext as _
from subprocess import call, Popen, PIPE
-import time
import dbus
@@ -138,7 +158,7 @@ class UDisks2(object):
try:
d = self.device(device_node_path)
mount_options = ['rw', 'noexec', 'nosuid',
- 'nodev','uid=%d'%os.geteuid(), 'gid=%d'%os.getegid()]
+ 'nodev', 'uid=%d'%os.geteuid(), 'gid=%d'%os.getegid()]
r=d.Mount(
{
'auth.no_user_interaction':True,
@@ -180,123 +200,77 @@ def makedirs(dest):
if not os.path.exists(dest):
os.makedirs(dest)
-class IsoDumper:
- def __init__(self,user):
- APP="isodumper"
- DIR="/usr/share/locale"
- RELEASE="v0.41"
-
- gettext.bindtextdomain(APP, DIR)
- gettext.textdomain(APP)
- gtk.glade.bindtextdomain(APP, DIR)
- gtk.glade.textdomain(APP)
-
- # for the localisation of log file
- self.user = user
-
- # get glade tree
- self.gladefile = "/usr/share/isodumper/isodumper.glade"
- self.wTree = gtk.glade.XML(self.gladefile)
-
- # get globally needed widgets
- self.window = self.wTree.get_widget("main_dialog")
- self.devicelist = self.wTree.get_widget("device_combobox")
- self.logview = self.wTree.get_widget("detail_text")
- self.log = self.logview.get_buffer()
- # set RELEASE number on title and About
- self.window.set_title(self.window.get_title()+' '+RELEASE)
- self.wTree.get_widget("about_dialog").set_version(RELEASE)
-
- # define size of the selected device
- self.deviceSize=0
-
- # Operation running
- self.operation=False
-
- # set default file filter to *.img
- # Added for Mageia : *.iso
- self.chooser = self.wTree.get_widget("filechooserbutton")
- filt = gtk.FileFilter()
- filt.add_pattern("*.iso")
- filt.add_pattern("*.img")
- self.chooser.set_filter(filt)
-
+class Info(object):
+ def __init__(self,title,richtext,text):
+ self.title=title
+ self.richtext=richtext
+ self.text=text
- # optionnal backup of the device
- self.backup_select = self.wTree.get_widget("backup_select")
- self.backup_name = self.wTree.get_widget("backup_name")
- self.backup_button = self.wTree.get_widget("backup_button")
- self.choose = self.wTree.get_widget("choose")
- self.backup_bname = self.wTree.get_widget("bname")
+
+class IsoDumper(object):
+# self.backup_select = self.wTree.get_widget("backup_select")
+# self.backup_name = self.wTree.get_widget("backup_name")
+# self.backup_button = self.wTree.get_widget("backup_button")
+# self.choose = self.wTree.get_widget("choose")
+# self.backup_bname = self.wTree.get_widget("bname")
+#
# set callbacks
- dict = { "on_main_dialog_destroy_event" : self.confirm_close,
- "on_main_dialog_delete_event" : self.confirm_close,
- "on_cancel_button_clicked" : self.confirm_close,
- "on_emergency_button_clicked" : self.restore,
- "on_confirm_cancel_button_clicked": self.restore,
- "on_filechooserbutton_file_set" : self.activate_devicelist,
- "on_device_combobox_changed" : self.device_selected,
- "on_nodev_close_clicked" : self.close,
- "on_backup_button_clicked" : self.backup_go,
- "on_backup_select_clicked" : self.backup_sel,
- "on_select_clicked" : self.backup_choosed,
- "on_about_button_clicked" : self.about,
- "on_choose_cancel_clicked" : self.backup_cancel,
- "on_format_button_clicked" : self.format_dialog,
- "on_format_cancel_clicked" : self.format_cancel,
- "on_format_go_clicked" : self.do_format,
- "on_write_button_clicked" : self.do_write,
- "on_help_close_clicked": self.help_close,
- "on_help_clicked": self.help_dialog,
- "on_update_button_clicked":self.update_list,
- }
- self.wTree.signal_autoconnect(dict)
-
- self.window.show_all()
- # make sure we have a target device
- self.u = None
- try:
- self.u = UDisks2()
- except :
- self.logger(_('UDisks2 is not available on your system'))
- self.emergency()
- self.get_devices()
-
- def update_list(self, widget):
- self.devicelist.remove_text(0)
- self.get_devices()
- self.restore(widget)
+# dict = { "on_main_dialog_destroy_event" : self.confirm_close,
+# "on_main_dialog_delete_event" : self.confirm_close,
+# "on_cancel_button_clicked" : self.confirm_close,
+# "on_emergency_button_clicked" : self.restore,
+# "on_confirm_cancel_button_clicked": self.restore,
+# "on_filechooserbutton_file_set" : self.activate_devicelist,
+# "on_device_combobox_changed" : self.device_selected,
+# "on_nodev_close_clicked" : self.close,
+# "on_backup_button_clicked" : self.backup_go,
+# "on_backup_select_clicked" : self.backup_sel,
+# "on_select_clicked" : self.backup_choosed,
+# "on_choose_cancel_clicked" : self.backup_cancel,
+# "on_format_button_clicked" : self.format_dialog,
+# "on_format_cancel_clicked" : self.format_cancel,
+# "on_format_go_clicked" : self.do_format,
+# "on_write_button_clicked" : self.do_write,
+# "on_help_close_clicked": self.help_close,
+# "on_help_clicked": self.help_dialog,
+# }
def get_devices(self):
- dialog = self.wTree.get_widget("nodev_dialog")
self.list=self.u.find_devices()
while len(self.list)==0:
- exit_dialog=dialog.run()
- if (exit_dialog==2) :
- dialog.destroy()
- exit(0)
- self.list = self.u.find_devices()
- for name, path, size in self.list:
+ if self.nodevDialog():
+ self.list = self.u.find_devices()
+ else:
+ return False
+ break
+ if len(self.list)>0:
+ for name, path, size in self.list:
# convert in Mbytes
- sizeM=str(int(size)/(1024*1024))
- self.devicelist.append_text(name+' ('+path.lstrip()+') '+sizeM+_('Mb'))
- dialog.hide()
+ sizeM=str(int(size)/(1024*1024))
+ self.devicelist.addItem(str(name+' ('+path.lstrip()+') '+sizeM+_('Mb')),False)
+ return True
+
+
+ def update_list(self ):
+ self.devicelist.deleteAllItems()
+ self.get_devices()
+ self.restore()
- def device_selected(self, widget):
- self.dev = self.devicelist.get_active_text()
- if self.dev != None:
+ def device_selected(self):
+ selitem = self.devicelist.selectedItem()
+ if selitem != None:
+ self.dev = selitem.label()
for name, path, size in self.list:
if self.dev.startswith(name):
self.deviceSize=size
self.device_name=name.rstrip().replace(' ', '')
break
- self.backup_select.set_sensitive(True)
- self.wTree.get_widget("format_button").set_sensitive(True)
- self.chooser.set_sensitive(True)
- if self.chooser.get_current_folder_uri() == None :
- self.chooser.set_current_folder_uri('file:///home/'+self.user)
+ self.formatbt.setEnabled()
+ self.ima.setEnabled()
+# if self.chooser.get_current_folder_uri() == None :
+# self.chooser.set_current_folder_uri('file:///home/'+self.user)
self.logger(_('Target Device: ')+ self.dev)
def backup_sel(self,widget):
@@ -305,58 +279,22 @@ class IsoDumper:
self.backup_bname.set_current_name(self.device_name+".img")
self.choose.run()
- def backup_cancel(self,widget):
- self.choose.hide()
- # Unckeck the choice to backup
- self.backup_button.set_sensitive(False)
-
- def backup_choosed(self, widget):
- exit_dialog=self.backup_bname.get_filename()
- if exit_dialog != None:
- # Add .iso if not specified
- if not exit_dialog.lower().endswith('.img'):
- exit_dialog=exit_dialog+".img"
- head, tail = os.path.split(exit_dialog)
- self.backup_dest=exit_dialog
- self.backup_select.set_label(tail)
- self.backup_button.set_sensitive(True)
- self.backup_select.set_tooltip_text(exit_dialog)
- self.logger(_('Backup in: ')+ exit_dialog)
- expander = self.wTree.get_widget("detail_expander")
- expander.set_sensitive(True)
- self.choose.hide()
-
- def format_dialog(self,widget):
- self.backup_select.set_sensitive(False)
- format_button=self.wTree.get_widget("format_button")
- format_button.set_sensitive(False)
- filechooserbutton=self.wTree.get_widget("filechooserbutton")
- filechooserbutton.set_sensitive(False)
- write_button = self.wTree.get_widget("write_button")
- write_button.set_sensitive(False)
- self.devicelist.set_sensitive(False)
- dialog=self.wTree.get_widget("format")
- self.wTree.get_widget("format_device").set_text(self.dev)
- self.wTree.get_widget("format_name").set_text(self.dev.split('(')[0])
- exit_dialog=dialog.run()
- if exit_dialog==0:
- dialog.hide()
-
- def do_format(self, widget) :
+ 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.backupbt.setEnabled()
+ #self.backup_select.set_tooltip_text(self.backup_img_name)
+ self.logger(_('Backup to: ')+ self.backup_img_name)
+
+ def do_format(self,format_type,name) :
target = self.dev.split('(')[1].split(')')[0]
- dialog = self.wTree.get_widget("confirm_dialog")
- expander = self.wTree.get_widget("detail_expander")
- expander.set_sensitive(True)
- resp = dialog.run()
- dev_name=self.wTree.get_widget("format_name").get_text()
- if resp:
- dialog.hide()
- if self.wTree.get_widget("format_fat").get_active():
- rc=self.raw_format(target, 'fat32', dev_name.upper()[:11])
- if self.wTree.get_widget("format_ntfs").get_active():
- rc=self.raw_format(target, 'ntfs', dev_name[:32])
- if self.wTree.get_widget("format_ext4").get_active():
- rc=self.raw_format(target, 'ext4', dev_name)
+ info = Info(_("Formatting confirmation"),1,self.warning)
+ if self.ask_YesOrNo(info):
+ rc=self.raw_format(target, format_type, name)
self.operation=False
if rc == 0:
message = _('The device was formatted successfully.')
@@ -365,31 +303,24 @@ class IsoDumper:
elif rc == 5:
message = _("An error occurred while creating a partition.")
self.logger(message)
- self.emergency()
+ self.emergency(message)
elif rc == 127:
message = _('Authentication error.')
self.logger(message)
- self.emergency()
+ self.emergency(message)
else:
message = _('An error occurred.')
- self.emergency()
- self.wTree.get_widget("format").hide()
- self.backup_select.set_sensitive(True)
- self.wTree.get_widget("format_button").set_sensitive(True)
- self.wTree.get_widget("filechooserbutton").set_sensitive(True)
- else:
- dialog.hide()
-
- def restore(self,widget):
- self.backup_select.set_sensitive(True)
- self.wTree.get_widget("format_button").set_sensitive(True)
- self.wTree.get_widget("filechooserbutton").set_sensitive(True)
- self.devicelist.set_sensitive(True)
- self.wTree.get_widget("emergency_dialog").hide()
- progress = self.wTree.get_widget("progressbar")
- progress.set_text("")
- progress.set_fraction(0)
- progress.set_sensitive(False)
+ self.emergency(message)
+
+ def restore(self):
+ self.backup_select.setEnabled()
+ self.backupbt.setDisabled()
+ self.formatbt.setEnabled()
+ self.ima.setEnabled()
+ self.devicelist.setEnabled()
+ self.progress.setLabel("")
+ self.progress.setValue(0)
+ self.progress.setDisabled()
def raw_format(self, usb_path, fstype, label):
self.operation=True
@@ -410,84 +341,64 @@ class IsoDumper:
working= False
return rc
- def format_cancel(self, widget):
- dialog=self.wTree.get_widget("format")
- dialog.hide()
- self.backup_select.set_sensitive(True)
- format_button=self.wTree.get_widget("format_button")
- filechooserbutton=self.wTree.get_widget("filechooserbutton")
- format_button.set_sensitive(True)
- filechooserbutton.set_sensitive(True)
- self.devicelist.set_sensitive(True)
-
- def backup_go(self,widget):
- dest = self.backup_dest
+ def backup_go(self):
+ dest = self.backup_img_name
if os.path.exists(dest):
- dialog=self.wTree.get_widget("confirm_overwrite")
- resp=dialog.run()
- if resp !=-5: # GTK_RESPONSE_OK
- dialog.hide()
+ info = Info(_("Backup confirmation"),1,_("Do you want to overwrite the file?"))
+ if not(self.ask_YesOrNo(info)):
+ self.returncode = 1
return True
- else:
- dialog.hide()
- # check free space
st = os.statvfs(os.path.dirname(dest))
free = st.f_bavail * st.f_frsize
if free<self.deviceSize :
sizeM=str(self.deviceSize/(1024*1024))
- self.logger(_("The destination directory is too small to receive the backup (%s Mb needed)")%(sizeM))
- self.emergency()
+ 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
source = self.dev.split('(')[1].split(')')[0]
self.logger(_('Backup in:')+' '+dest)
- task = self.raw_write(source, dest, self.deviceSize)
- gobject.idle_add(task.next)
- while gtk.events_pending():
- gtk.main_iteration(True)
+ self.raw_write(source, dest, self.deviceSize)
if self.returncode==0:
self.success()
-
- def do_write(self, widget):
- write_button = self.wTree.get_widget("write_button")
- write_button.set_sensitive(False)
- combo = self.wTree.get_widget("device_combobox")
- combo.set_sensitive(False)
- format_button=self.wTree.get_widget("format_button")
- format_button.set_sensitive(False)
- backup_select=self.wTree.get_widget("backup_select")
- backup_select.set_sensitive(False)
- source = self.chooser.get_filename()
+ self.restore()
+
+
+ def do_write(self):
+# write_button = self.wTree.get_widget("write_button")
+ self.writebt.setDisabled()
+ self.devicelist.setDisabled()
+ self.formatbt.setDisabled()
+ self.backupbt.setDisabled()
+ self.backup_select.setDisabled()
+ self.progress.setEnabled()
+ source = self.img_name
target = self.dev.split('(')[1].split(')')[0]
- dialog = self.wTree.get_widget("confirm_dialog")
-# if self.backup.get_active() :
-# backup_dest=self.backup_select.get_label()
-# self.logger(_('Image: ')+source)
+ self.logger(_('Image: ')+source)
self.logger(_('Target Device: ')+self.dev)
b = os.path.getsize(source)
if b > (self.deviceSize):
- self.logger(_('The device is too small to contain the ISO file.'))
- self.emergency()
+ message = _('The device is too small to contain the ISO file.')
+ self.logger(message)
+ self.emergency(message)
else:
- resp = dialog.run()
- if resp:
+ info = Info(_("Writing confirmation"),1,self.warning)
+ if self.ask_YesOrNo(info):
if self.deviceSize> 1024*1024*1024*32 :
- message=self.wTree.get_widget("label1")
- message.set_text(_('The device is bigger than 32 Gbytes. Are you sure you want use it?'))
- resp = dialog.run()
- if resp:
+ info = Info(_("Warning"),2,_('The device is bigger than 32 Gbytes.\
+ Are you sure you want use it?'))
+ if self.ask_YesOrNo(info):
pass
else:
- self.emergency()
- dialog.hide()
+ self.emergency(message)
return
- self.chooser.set_sensitive(False)
+ self.ima.setDisabled()
+ self.writebt.setDisabled()
self.do_umount(target)
- dialog.hide()
# Writing step
# Iso dump or Uefi preparation
- uefi_checkbox=self.wTree.get_widget("uefi_check")
- if uefi_checkbox.get_active():
+ if self.uefi_check.isChecked():
#uefi mode : formats FAT32, names MGALIVE, copies the ISO
target = self.dev.split('(')[1].split(')')[0]
dev_name="MGALIVE"
@@ -495,15 +406,14 @@ class IsoDumper:
if rc == 5:
message = _("An error occurred while creating a partition.")
self.logger(message)
- self.emergency()
+ self.emergency(message)
elif rc == 127:
message = _('Authentication error.')
self.logger(message)
- self.emergency()
+ self.emergency(message)
elif rc == 0:
message = _('The device was formatted successfully.')
self.logger(message)
-# time.sleep(2)
seen=False
part=target+'1'
while(not seen):
@@ -516,104 +426,98 @@ class IsoDumper:
try:
dest=self.u.mount(part)
except:
- self.logger(_("Error mounting the partition %s")%part)
- self.emergency()
+ message = _("Error mounting the partition %s")%part
+ self.logger(message)
+ self.emergency(message)
return
if dest!="":
- self.logger(_("Mounted in: ")+dest)
+ self.logger(_("Mounted in: "))
self.returncode=0
- task = self.files_write(source, dest, b)
- gobject.idle_add(task.next)
+ self.files_write(source, dest)
self.operation=False
- while gtk.events_pending():
- gtk.main_iteration(True)
if self.returncode==0:
self.success()
else:
- self.logger(_("Error copying files"))
- self.emergency()
+ message = _("Error copying files")
+ self.logger(message)
+ self.emergency(message)
+ try:
+ self.u.unmount(part)
+ except:
+ pass
else:
self.operation=False
- self.logger(_("Error mounting the partition %s")%part)
- self.emergency()
+ message = _("Error mounting the partition %s")%part
+ self.logger(message)
+ self.emergency(message)
else:
message = _('An error occurred.')
- self.emergency()
+ self.emergency(message)
else:
#Dump mode
self.returncode=0
b=os.path.getsize(source)
- task = self.raw_write(source, target, b)
- gobject.idle_add(task.next)
- while gtk.events_pending():
- gtk.main_iteration(True)
- task = self.check_write(target, b)
- gobject.idle_add(task.next)
- while gtk.events_pending():
- gtk.main_iteration(True)
+ self.raw_write(source, target, b)
+ self.check_write(target, b)
if self.returncode == 0:
self.success()
else:
- dialog.hide()
- combo.set_sensitive(True)
- write_button.set_sensitive(True)
- format_button.set_sensitive(True)
- backup_select.set_sensitive(True)
+ self.restore()
def do_umount(self, target):
mounts = self.get_mounted(target)
if mounts:
self.logger(_('Unmounting all partitions of ')+target+':')
for mount in mounts:
self.logger(_('Trying to unmount ')+mount[0]+'...')
- while gtk.events_pending():
- gtk.main_iteration(True)
try:
retcode = call('umount '+mount[0], shell=True)
if retcode < 0:
- self.logger(_('Error, umount ')+mount[0]+_(' was terminated by signal ')+str(retcode))
- self.emergency()
+ message = _('Error, umount ')+mount[0]+_(' was terminated by signal ')+str(retcode)
+ self.logger(message)
+ self.emergency(message)
else:
if retcode == 0:
self.logger(mount[0]+_(' successfully unmounted'))
else:
- self.logger(_('Error, umount ')+mount[0]+_(' returned ')+str(retcode))
- self.emergency()
+ message = _('Error, umount ')+mount[0]+_(' returned ')+str(retcode)
+ self.logger(message)
+ self.emergency(message)
except OSError, e:
- self.logger(_('Execution failed: ')+str(e))
- self.emergency()
+ message = _('Execution failed: ')+str(e)
+ self.logger(message)
+ self.emergency(message)
def get_mounted(self, 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:
- self.logger(_('Could not read mtab !'))
- self.emergency()
+ message = _('Could not read mtab !')
+ self.logger(message)
+ self.emergency(message)
def raw_write(self, source, target, b):
self.operation=True
-
bs=4096*128
try:
ifc=io.open(source, "rb",1)
except:
- self.logger(_('Reading error.')+ source)
- self.emergency()
+ message = _('Reading error.')+ source
+ self.logger(message)
+ self.emergency(message)
return
else:
try:
ofc= io.open(target, 'wb',0)
except:
- self.logger(_('You have not the rights for writing on the device'))
- self.emergency()
- self.close('dummy')
+ message = _('You have not the rights for writing on the device')
+ self.logger(message)
+ self.emergency(message)
+ self.close()
else:
- progress = self.wTree.get_widget("progressbar")
- progress.set_sensitive(True)
- progress.set_text(_('Writing ')+source.split('/')[-1]+_(' to ')+target.split('/')[-1])
+ self.progress.setEnabled()
+ self.progress.setLabel(_('Writing ')+source.split('/')[-1]+_(' to ')+target.split('/')[-1])
self.logger(_('Executing copy from ')+source+_(' to ')+target)
- while gtk.events_pending():
- gtk.main_iteration(True)
steps=range(0, b+1, b/100)
steps.append(b)
indice=1
@@ -626,49 +530,46 @@ class IsoDumper:
try:
buf=ifc.read(bs)
except:
- self.logger(_("Reading error."))
- self.emergency()
+ message = _("Reading error.")
+ self.logger(message)
+ self.emergency(message)
return
try:
ofc.write(buf)
except:
- self.logger(_("Writing error."))
- self.emergency()
+ message = _("Writing error.")
+ self.logger(message)
+ self.emergency(message)
return
written+=len(buf)
if written > steps[indice]:
if indice%1==0:
self.logger(_('Wrote: ')+str(indice)+'% '+str(written)+' bytes')
- mark = self.log.create_mark("end", self.log.get_end_iter(), False)
- self.logview.scroll_to_mark(mark, 0.05, True, 0.0, 1.0)
- progress.set_fraction(float(indice)/100)
- while gtk.events_pending():
- gtk.main_iteration(True)
+ self.progress.setValue(indice)
indice +=1
try:
os.fsync(ofc)
except:
- self.logger(_("Writing error."))
- self.emergency()
+ message = _("Writing error.")
+ self.logger(message)
+ self.emergency(message)
return
- yield True
- progress.set_fraction(1.0)
+ self.progress.setValue(100)
self.logger(_('Image ')+source.split('/')[-1]+_(' successfully written to ')+target)
self.logger(_('Bytes written: ')+str(written))
try:
ofc.close()
except:
- self.logger(_("Writing error."))
- self.emergency()
+ message = _("Writing error.")
+ self.logger(message)
+ self.emergency(message)
ifc.close()
- yield False
def check_write(self, target, b):
import hashlib
- progress = self.wTree.get_widget("progressbar")
- progress.set_sensitive(True)
- progress.set_text(_('Checking ')+target.split('/')[-1])
- progress.set_fraction(0.0)
+ self.progress.setEnabled()
+ self.progress.setLabel(_('Checking ')+target.split('/')[-1])
+ self.progress.setValue(0)
steps=range(0, b+1, b/100)
steps.append(b)
indice=0
@@ -683,11 +584,8 @@ class IsoDumper:
sha1func.update(block)
md5func.update(block)
if checked > steps[indice]:
- progress.set_fraction(float(indice)/100)
+ self.progress.setValue(indice)
indice +=1
- while gtk.events_pending():
- gtk.main_iteration(True)
- yield True
checked+=1024
block = f.read(b-ncuts*1024)
sha1func.update(block)
@@ -696,17 +594,13 @@ class IsoDumper:
md5sumcalc=md5func.hexdigest()
self.logger(_('SHA1 sum: ')+sha1sumcalc)
self.logger(_('MD5 sum: ')+md5sumcalc)
- mark = self.log.create_mark("end", self.log.get_end_iter(), False)
- self.logview.scroll_to_mark(mark, 0.05, True, 0.0, 1.0)
f.close()
except:
pass
- progress.set_fraction(1.0)
- yield False
+ self.progress.setValue(100)
- def files_write(self, source, dest, size):
+ def files_write(self, source, dest):
self.operation=True
- self.logger(time.ctime(time.time()))
temp_dir='/mnt/MGALIVE'
makedirs(temp_dir)
self.process=Popen(['mount', '-o', 'loop',source,temp_dir ], shell=False, stdout=PIPE)
@@ -720,17 +614,14 @@ class IsoDumper:
else:
self.process = None
working=False
- self.logger(_('ISO image mounted in ')+temp_dir)
- progress = self.wTree.get_widget("progressbar")
- progress.set_sensitive(True)
- progress.set_text(_('Writing ')+source.split('/')[-1]+_(' to ')+dest)
- self.logger(_('Executing copy from ')+source+_(' to ')+dest)
- while gtk.events_pending():
- gtk.main_iteration(True)
total_files=countFiles(temp_dir)
- self.logger(_("%s file(s) to copy."%total_files))
cumuled_size=0
if total_files > 0:
+ self.logger(_('ISO image mounted in ')+temp_dir)
+ self.progress.setEnabled()
+ self.progress.setLabel(_('Writing ')+source.split('/')[-1]+_(' to ')+dest.encode())
+ self.logger(_('Executing copy from ')+source+_(' to ')+dest.encode())
+ self.logger(_("%s file(s) to copy."%total_files))
for path, dirs, filenames in os.walk(temp_dir):
for directory in dirs:
destDir = path.replace(temp_dir,dest)
@@ -748,74 +639,59 @@ class IsoDumper:
break
fdst.write(buf)
cumuled_size += len(buf)
- progress.set_fraction(min(float(cumuled_size)/size,1))
- print float(cumuled_size)/size
- while gtk.events_pending():
- gtk.main_iteration(True)
+ self.progress.setValue(int(cumuled_size*100/total_files))
except:
self.returncode=1
return
- while gtk.events_pending():
- gtk.main_iteration(True)
- yield True
self.process = Popen(['umount', temp_dir ], shell=False, stdout=PIPE)
while True :
self.process.poll()
if self.process.returncode != None:
break
- self.logger(_('Image ')+source.split('/')[-1]+_(' successfully written to ')+dest)
- self.logger(time.ctime(time.time()))
+ self.logger(_('Image ')+source.split('/')[-1]+_(' successfully written to ')+dest.encode())
else:
self.returncode=1
def success(self):
self.operation=False
- dialog = self.wTree.get_widget("success_dialog")
self.final_unsensitive()
- resp = dialog.run()
- if resp:
-# exit(0)
- dialog.hide()
+ info = Info(_("Success"),1,_("The operation was successfully performed.\n\
+ You are free to unplug it now, a log isodumper.log\n\
+ of the operation will be saved in your homedir/.isodumper/ when\n\
+ you close the application."))
+ if self.ask_OK(info) :
+ return
- def confirm_close(self, widget, *args):
+ def confirm_close(self, *args):
if self.operation==False: # no writing , backup nor format running
- self.close('dummy')
+ self.close()
else: # writing , backup or format running
- dialog=self.wTree.get_widget("Quit_warning")
- resp = dialog.run()
- if resp==-5 : # GTK_RESPONSE_OK
- self.close('dummy')
- else:
- dialog.hide()
+ info = Info(_("Warning"),1,_("Writing is in progress. Exiting during writing \n\
+ will occur that the device or the backup will be unusable.\n\
+ Are you sure you want to quit during writing?"))
+ if self.ask_YesOrNo(info) :
return True
+ else:
+ return False
- def emergency(self):
+ def emergency(self,message):
self.operation=False
self.returncode=1
self.final_unsensitive()
- dialog = self.wTree.get_widget("emergency_dialog")
- expander = self.wTree.get_widget("detail_expander")
- expander.set_expanded(True)
- mark = self.log.create_mark("end", self.log.get_end_iter(), False)
- self.logview.scroll_to_mark(mark, 0.05, True, 0.0, 1.0)
- resp = dialog.run()
- if resp:
- dialog.hide()
-# self.close()
+ info = Info(_("Error"),1,message)
+ self.ask_OK(info)
def final_unsensitive(self):
- self.chooser.set_sensitive(False)
- self.devicelist.set_sensitive(False)
- write_button = self.wTree.get_widget("write_button")
- write_button.set_sensitive(False)
- progress = self.wTree.get_widget("progressbar")
- progress.set_sensitive(False)
- self.backup_select.set_sensitive(False)
-
- def close(self, widget):
+ self.ima.setDisabled()
+ self.devicelist.setDisabled()
+ self.writebt.setDisabled()
+ self.progress.setDisabled()
+ self.backup_select.setDisabled()
+
+ def close(self):
self.write_logfile()
- gtk.main_quit()
+ self.dialog.destroy
exit(0)
def write_logfile(self):
@@ -840,47 +716,290 @@ class IsoDumper:
print self.log.get_text(start, end, False)
def logger(self, text):
- self.log.insert_at_cursor(text+"\n")
-
- def activate_devicelist(self, widget):
-# label = self.wTree.get_widget("to_label")
- expander = self.wTree.get_widget("detail_expander")
-# self.devicelist.set_sensitive(True)
- expander.set_sensitive(True)
-# label.set_sensitive(True)
- self.img_name = self.chooser.get_filename()
- write_button = self.wTree.get_widget("write_button")
- write_button.set_sensitive(True)
+ self.logview.appendLines(text+"\n")
+
+ def activate_devicelist(self):
+ self.devicelist.setEnabled()
+# self.img_name = self.chooser.get_filename()
+ self.writebt.setEnabled()
self.logger(_('Image ')+": "+ self.img_name)
- self.chooser.set_tooltip_text(self.img_name)
+# self.chooser.set_tooltip_text(self.img_name)
+
+ def help_dialog(self):
+ print "Help 2"
+ info = Info(_("IsoDumper"),0,_("Mageia IsoDumper\n\
+----------------\n\
+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. It gives also a feature for formatting the USB device.\n\
+\n\
+IsoDumper can be launched either from the menus, or a user or root console with the command 'isodumper'. For normal users, the root password is solicited; this is necessary for the program's operation. 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. (You may have to close any automatically opened File Manager window).\n\
+\n\
+The fields of the main window are as follows:\n\
+- Device to work on: the device of the USB flash drive, a drop-down list to choose from.\n\
+- Write Image: to choose the source ISO image *.iso (or flash drive backup file *.img) to write out.\n\
+- Write to device: This button launches the operation - with a prior warning dialogue. The operation is shown in the progress bar beneath.\n\
+- Backup in: 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.\n\
+- Backup the device: launch the backup operation.\n\
+- Format the device: create an unique partition on the entire volume in the specified format in FAT, NTFS or ext. You can specify a volume name and the format in a new dialog box.\n"))
+ if self.ask_OK(info) :
+ return
- def activate_backup(self, widget):
- self.backup_img_name = self.backup_dir.get_filename()
+ def __init__(self,user):
+ APP="isodumper"
+ DIR="/usr/share/locale"
+ self.RELEASE="v0.40"
-# def expander_control(self, widget):
-# # this is darn ugly but still better than the UI behavior of
-# # the unexpanded expander which doesnt reset the window size
-# if widget.get_expanded():
-# gobject.timeout_add(130, lambda: self.window.reshow_with_initial_size())
+ gettext.bindtextdomain(APP, DIR)
+ gettext.textdomain(APP)
- def help_dialog(self, widget):
- dialog = self.wTree.get_widget("help_dialog")
- dialog.run()
+ # for the localisation of log file
+ self.user = user
- def help_close(self, widget):
- dialog = self.wTree.get_widget("help_dialog")
- dialog.hide()
+ # define size of the selected device
+ self.deviceSize=0
- def about(self, widget):
- about_button = self.wTree.get_widget("about_button")
- about_button.set_sensitive(True)
- dialog = self.wTree.get_widget("about_dialog")
- resp = dialog.run()
- if resp:
- dialog.hide()
+ # Operation running
+ self.operation=False
+
+ self.warning = _("Warning\nThis will destroy all data on the target device,\n\
+ are you sure you want to proceed?\n\
+ If you say ok here, please <b>do not unplug</b>\
+ the device during the following operation.")
+ """
+ Init/Constructor for the 'widgets'
+ """
+ yui.YUI.app().setApplicationTitle("ManaDumper")
+ yui.YUI.app().setApplicationIcon("/usr/share/icons/isodumper.png")
+ self.atelier = yui.YUI.widgetFactory()
+ self.dialog = self.atelier.createMainDialog()
+ #self.dialog.setTitle("ManaDumper")
+ # create the main gui
+ # +---+-----------------+
+ # + banner +
+ # +---+-----------------+
+ # | devicelist |
+ # +---+-----+------+----+
+ # + L | ima | uefi_check | writebt |
+ # +---+-----+------+----+
+ # + L | backup_select | backupbt |
+ # +---+-----+------+----+
+ # + F | formatbt |
+ # +----------------+----+
+ # | progress |
+ # +---------------------+
+ # | report |
+ # +---------------------+
+ # | refreshbt | aboutbt | helpbt | quitbt |
+ # +---------------------+
+ self.ancrage = self.atelier.createReplacePoint(self.dialog)
+ self.box = self.atelier.createVBox(self.ancrage)
+ self.bannerbox = self.atelier.createHBox(self.box)
+# self.bannerbox.setWeight(1,15)
+ self.banner=self.atelier.createImage(self.bannerbox,"/usr/share/isodumper/header.png")
+ self.devicebox = self.atelier.createHBox(self.box)
+ self.devicebox.setWeight(1,10)
+ self.devicelist=self.atelier.createComboBox(self.devicebox,_("Device to use:"),False)
+ self.devicelist.setStretchable(0,True)
+ self.writebox = self.atelier.createHBox(self.box)
+ #self.writebox.setWeight(1,10)
+ self.atelier.createLabel(self.writebox,_("Write Image:"))
+ # add file picker
+ self.ima=self.atelier.createPushButton(self.writebox,"Choose an image")
+ self.ima.setStretchable(0,True)
+ self.uefi_check=self.atelier.createCheckBox(self.writebox,_("For UEFI"))
+ self.atelier.createHStretch(self.writebox)
+ self.writebt = self.atelier.createPushButton(self.writebox, _("&Write" ))
+ #self.writebt.setStretchable(0,True)
+ self.writebt.setDisabled()
+ self.backupbox = self.atelier.createHBox(self.box)
+ #self.backupbox.setWeight(1,10)
+ self.atelier.createLabel(self.backupbox,_("Backup to:"))
+ self.backup_select=self.atelier.createPushButton(self.backupbox,"Choose an image")
+ self.backup_select.setStretchable(0,True)
+ self.atelier.createHStretch(self.backupbox)
+ self.backupbt = self.atelier.createPushButton(self.backupbox, _("&Backup" ))
+ #self.backupbt.setStretchable(0,True)
+ self.backupbt.setDisabled()
+ self.formatbox = self.atelier.createHBox(self.box)
+ #self.formatbox.setWeight(1,10)
+ self.atelier.createLabel(self.formatbox,_("Format the device in FAT, NTFS or ext:"))
+ self.atelier.createHStretch(self.formatbox)
+ self.formatbt = self.atelier.createPushButton(self.formatbox, _("&Format" ))
+ #self.formatbt.setStretchable(0,True)
+ self.progressbox = self.atelier.createHBox(self.box)
+ self.progressbox.setWeight(1,10)
+ self.progress = self.atelier.createProgressBar(self.progressbox,"Progression",100)
+ self.reportbox = self.atelier.createHBox(self.box)
+ #self.reportbox.setWeight(1,10)
+ self.logview = self.atelier.createLogView(self.reportbox,"Report", 10)
+ #self.reportbox.setWeight(1,20)
+ self.buttonsbox = self.atelier.createHBox(self.box)
+ #self.buttonsbox.setWeight(1,10)
+# self.cadregauche= self.atelier.createFrame(self.mainhbox,"Traitements par lots")
+ self.refreshbt = self.atelier.createPushButton(self.buttonsbox, _("&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)
+ if not self.get_devices():
+ self.dialog.destroy()
+ self.device_selected()
+ self.dialog.recalcLayout()
+ self.ancrage.showChild()
+
+ def ask_format(self):
+ self.ima.setDisabled()
+ self.formatbt.setDisabled()
+ self.backup_select.setDisabled()
+ self.writebt.setDisabled()
+ self.devicelist.setDisabled()
+ atelier = yui.YUI.widgetFactory()
+ dialog = atelier.createPopupDialog()
+# dialog.setTitle(_("Choose format"))
+ 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)"))
+ vb_c2 = atelier.createHBox(vb_c)
+ 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)"))
+ bb = atelier.createHBox(vb)
+ executebt = atelier.createPushButton(bb,_("Execute"))
+ cancelbt = atelier.createPushButton(bb,_("Cancel"))
+ dialog.open()
+ returncode = True
+ while True:
+ event = dialog.waitForEvent()
+ if event.eventType() == yui.YEvent.CancelEvent:
+ returncode = False
+ break
+ if event.widget() == executebt:
+ if format_fat.value():
+ format_type = 'fat32'
+ format_label = label.value().upper()[:11]
+ break
+ if format_ntfs.value():
+ format_type = 'ntfs'
+ format_label = label.value()[:32]
+ break
+ if format_ext.value():
+ format_type = 'ext4'
+ format_label = label.value()
+ break
+ if event.widget() == cancelbt:
+ self.restore()
+ returncode = False
+ break
+ dialog.destroy()
+ if returncode:
+ return True,format_type,format_label
+ else:
+ return False," "," "
+
+
+ def ask_OK(self, info):
+ yui.YUI.widgetFactory
+ mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga"))
+ dlg = mgafactory.createDialogBox(yui.YMGAMessageBox.B_ONE)
+ dlg.setTitle(info.title)
+ dlg.setText(info.text, info.richtext)
+ dlg.setButtonLabel("OK", yui.YMGAMessageBox.B_ONE)
+ dlg.setMinSize(50, 5);
+ return dlg.show() == yui.YMGAMessageBox.B_ONE
+
+ def ask_YesOrNo(self, info):
+ yui.YUI.widgetFactory
+ mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga"))
+ dlg = mgafactory.createDialogBox(yui.YMGAMessageBox.B_TWO)
+ 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(70, 8);
+ return dlg.show() == yui.YMGAMessageBox.B_ONE
+
+ def aboutDialog(self):
+ yui.YUI.widgetFactory;
+ mgafactory = yui.YMGAWidgetFactory.getYMGAWidgetFactory(yui.YExternalWidgets.externalWidgetFactory("mga"))
+ dlg = mgafactory.createAboutDialog("About Isodumper", self.RELEASE, "GPLv2",
+ "Oliver Grawert\nPapoteur", "A tool for writing ISO images to a device", "")
+ 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.setButtonLabel("Refresh", yui.YMGAMessageBox.B_ONE)
+ dlg.setButtonLabel("Cancel", yui.YMGAMessageBox.B_TWO)
+ dlg.setMinSize(70, 8);
+ return dlg.show() == yui.YMGAMessageBox.B_ONE
+
+ def handleevent(self):
+ self.traitement=None
+ while True:
+ event = self.dialog.waitForEvent()
+ if event.eventType() == yui.YEvent.CancelEvent:
+ self.dialog.destroy()
+ break
+ if event.widget() == self.quitbt:
+ self.dialog.destroy()
+ break
+ if event.widget() == self.ima:
+ self.img_name=yui.YUI.app().askForExistingFile('file:///home/'+self.user,"*.iso *.img","Choose an image")
+ self.ima.setLabel(self.img_name)
+
+ self.activate_devicelist()
+ if event.widget() == self.writebt:
+ self.do_write()
+ if event.widget() == self.backupbt:
+ self.backup_go()
+ if event.widget() == self.backup_select:
+ self.backup_img_name=yui.YUI.app().askForSaveFileName('file:///home/'+self.user,"*.img","Backup to:")
+ if self.backup_img_name != '':
+ 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()
+ try:
+ if event.widget() == self.refreshbt:
+ self.update_list()
+ except:
+ pass
+ try:
+ if event.widget() == self.helpbt:
+ print "help"
+ self.help_dialog()
+ except:
+ pass
+ try:
+ if event.widget() == self.quitbt:
+ self.confirm_close()
+ except:
+ pass
+ if event.widget() == self.aboutbt:
+ self.aboutDialog()
if __name__ == "__main__":
import sys
user=sys.argv[1]
app = IsoDumper(user)
- gtk.main()
+ app.handleevent()
+
+