From f6b6d1c0e5db5893d8a346634cd8ace4c221f93a Mon Sep 17 00:00:00 2001 From: mbusb Date: Sun, 5 Feb 2017 15:29:07 +0530 Subject: [PATCH] Update to new release - 8.5.0 --- CHANGELOG | 11 ++ data/version.txt | 2 +- multibootusb.nsi | 4 +- scripts/distro.py | 11 +- scripts/imager.py | 3 +- scripts/install.py | 11 +- scripts/mbusb_gui.py | 1 + scripts/udisks.py | 223 +++++++++++++++++++++++++++++++++++++ scripts/update_cfg_file.py | 37 +++++- scripts/usb.py | 12 +- 10 files changed, 299 insertions(+), 16 deletions(-) create mode 100644 scripts/udisks.py diff --git a/CHANGELOG b/CHANGELOG index a5e508e..258e8c6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,14 @@ +Version - 8.5.0 +--------------- +* Added Solus OS +* Added Ka OS +* Added PC Unlocker +* Fixed bug - Same drives appearing multiple times under imager tab +* Fixed HBCD boot issue +* Fix crash when using ISO Imager option to write ISO files (fix by bagage) +* Small improvement in detecting USB disks under Linux (by gktrk) +* Auto mount USB drives if not mounted under Linux + Version - 8.4.0 --------------- * Bug fix in selection of persistence size diff --git a/data/version.txt b/data/version.txt index a2f28f4..6d28907 100644 --- a/data/version.txt +++ b/data/version.txt @@ -1 +1 @@ -8.4.0 +8.5.0 diff --git a/multibootusb.nsi b/multibootusb.nsi index 95c9c21..949928a 100644 --- a/multibootusb.nsi +++ b/multibootusb.nsi @@ -1,8 +1,8 @@ ;-------------------------------- ;NSIS script for creating multibootusb setup file -Name "multibootusb 8.4.0" -OutFile "multibootusb-8.4.0-setup.exe" +Name "multibootusb 8.5.0" +OutFile "multibootusb-8.5.0-setup.exe" SetCompressor lzma diff --git a/scripts/distro.py b/scripts/distro.py index d262e6e..0c788ec 100644 --- a/scripts/distro.py +++ b/scripts/distro.py @@ -72,8 +72,7 @@ def distro(iso_cfg_ext_dir, iso_link): return "redhat" # elif re.search(r'suse', string, re.I): # return "suse" - elif re.search(r'opensuse', string, - re.I): + elif re.search(r'opensuse', string, re.I): return "opensuse" elif re.search( r'slitaz|dban |ophcrack|tinycore|rescue.cpi|xpud|untangle|4mlinux|partition wizard|android-x86.png|' @@ -127,6 +126,9 @@ def distro(iso_cfg_ext_dir, iso_link): return "ReactOS" elif re.search(r'fsecure', string, re.I): return "fsecure" + elif re.search(r'default rwp', string, re.I): + return "pc-unlocker" + distro = detect_iso_from_file_list(iso_link) if distro: @@ -162,12 +164,13 @@ def detect_iso_from_file_list(iso_link): return "mentest" elif any("menu.lst" in s.lower() for s in iso_file_list): return "grub4dos" + elif any("bootwiz.cfg" in s.lower() for s in iso_file_list) and any("bootmenu_logo.png" in s.lower() for s in iso_file_list): + return "grub4dos_iso" else: log(iso_file_list) if __name__ == '__main__': iso_cfg_ext_dir = os.path.join(multibootusb_host_dir(), "iso_cfg_ext_dir") - #iso_link = '../../../DISTROS/2016/debian-live-8.3.0-amd64-lxde-desktop.iso' - iso_link = '/media/sundar/Data/DISTROS/ubuntu_14_04_backup/Downloads/clonezilla-live-2.4.2-32-amd64.iso' + iso_link = 'Downloads/clonezilla-live-2.4.2-32-amd64.iso' iso_extract_file(iso_link, iso_cfg_ext_dir, 'cfg') log(distro(iso_cfg_ext_dir)) diff --git a/scripts/imager.py b/scripts/imager.py index 0203805..0d3e006 100644 --- a/scripts/imager.py +++ b/scripts/imager.py @@ -65,7 +65,7 @@ def dd_win(): in_file_size = float(os.path.getsize(config.imager_iso_link) / 1024 / 1024) output = "of=\\\.\\" + config.imager_usb_disk command = [windd, input, output, "bs=1M", "--progress"] - log("Executing ==> " + command) + log("Executing ==> " + " ".join(command)) dd_process = subprocess.Popen(command, universal_newlines=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False) while dd_process.poll() is None: @@ -224,4 +224,3 @@ class Imager(QtWidgets.QDialog, Ui_Dialog): else: usb_size = self.usb.disk_usage(self.usb.get_usb(usb_disk).mount).total return usb_size - diff --git a/scripts/install.py b/scripts/install.py index eea1dc2..7c34d8b 100644 --- a/scripts/install.py +++ b/scripts/install.py @@ -52,7 +52,7 @@ def install_distro(): elif platform.system() == "Linux": log("Copying " + config.iso_link + " to " + usb_mount) shutil.copy(config.iso_link, usb_mount) - elif config.distro == "Windows" or config.distro == "alpine": + elif config.distro == "Windows" or config.distro == "alpine" or config.distro == 'pc-unlocker': log("Extracting iso to " + usb_mount) iso_extract_full(config.iso_link, usb_mount) elif config.distro == "trinity-rescue": @@ -91,6 +91,8 @@ def install_distro(): iso_extract_full(config.iso_link, usb_mount) elif config.distro == 'ReactOS': iso_extract_full(config.iso_link, usb_mount) + elif config.distro == 'grub4dos_iso': + copy_iso(config.iso_link, install_dir) else: iso.iso_extract_full(config.iso_link, install_dir) @@ -107,6 +109,13 @@ def install_distro(): def copy_iso(src, dst): + """ + A simple wrapper for copying larger files. This is necessary as + shutil copy files is much slower under Windows platform + :param src: Path to source file + :param dst: Destination directory + :return: + """ if platform.system() == "Windows": subprocess.call("xcopy " + src + " " + dst, shell=True) elif platform.system() == "Linux": diff --git a/scripts/mbusb_gui.py b/scripts/mbusb_gui.py index 9f47d73..2b9db7d 100644 --- a/scripts/mbusb_gui.py +++ b/scripts/mbusb_gui.py @@ -94,6 +94,7 @@ class AppGui(qemu.Qemu, Imager, QtWidgets.QDialog, Ui_Dialog): :return: """ self.ui.comboBox.clear() + self.ui.comboBox_2.clear() if self.ui.checkBox_all_drives.isChecked(): detected_device = usb.list(partition=1, fixed=True) else: diff --git a/scripts/udisks.py b/scripts/udisks.py new file mode 100644 index 0000000..659b62d --- /dev/null +++ b/scripts/udisks.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python3 +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +# Name: udisks.py +# Purpose: Module to mount unmount and eject using dbus and udisk +# Authors: Original author is Kovid Goyal and python3 +# supporte by Sundar for multibootusb project +# Licence: 'GPL v3' as per original Licence + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +# from __future__ import print_function +import os, re + + +def node_mountpoint(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 + + +class NoUDisks1(Exception): + pass + + +class UDisks(object): + + def __init__(self): + import dbus + self.bus = dbus.SystemBus() + try: + self.main = dbus.Interface(self.bus.get_object('org.freedesktop.UDisks', + '/org/freedesktop/UDisks'), 'org.freedesktop.UDisks') + except dbus.exceptions.DBusException as e: + if getattr(e, '_dbus_error_name', None) == 'org.freedesktop.DBus.Error.ServiceUnknown': + raise NoUDisks1() + raise + + def device(self, device_node_path): + import dbus + devpath = self.main.FindDeviceByDeviceFile(device_node_path) + return dbus.Interface(self.bus.get_object('org.freedesktop.UDisks', + devpath), 'org.freedesktop.UDisks.Device') + + def mount(self, device_node_path): + d = self.device(device_node_path) + try: + return str(d.FilesystemMount('', + ['auth_no_user_interaction', 'rw', 'noexec', 'nosuid', + 'nodev', 'uid=%d'%os.geteuid(), 'gid=%d'%os.getegid()])) + except: + # May be already mounted, check + mp = node_mountpoint(str(device_node_path)) + if mp is None: + raise + return mp + + def unmount(self, device_node_path): + d = self.device(device_node_path) + d.FilesystemUnmount(['force']) + + def eject(self, device_node_path): + parent = device_node_path + while parent[-1] in '0123456789': + parent = parent[:-1] + d = self.device(parent) + d.DriveEject([]) + + +class NoUDisks2(Exception): + pass + + +class UDisks2(object): + + BLOCK = 'org.freedesktop.UDisks2.Block' + FILESYSTEM = 'org.freedesktop.UDisks2.Filesystem' + DRIVE = 'org.freedesktop.UDisks2.Drive' + + def __init__(self): + import dbus + self.bus = dbus.SystemBus() + try: + self.bus.get_object('org.freedesktop.UDisks2', + '/org/freedesktop/UDisks2') + except dbus.exceptions.DBusException as e: + if getattr(e, '_dbus_error_name', None) == 'org.freedesktop.DBus.Error.ServiceUnknown': + raise NoUDisks2() + raise + + def device(self, device_node_path): + device_node_path = os.path.realpath(device_node_path) + devname = device_node_path.split('/')[-1] + + # First we try a direct object path + bd = self.bus.get_object('org.freedesktop.UDisks2', + '/org/freedesktop/UDisks2/block_devices/%s'%devname) + try: + device = bd.Get(self.BLOCK, 'Device', + dbus_interface='org.freedesktop.DBus.Properties') + device = bytearray(device).replace(b'\x00', b'').decode('utf-8') + except: + device = None + + if device == device_node_path: + return bd + + # Enumerate all devices known to UDisks + 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('')(xml)): + bd = self.bus.get_object('org.freedesktop.UDisks2', + '/org/freedesktop/UDisks2/block_devices/%s2'%dev.group(1)) + try: + device = bd.Get(self.BLOCK, 'Device', + dbus_interface='org.freedesktop.DBus.Properties') + device = bytearray(device).replace(b'\x00', b'').decode('utf-8') + except: + device = None + if device == device_node_path: + return bd + + raise ValueError('%r not known to UDisks2'%device_node_path) + + def mount(self, device_node_path): + d = self.device(device_node_path) + mount_options = ['rw', 'noexec', 'nosuid', + 'nodev', 'uid=%d'%os.geteuid(), 'gid=%d'%os.getegid()] + try: + return str(d.Mount( + { + 'auth.no_user_interaction':True, + 'options':','.join(mount_options) + }, + dbus_interface=self.FILESYSTEM)) + except: + # May be already mounted, check + mp = node_mountpoint(str(device_node_path)) + if mp is None: + raise + return mp + + 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) + + 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) + + 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) + + +def get_udisks(ver=None): + if ver is None: + try: + u = UDisks2() + except NoUDisks2: + u = UDisks() + return u + return UDisks2() if ver == 2 else UDisks() + + +def get_udisks1(): + u = None + try: + u = UDisks() + except NoUDisks1: + try: + u = UDisks2() + except NoUDisks2: + pass + if u is None: + raise EnvironmentError('UDisks not available on your system') + return u + + +def mount(node_path): + u = get_udisks1() + u.mount(node_path) + + +def eject(node_path): + u = get_udisks1() + u.eject(node_path) + + +def umount(node_path): + u = get_udisks1() + u.unmount(node_path) + + +def test_udisks(ver=None): + import sys + dev = sys.argv[1] + print('Testing with node', dev) + u = get_udisks(ver=ver) + print('Using Udisks:', u.__class__.__name__) + print('Mounted at:', u.mount(dev)) + print('Unmounting') + u.unmount(dev) + print('Mounting') + u.mount(dev) + print('Ejecting:') + u.eject(dev) + +if __name__ == '__main__': + print('Run test here...') + # test_udisks() diff --git a/scripts/update_cfg_file.py b/scripts/update_cfg_file.py index 04c4864..652efc6 100644 --- a/scripts/update_cfg_file.py +++ b/scripts/update_cfg_file.py @@ -233,7 +233,12 @@ def update_mbusb_cfg_file(iso_link, usb_uuid, usb_mount, distro): string = re.sub(r'/HBCD', '/multibootusb/' + iso_basename(iso_link) + '/HBCD', _config_file) config_file.write(string) config_file.close() - + with open(sys_cfg_file, "a") as f: + f.write("#start " + iso_basename(config.iso_link) + "\n") + f.write("LABEL " + iso_basename(config.iso_link) + "\n") + f.write("MENU LABEL " + iso_basename(config.iso_link) + "\n") + f.write("BOOT " + '/multibootusb/' + iso_basename(iso_link) + '/' + isolinux_bin_dir(iso_link).replace("\\", "/") + '/' + distro + '.bs' + "\n") + f.write("#end " + iso_basename(config.iso_link) + "\n") elif distro == "Windows": if os.path.exists(sys_cfg_file): config_file = open(sys_cfg_file, "a") @@ -264,6 +269,8 @@ def update_mbusb_cfg_file(iso_link, usb_uuid, usb_mount, distro): config_file.close() elif distro == 'grub4dos': update_menu_lst() + elif distro == 'grub4dos_iso': + update_grub4dos_iso_menu() else: # admin.adminCmd(["mount", "-o", "remount,rw", config.usb_disk]) config_file = open(sys_cfg_file, "a") @@ -290,8 +297,11 @@ def update_mbusb_cfg_file(iso_link, usb_uuid, usb_mount, distro): config_file.write("INITRD " + "/multibootusb/" + iso_basename(iso_link) + '/' + iso_name(iso_link) + '\n') config_file.write("APPEND iso\n") elif distro == 'ReactOS': - config_file.write("COM32 mboot.c32") - config_file.write("APPEND /loader/setupldr.sys") + config_file.write("COM32 mboot.c32" + '\n') + config_file.write("APPEND /loader/setupldr.sys" + '\n') + elif distro == 'pc-unlocker': + config_file.write("kernel ../ldntldr" + '\n') + config_file.write("append initrd=../ntldr" + '\n') else: if isolinux_bin_exist(config.iso_link) is True: if distro == "generic": @@ -350,3 +360,24 @@ def update_menu_lst(): f.write("KERNEL grub.exe" + "\n") f.write('APPEND --config-file=/' + menu_lst + "\n") f.write("#end " + iso_basename(config.iso_link) + "\n") + +def update_grub4dos_iso_menu(): + sys_cfg_file = os.path.join(config.usb_mount, "multibootusb", "syslinux.cfg") + install_dir = os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link)) + menu_lst_file = os.path.join(install_dir, 'menu.lst') + with open(menu_lst_file, "w") as f: + f.write("title Boot " + iso_name(config.iso_link) + "\n") + f.write("find --set-root --ignore-floppies --ignore-cd /multibootusb/" + iso_basename(config.iso_link) + '/' + + iso_name(config.iso_link) + "\n") + f.write("map --heads=0 --sectors-per-track=0 /multibootusb/" + iso_basename(config.iso_link) + + '/' + iso_name(config.iso_link) + ' (hd32)' + "\n") + f.write("map --hook" + "\n") + f.write("chainloader (hd32)") + + with open(sys_cfg_file, "a") as f: + f.write("#start " + iso_basename(config.iso_link) + "\n") + f.write("LABEL " + iso_basename(config.iso_link) + "\n") + f.write("MENU LABEL " + iso_basename(config.iso_link) + "\n") + f.write("KERNEL grub.exe" + "\n") + f.write('APPEND --config-file=/multibootusb/' + iso_basename(config.iso_link) + '/' + iso_name(config.iso_link) + "\n") + f.write("#end " + iso_basename(config.iso_link) + "\n") diff --git a/scripts/usb.py b/scripts/usb.py index 35fbb02..9c27c8b 100644 --- a/scripts/usb.py +++ b/scripts/usb.py @@ -14,6 +14,9 @@ import collections import ctypes import subprocess from . import gen +if platform.system() == 'Linux': + from . import udisks + u = udisks.get_udisks(ver=None) if platform.system() == 'Windows': import psutil import win32com.client @@ -213,8 +216,8 @@ def details_udev(usb_disk_part): label = str(device['ID_FS_LABEL']) except: label = "No_Label" - mount_point = os.popen('findmnt -nr -o target -S %s' - % usb_disk_part).read().strip() + mount_point = u.mount(usb_disk_part) + # mount_point = os.popen('findmnt -nr -o target -S %s' % usb_disk_part).read().strip() # Convert the hex string of space to empty space. mount_point = mount_point.replace('\\x20', ' ') try: @@ -259,7 +262,10 @@ def details_udisks2(usb_disk_part): # mount_point = str(bytearray(mount_point[0]).decode('utf-8').replace(b'\x00', b'')) mount_point = bytearray(mount_point[0]).replace(b'\x00', b'').decode('utf-8') else: - mount_point = "No_Mount" + try: + mount_point = u.mount(usb_disk_part) + except: + mount_point = "No_Mount" try: label = bd.Get('org.freedesktop.UDisks2.Block', 'IdLabel', dbus_interface='org.freedesktop.DBus.Properties') except: