152 lines
4.9 KiB
Python
152 lines
4.9 KiB
Python
#!/usr/bin/python
|
|
|
|
# Copyright (C) 2009 Canonical Ltd.
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version 3,
|
|
# as published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import gettext
|
|
import logging, logging.handlers
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
# Padding for the kernel and initramfs, in megabytes
|
|
PADDING = 30
|
|
(CAN_USE, # Obvious.
|
|
CANNOT_USE, # The partition or disk is too small for the source image.
|
|
NEED_SPACE, # There is not enough free space, but there could be.
|
|
NEED_FORMAT, # The device has the wrong filesystem type, or the source is a
|
|
# disk image.
|
|
) = list(range(4))
|
|
SOURCE_CD, SOURCE_ISO, SOURCE_IMG = list(range(3))
|
|
MAX_LOG_SIZE = 1024 * 1024 * 1
|
|
MAX_LOG_BACKUP = 0
|
|
|
|
# TODO xnox 20121109 should not hard-code timeouts, instead should
|
|
# do async dbus calls with a qt or glib main loop running.
|
|
MAX_DBUS_TIMEOUT = 2147483
|
|
|
|
if sys.version >= '3':
|
|
text_type = str
|
|
|
|
def callable(obj):
|
|
import collections
|
|
return isinstance(obj, collections.abc.Callable)
|
|
else:
|
|
text_type = unicode
|
|
|
|
callable = callable
|
|
|
|
def setup_gettext(localedir='/usr/share/locale'):
|
|
kwargs = {}
|
|
if sys.version < '3':
|
|
kwargs['unicode'] = True
|
|
gettext.install('usbcreator', localedir=localedir, **kwargs)
|
|
|
|
def setup_logging():
|
|
log = logging.getLogger('')
|
|
# usb-creator used to write ~/.usb-creator.log as root (whoops!), so lets
|
|
# use a different name here. -- ev
|
|
# new location so let's go back to original name =) -- xnox
|
|
cache_dir = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
|
|
log_file = os.path.join(cache_dir, 'usb-creator.log')
|
|
handler = None
|
|
try:
|
|
handler = logging.handlers.RotatingFileHandler(log_file,
|
|
maxBytes=MAX_LOG_SIZE, backupCount=MAX_LOG_BACKUP)
|
|
except IOError:
|
|
logging.exception('Could not set up file logging:')
|
|
if handler:
|
|
formatter = logging.Formatter('usb-creator %(asctime)s (%(levelname)s)'
|
|
' %(filename)s:%(lineno)d: %(message)s')
|
|
handler.setFormatter(formatter)
|
|
handler.setLevel(logging.DEBUG)
|
|
log.addHandler(handler)
|
|
log.setLevel(logging.DEBUG)
|
|
|
|
def format_size(size):
|
|
"""Format a partition size."""
|
|
# Taken from ubiquity's ubiquity/misc.py
|
|
# TODO evand 2009-07-28: Localized size formatting.
|
|
if size < 1024:
|
|
unit = 'B'
|
|
factor = 1
|
|
elif size < 1024 * 1024:
|
|
unit = 'kB'
|
|
factor = 1024
|
|
elif size < 1024 * 1024 * 1024:
|
|
unit = 'MB'
|
|
factor = 1024 * 1024
|
|
elif size < 1024 * 1024 * 1024 * 1024:
|
|
unit = 'GB'
|
|
factor = 1024 * 1024 * 1024
|
|
else:
|
|
unit = 'TB'
|
|
factor = 1024 * 1024 * 1024 * 1024
|
|
return '%.1f %s' % (float(size) / factor, unit)
|
|
|
|
def format_mb_size(size):
|
|
if size < 1024:
|
|
unit = 'MB'
|
|
factor = 1
|
|
elif size < 1024 * 1024:
|
|
unit = 'GB'
|
|
factor = 1024
|
|
elif size < 1024 * 1024 * 1024:
|
|
unit = 'TB'
|
|
factor = 1024 * 1024
|
|
return '%.1f %s' % (float(size) / factor, unit)
|
|
|
|
class USBCreatorProcessException(Exception):
|
|
pass
|
|
|
|
def popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
stdin=subprocess.PIPE):
|
|
logging.debug(str(cmd))
|
|
startupinfo = None
|
|
process = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, stdin=stdin,
|
|
universal_newlines=True,
|
|
startupinfo=startupinfo)
|
|
out, err = process.communicate()
|
|
if process.returncode is None:
|
|
process.wait()
|
|
elif process.returncode != 0:
|
|
raise USBCreatorProcessException(err)
|
|
return out
|
|
|
|
# Taken from ubiquity.
|
|
def find_on_path(command):
|
|
"""Is command on the executable search path?"""
|
|
if 'PATH' not in os.environ:
|
|
return False
|
|
path = os.environ['PATH']
|
|
for element in path.split(os.pathsep):
|
|
if not element:
|
|
continue
|
|
filename = os.path.join(element, command)
|
|
if os.path.isfile(filename) and os.access(filename, os.X_OK):
|
|
return True
|
|
return False
|
|
|
|
def prepend_path(directory):
|
|
if 'PATH' in os.environ and os.environ['PATH'] != '':
|
|
os.environ['PATH'] = '%s:%s' % (directory, os.environ['PATH'])
|
|
else:
|
|
os.environ['PATH'] = directory
|
|
|
|
def sane_path():
|
|
elements = os.environ.get('PATH', '').split(os.pathsep)
|
|
for element in ('/bin', '/sbin', '/usr/bin', '/usr/sbin'):
|
|
if element not in elements:
|
|
prepend_path(element)
|