aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/isodumper.py954
-rwxr-xr-xlib/raw_format.py52
2 files changed, 579 insertions, 427 deletions
diff --git a/lib/isodumper.py b/lib/isodumper.py
index 8af078e..c62089b 100755
--- a/lib/isodumper.py
+++ b/lib/isodumper.py
@@ -1,4 +1,6 @@
-#!/usr/bin/python
+#coding:utf-8
+
+#!/usr/bin/python3
#
# Copyright (c) 2007-2009 Canonical Ltd.
#
@@ -21,17 +23,35 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-# Requires python-parted
+# Requires python3-parted
+
+# ensure we're using the latest build, if called from our build environment
+import sys
+import imp
+
+sys.path.insert(0,'../../../build/swig/python3')
+imp.reload(sys)
+###########
+# 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 gtk
-import gtk.glade
-import gobject
import os, re
import io
import gettext
from gettext import gettext as _
from subprocess import call, Popen, PIPE
-import time
import dbus
@@ -55,6 +75,18 @@ class UDisks2(object):
raise NoUDisks2()
raise
+ def node_mountpoint(self,node):
+
+ def de_mangle(raw):
+ return raw.replace('\\040', ' ').replace('\\011', '\t').replace('\\012',
+ '\n').replace('\\0134', '\\')
+
+ for line in open('/proc/mounts').readlines():
+ line = line.split()
+ if line[0] == node:
+ return de_mangle(line[1])
+ return None
+
def device(self, device_node_path):
device_node_path = os.path.realpath(device_node_path)
devname = device_node_path.split('/')[-1]
@@ -76,7 +108,7 @@ class UDisks2(object):
devs = self.bus.get_object('org.freedesktop.UDisks2',
'/org/freedesktop/UDisks2/block_devices')
xml = devs.Introspect(dbus_interface='org.freedesktop.DBus.Introspectable')
- for dev in re.finditer(r'name=[\'"](.+?)[\'"]', type(u'')(xml)):
+ for dev in re.finditer(r'name=[\'"](.+?)[\'"]', type('')(xml)):
bd = self.bus.get_object('org.freedesktop.UDisks2',
'/org/freedesktop/UDisks2/block_devices/%s2'%dev.group(1))
try:
@@ -98,10 +130,10 @@ class UDisks2(object):
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()]
+ [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()]
+ [re_block.match(path) for path in (objects.keys())]
if m]
list=[]
@@ -120,194 +152,90 @@ class UDisks2(object):
item.append(path)
item.append(size)
list.append(item)
- self.device_nb=len(list)
return list
- def unmount(self, device_node_path):
- d = self.device(device_node_path)
- d.Unmount({'force':True, 'auth.no_user_interaction':True},
- dbus_interface=self.FILESYSTEM)
-
-class IsoDumper:
- def __init__(self,user):
- APP="isodumper"
- DIR="/usr/share/locale"
- RELEASE="v0.47"
-
- 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)
+ def drive_for_device(self, device):
+ drive = device.Get(self.BLOCK, 'Drive',
+ dbus_interface='org.freedesktop.DBus.Properties')
+ return self.bus.get_object('org.freedesktop.UDisks2', drive)
- # 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)
+ def eject(self, device_node_path):
+ drive = self.drive_for_device(self.device(device_node_path))
+ drive.Eject({'auth.no_user_interaction':True},
+ dbus_interface=self.DRIVE)
- # 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)
-
-
- # 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")
-
-
- # 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()
+class Info(object):
+ def __init__(self,title,richtext,text):
+ self.title=title
+ self.richtext=richtext
+ self.text=text
- def update_list(self, widget):
- for i in xrange(self.device_nb):
- self.devicelist.remove_text(0)
- self.get_devices()
- self.restore(widget)
+
+class IsoDumper(object):
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 size != 0 :
+ if self.nodevDialog():
+ self.list = self.u.find_devices()
+ else:
+ return False
+ break
+ self.devicelist.addItem("",False)
+ if len(self.list)>0:
+ for name, path, size in self.list:
+ if size != 0 :
# convert in Mbytes
- sizeM=str(int(size)/(1024*1024))
- self.devicelist.append_text(name+' ('+path.lstrip()+') '+sizeM+_('Mb'))
- self.device_nb=len(self.list)
- dialog.hide()
-
- def device_selected(self, widget):
- self.dev = self.devicelist.get_active_text()
- if self.dev != None:
+ 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.img_name = ""
+ self.ima.setLabel(self.ChooseImage)
+ self.backup_select.setLabel(self.ChooseImage)
+ self.restore()
+
+ 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(' ', '')
+ self.logger(_('Target Device: ')+ self.dev)
+ self.formatbt.setEnabled()
+ self.ima.setEnabled()
+ self.backup_select.setEnabled()
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.logger(_('Target Device: ')+ self.dev)
-
- def backup_sel(self,widget):
+
+
+ def backup_sel(self):
if self.backup_bname.get_current_folder_uri() == None :
self.backup_bname.set_current_folder_uri('file:///home/'+self.user)
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"),True,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.')
@@ -316,39 +244,34 @@ 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.setDisabled()
+ self.backupbt.setDisabled()
+ self.formatbt.setDisabled()
+ self.ima.setDisabled()
+ self.writebt.setDisabled()
+ self.devicelist.setEnabled()
+ self.progress.setLabel("")
+ self.progress.setValue(0)
+ self.progress.setDisabled()
+ self.refreshbt.setEnabled()
def raw_format(self, usb_path, fstype, label):
self.operation=True
if os.geteuid() > 0:
launcher='pkexec'
- self.process = Popen([launcher,'/usr/bin/python', '-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)
+ 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/python', '-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)
+ 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)
@@ -361,300 +284,263 @@ 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"),True,_("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.logger(_('Backup to:')+' '+dest)
+ self.raw_write(source, dest, self.deviceSize)
if self.returncode==0:
self.success()
+
- def do_write(self, widget):
+ def do_write(self):
self.returncode = 0
- 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.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")
- self.logger(_('Target Device: ')+self.dev)
+# 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"),True,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"),True,_('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()
if self.returncode != 1:
# Writing step
- #Dump mode
+ #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)
if self.returncode == 0:
+ self.check_write(target, b)
self.success()
else:
- self.restore(widget)
+ self.restore()
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 == 32:
message = _('Partition %s is busy')%mount[0]
self.logger(message)
- self.emergency()
+ self.emergency(message)
elif 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)
elif retcode == 0:
self.logger(mount[0]+_(' successfully unmounted'))
else:
- self.logger(_('Error, umount ')+mount[0]+_(' returned ')+str(retcode))
- self.emergency()
- except OSError, e:
- self.logger(_('Execution failed: ')+str(e))
- self.emergency()
+ message = _('Error, umount ')+mount[0]+_(' returned ')+str(retcode)
+ self.logger(message)
+ self.emergency(message)
+ except OSError as e:
+ 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 don't have permission to write to the device") +" "+ target
+ 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.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=list(range(0, b+1, int(b/100)))
steps.append(b)
indice=1
written=0
- ncuts=b/bs
+ ncuts=int(b/bs)
while ncuts <= 100:
- bs=bs/2
- ncuts=b/bs
- for i in xrange(0,ncuts+1):
+ bs=int(bs/2)
+ ncuts=int(b/bs)
+ for i in range(0,int(ncuts)+1):
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)
+ self.dialog.pollEvent()
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)
- steps=range(0, b+1, b/100)
+ self.progress.setEnabled()
+ self.progress.setLabel(_('Checking ')+target.split('/')[-1])
+ self.progress.setValue(0)
+ steps=list(range(0, b+1, int(b/100)))
steps.append(b)
indice=0
checked=0
sha1func=hashlib.sha1()
md5func=hashlib.md5()
- ncuts=b/1024
+ ncuts=int(b/1024)
try:
- with open(target, 'rb') as f:
- for x in xrange(0,ncuts):
- block = f.read(1024)
- sha1func.update(block)
- md5func.update(block)
- if checked > steps[indice]:
- progress.set_fraction(float(indice)/100)
- indice +=1
- while gtk.events_pending():
- gtk.main_iteration(True)
- yield True
- checked+=1024
- block = f.read(b-ncuts*1024)
- sha1func.update(block)
- md5func.update(block)
- sha1sumcalc=sha1func.hexdigest()
- 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
+ with open(target, 'rb') as f:
+ for x in range(0,ncuts):
+ block = f.read(1024)
+ sha1func.update(block)
+ md5func.update(block)
+ if checked > steps[indice]:
+ self.progress.setValue(indice)
+ self.dialog.pollEvent()
+ indice +=1
+ checked+=1024
+ block = f.read(b-ncuts*1024)
+ sha1func.update(block)
+ md5func.update(block)
+ sha1sumcalc=sha1func.hexdigest()
+ md5sumcalc=md5func.hexdigest()
+ self.logger(_('SHA1 sum: ')+sha1sumcalc)
+ self.logger(_('MD5 sum: ')+md5sumcalc)
+ f.close()
+ except:
+ pass
+ self.progress.setValue(100)
def success(self):
self.operation=False
- dialog = self.wTree.get_widget("success_dialog")
self.final_unsensitive()
- resp = dialog.run()
- if resp:
- dialog.hide()
+ 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
- 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"),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) :
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()
+ info = Info(_("Error"),True,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 wip_unsensitive(self):
+ self.ima.setDisabled()
+ self.devicelist.setDisabled()
+ self.writebt.setDisabled()
+ self.backup_select.setDisabled()
+ self.backupbt.setDisabled()
+ self.refreshbt.setDisabled()
+
+ def close(self):
self.write_logfile()
- gtk.main_quit()
- exit(0)
+ self.dialog.destroy()
+ #exit(0)
def write_logfile(self):
- start = self.log.get_start_iter()
- end = self.log.get_end_iter()
import pwd
pw = pwd.getpwnam(self.user)
uid = pw.pw_uid
@@ -667,45 +553,311 @@ class IsoDumper:
os.mkdir(logpath)
else:
logpath='/root'
- logfile=open(logpath+'/isodumper.log',"w")
- logfile.write(self.log.get_text(start, end, False))
+ logfile=open(logpath+'/isodumper.log',"w", encoding="utf-8")
+ logfile.write(self.logview.logText())
logfile.close()
- print self.log.get_text(start, end, False)
+ print((self.logview.logText()))
def logger(self, text):
- self.log.insert_at_cursor(text+"\n")
-
- def activate_devicelist(self, widget):
- expander = self.wTree.get_widget("detail_expander")
- expander.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.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):
+ 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<BR />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 or root console with the command 'isodumper'.<BR />\
+For normal users, the root password is solicited; 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 />\
+- 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 />\
+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, \
+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 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.51"
- def help_dialog(self, widget):
- dialog = self.wTree.get_widget("help_dialog")
- dialog.run()
+ gettext.bindtextdomain(APP, DIR)
+ gettext.textdomain(APP)
- def help_close(self, widget):
- dialog = self.wTree.get_widget("help_dialog")
- dialog.hide()
+ # for the localisation of log file
+ self.user = user
- 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()
+ # define size of the selected device
+ self.deviceSize=0
+
+ # Operation running
+ self.operation=False
+
+ self.ChooseImage = _("Choose an image")
+ 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(_("IsoDumper")+" "+self.RELEASE)
+ yui.YUI.app().setApplicationIcon("/usr/share/icons/isodumper.png")
+ self.atelier = yui.YUI.widgetFactory()
+ self.dialog = self.atelier.createPopupDialog()
+ # create the main gui
+ # +---+-----------------+
+ # + banner +
+ # +---+-----------------+
+ # | devicelist |
+ # +---+-----+------+----+
+ # + L | ima | 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.banner=self.atelier.createImage(self.bannerbox,"/usr/share/isodumper/header.svg")
+ self.devicebox = self.atelier.createHBox(self.box)
+ self.devicebox.setWeight(1,10)
+ self.devicelist=self.atelier.createComboBox(self.devicebox,_("Device to work on:"),False)
+ self.devicelist.setNotify()
+ self.devicelist.setStretchable(0,True)
+ self.writebox = self.atelier.createHBox(self.box)
+ 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.setDisabled()
+ self.atelier.createHStretch(self.writebox)
+ self.writebt = self.atelier.createPushButton(self.writebox, _("&Write to device" ))
+ self.writebt.setDisabled()
+ self.backupbox = self.atelier.createHBox(self.box)
+ 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.setDisabled()
+ self.atelier.createHStretch(self.backupbox)
+ self.backupbt = self.atelier.createPushButton(self.backupbox, _("&Backup the device" ))
+ 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 the device" ))
+ self.formatbt.setDisabled()
+ self.progressbox = self.atelier.createHBox(self.box)
+ self.progressbox.setWeight(1,10)
+ self.progress = self.atelier.createProgressBar(self.progressbox,_("Progression"),100)
+ self.progress.setStretchable(0,True)
+ self.reportbox = self.atelier.createHBox(self.box)
+ #self.reportbox.setWeight(1,10)
+ self.logview = self.atelier.createLogView(self.reportbox,_("Report"), 10)
+ self.logview.setStretchable(0,True)
+ #self.reportbox.setWeight(1,20)
+ self.buttonsbox = self.atelier.createHBox(self.box)
+ #self.buttonsbox.setWeight(1,10)
+ 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(60, 10);
+ 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(60, 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("Isodumper", self.RELEASE, "GPLv2",
+ "Oliver Grawert<BR />Papoteur<BR />Pictures : Thimotée Giet", _("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(60, 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.close()
+ break
+ if event.widget() == self.quitbt:
+ self.close()
+ 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.writebt.setEnabled()
+ self.activate_devicelist()
+ if event.widget() == self.writebt:
+ 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('file:///home/'+self.user,"*.img","Backup to:")
+ if self.backup_img_name != '':
+ self.backup_choosed()
+ if event.widget() == self.formatbt:
+ self.wip_unsensitive()
+ 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:
+ if event.widget() == self.refreshbt:
+ self.update_list()
+ except:
+ pass
+ try:
+ if event.widget() == self.helpbt:
+ 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()
+
+
diff --git a/lib/raw_format.py b/lib/raw_format.py
index b634470..0cce0e9 100755
--- a/lib/raw_format.py
+++ b/lib/raw_format.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
#
# imported from project Mintstick, by Clement Lefebvre
# https://github.com/linuxmint/mintstick/
@@ -24,7 +24,7 @@
import os, sys
import getopt
-import parted
+
from subprocess import call
sys.path.append('/usr/lib/isodumper')
@@ -32,22 +32,22 @@ sys.path.append('/usr/lib/isodumper')
def do_umount(target):
mounts = get_mounted(target)
if mounts:
- print 'Unmounting all partitions of '+target+':'
+ print('Unmounting all partitions of '+target+':')
for mount in mounts:
- print 'Trying to unmount '+mount[0]+'...'
+ 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)
+ print('Error, umount '+mount[0]+' was terminated by signal '+str(retcode))
sys.exit(6)
else:
if retcode == 0:
- print mount[0]+' successfully unmounted'
+ print(mount[0]+' successfully unmounted')
else:
- print 'Error, umount '+mount[0]+' returned '+str(retcode)
+ print('Error, umount '+mount[0]+' returned '+str(retcode))
sys.exit(6)
- except OSError, e:
- print 'Execution failed: '+str(e)
+ except OSError as e:
+ print('Execution failed: '+str(e))
sys.exit(6)
@@ -56,11 +56,11 @@ def get_mounted(target):
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 !'
+ print('Could not read mtab !')
sys.exit(6)
def raw_format(device_path, fstype, volume_label, uid, gid):
-
+ import parted
do_umount(device_path)
# First erase MBR and partition table , if any
@@ -74,7 +74,7 @@ def raw_format(device_path, fstype, volume_label, uid, gid):
disk.commit()
except:
# Unable to write the new partition
- print "Can't create partition. The device could be read-only."
+ print("Can't create partition. The device could be read-only.")
sys.exit(5)
regions = disk.getFreeSpaceRegions()
@@ -93,7 +93,7 @@ def raw_format(device_path, fstype, volume_label, uid, gid):
try:
geometry = parted.Geometry(device=device, start=start, end=end)
except:
- print "Geometry error - Can't create partition"
+ print("Geometry error - Can't create partition")
sys.exit(5)
# fstype
@@ -122,26 +122,26 @@ 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="])
- except getopt.error, msg:
- print msg
- print "for help use --help"
+ except getopt.error as msg:
+ print(msg)
+ print("for help use --help")
sys.exit(2)
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 "-d|--device : device path"
- print "-f|--filesystem : filesystem\n"
- print "-l|--label : volume label\n"
- print "-u|--uid : uid of user\n"
- print "-g|--gid : gid of user\n"
- print "Example : %s -d /dev/sdj -f fat32 -l \"USB Stick\" -u 1000 -g 1000" % 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")
+ print("-u|--uid : uid of user\n")
+ print("-g|--gid : gid of user\n")
+ print("Example : %s -d /dev/sdj -f fat32 -l \"USB Stick\" -u 1000 -g 1000" % sys.argv[0])
sys.exit(0)
elif o in ("-d"):
device = a
elif o in ("-f"):
if a not in [ "fat32", "ntfs", "ext4" ]:
- print "Specify fat32, ntfs or ext4"
+ print("Specify fat32, ntfs or ext4")
sys.exit(3)
fstype = a
elif o in ("-l"):
@@ -153,8 +153,8 @@ def main():
argc = len(sys.argv)
if argc < 11:
- print "Too few arguments"
- print "for help use --help"
+ print("Too few arguments")
+ print("for help use --help")
exit(2)
raw_format(device, fstype, label, uid, gid)