Created
August 21, 2020 20:14
-
-
Save ids1024/facefabfb5b6c2987c6c83660c662447 to your computer and use it in GitHub Desktop.
Create Windows Bootable USB from ISO using UDisks Dbus API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dbus | |
import shutil | |
import sys | |
# TODO: Timeouts | |
# {'options': 'sync'} | |
bus = dbus.SystemBus() | |
iso = sys.argv[1] | |
drive = sys.argv[2] | |
EMPTY_OPTS = dbus.Dictionary(signature = "sv") | |
# Loopback mount the .iso | |
manager_obj = bus.get_object("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2/Manager") | |
manager = dbus.Interface(manager_obj, "org.freedesktop.UDisks2.Manager") | |
with open(iso, 'rb') as f: | |
path = manager.LoopSetup(f.raw.fileno(), {}) | |
loop_obj = bus.get_object("org.freedesktop.UDisks2", path) | |
loop_filesystem = dbus.Interface(loop_obj, "org.freedesktop.UDisks2.Filesystem") | |
try: | |
loop_filesystem.Mount({}) | |
except dbus.exceptions.DBusException as e: | |
if e.get_dbus_name() != "org.freedesktop.UDisks2.Error.AlreadyMounted": | |
raise e | |
properties = dbus.Interface(loop_obj, 'org.freedesktop.DBus.Properties') | |
mount_points = properties.Get("org.freedesktop.UDisks2.Filesystem", "MountPoints") | |
iso_mount_path = bytes(mount_points[0])[:-1] | |
# Remove loop device when unmounted | |
loop = dbus.Interface(loop_obj, "org.freedesktop.UDisks2.Loop") | |
loop.SetAutoclear(True, {}) | |
# Unmount any partitions | |
udisks_obj = bus.get_object("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2") | |
obj_manager = dbus.Interface(udisks_obj, "org.freedesktop.DBus.ObjectManager") | |
for k in obj_manager.GetManagedObjects(): | |
if k.startswith("/org/freedesktop/UDisks2/block_devices/" + drive) and not k.endswith(drive): | |
obj = bus.get_object("org.freedesktop.UDisks2", k) | |
try: | |
filesystem = dbus.Interface(obj, "org.freedesktop.UDisks2.Filesystem") | |
filesystem.Unmount({"force": True}) | |
except dbus.exceptions.DBusException as e: | |
if e.get_dbus_name() == "org.freedesktop.DBus.Error.UnknownMethod": | |
pass | |
elif e.get_dbus_name() == "org.freedesktop.UDisks2.Error.NotMounted": | |
pass | |
else: | |
raise e | |
# Create dos partition table | |
drive_obj = bus.get_object("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2/block_devices/" + drive) | |
block = dbus.Interface(drive_obj, "org.freedesktop.UDisks2.Block") | |
block.Format("gpt", {}) | |
partition_table = dbus.Interface(drive_obj, "org.freedesktop.UDisks2.PartitionTable") | |
offset = 1024 ** 2 | |
# UEFI system partition | |
partition = partition_table.CreatePartitionAndFormat(offset, 1024 ** 3, "0xef", "", {}, "vfat", {}, timeout=30*60) | |
part_obj = bus.get_object("org.freedesktop.UDisks2", partition) | |
fat_filesystem = dbus.Interface(part_obj, "org.freedesktop.UDisks2.Filesystem") | |
fat_path = fat_filesystem.Mount({}) | |
offset += 1024**3 | |
# Ntfs partition | |
partition = partition_table.CreatePartitionAndFormat(offset, 0, "0xb", "", {}, "ntfs", {}, timeout=30*60) | |
part_obj = bus.get_object("org.freedesktop.UDisks2", partition) | |
ntfs_filesystem = dbus.Interface(part_obj, "org.freedesktop.UDisks2.Filesystem") | |
ntfs_path = ntfs_filesystem.Mount({}) | |
# Copy the files | |
def f(src, files): | |
if src.endswith(b'/sources'): | |
return [i for i in files if i != b'boot.wim'] | |
return [] | |
shutil.copytree(iso_mount_path, fat_path.encode('utf-8'), ignore=f, dirs_exist_ok=True) | |
shutil.copytree(iso_mount_path + b'/sources', (ntfs_path + '/sources').encode('utf-8')) | |
# Unmount filesystems | |
loop_filesystem.Unmount({}) | |
#ntfs_filesystem.Unmount({}, timeout=30*60) | |
#fat_filesystem.Unmount({}, timeout=30*60) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment