示例#1
0
def manage_uefi_files(_os, mount_point):
    """Manage UEFI bootloader files."""
    logger.info("manage_uefi_files(): Copying UEFI Files to uefi_boot_dir...")

    #First, let's check if EFI/boot already exists. This is a fat32/fat16 filesystem,
    #so case doesn't matter.
    if os.path.isdir(mount_point+"/boot/efi/EFI/boot"):
        uefi_boot_dir = mount_point+"/boot/efi/EFI/boot"

    else:
        #It doesn't, so we'll create it.
        uefi_boot_dir = mount_point+"/boot/efi/EFI/boot"
        CoreTools.start_process("mkdir "+uefi_boot_dir, show_output=False, privileged=True)

    #Do this different depending on whether the OS is ubuntu or fedora-based.
    if OS_INFO[_os]["PackageManager"] == "apt-get":
        source_dir = mount_point+"/boot/efi/EFI/ubuntu"

    elif OS_INFO[_os]["PackageManager"] == "dnf":
        source_dir = mount_point+"/boot/efi/EFI/fedora"

    if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI":
        #We need to copy grubx64.efi to uefi_boot_dir.
        logger.info("manage_uefi_files(): Copying grubx64.efi to "+uefi_boot_dir+"...")

        if CoreTools.start_process("cp -v "+source_dir+"/grubx64.efi "+uefi_boot_dir+"/bootx64.efi",
                                   show_output=False, privileged=True) != 0:
            logger.error("manage_uefi_files(): Failed to copy "+source_dir+"/grub*.efi to "
                         + uefi_boot_dir+"/bootx64.efi! Attempting to continue anyway...")

    logger.info("manage_uefi_files(): Done!")
示例#2
0
 def test_start_process(self):
     for command in self.commands:
         retval, output = CoreTools.start_process(command,
                                                  return_output=True,
                                                  testing=True)
         self.assertEqual(retval, self.commands[command]["Retval"])
         self.assertEqual(output, self.commands[command]["Output"])
示例#3
0
def check_depends():
    """
    Check dependencies, and show an error message and kill the app if the dependencies are not met.
    """

    logger.info("MainStartupTools(): check_depends(): Checking dependencies...")
    #Create a temporary list to allow WxFixBoot to notify the user of particular unmet
    #dependencies. TODO This will need to be updated at each release time.
    cmd_list = ("mkdir", "notify-send", "pkexec", "cp", "mv", "which", "uname", "fsck", "ls",
                "modprobe", "mount", "umount", "rm", "ping", "badblocks", "arch", "file",
                "sh", "echo", "dmidecode", "chroot", "strings", "dd", "dmsetup")

    #Create a list to contain names of failed commands.
    failed_list = []

    for cmd in cmd_list:
        #Run the command with its argument and log the output (if in debug mode)
        retval, output = CoreTools.start_process("which "+cmd, return_output=True)

        if retval != 0:
            logger.error("check_depends(): Dependency problems! Command: "+cmd
                         + " failed to execute or wasn't found.")

            logger.error("check_depends(): The error was: "+output)
            failed_list.append(cmd)

    #Check if any commands failed.
    if failed_list != []:
        #Missing dependencies!
        logger.critical("check_depends(): Dependencies missing! WxFixBoot will exit. The missing "
                        + "dependencies are: "+', '.join(failed_list)+". Exiting.")

        CoreTools.emergency_exit("The following dependencies could not be found on your system: "
                                 + ', '.join(failed_list)+".\n\nPlease install the missing "
                                 + "dependencies.")

    #Check that the getdevinfo version is 1.0.10 or greater.
    version_okay = False

    #TODO May need to change before each release.
    versions = ["1.1.1", getdevinfo.getdevinfo.VERSION]

    #Last entry is highest version.
    versions = sorted(versions, key=LooseVersion)

    if versions[-1] == versions[-2]:
        #This is the latest version WxFixBoot is aware of at the time of writing.
        version_okay = True

    elif versions[-1] != "1.1.1" and versions[-1] == getdevinfo.getdevinfo.VERSION:
        #This is newer than the latest version WxFixBoot is aware of at the time of writing.
        version_okay = True

    if not version_okay:
        logger.critical("check_depends(): Your getdevinfo module is known to not work with this "
                        + "version of WxFixBoot. Please update to at least 1.1.1")

        CoreTools.emergency_exit("Your getdevinfo module is known to not work "
                                 + "with this version of WxFixBoot. Please update to at least "
                                 + "v1.1.1.")
示例#4
0
def find_missing_fsck_modules():
    """Check for and return all missing fsck modules (fsck.vfat, fsck.minix, etc)."""
    logger.info("find_missing_fsck_modules(): Looking for missing FSCK modules to ignore...")
    failed_list = []

    keys = list(DISK_INFO.keys())
    keys.sort()

    for disk in keys:
        #Check the FSType is known and isn't swap.
        if DISK_INFO[disk]["FileSystem"] not in ("Unknown", "N/A"):
            #Check if this module is present.
            if CoreTools.start_process("which fsck."+DISK_INFO[disk]["FileSystem"],
                                       show_output=False) != 0:
                #Couldn't find it, add it to the failed list.
                logger.warning("FSCKModules(): Couldn't find FSCK module fsck."
                               + DISK_INFO[disk]["FileSystem"]
                               + "! Adding it to the list of missing modules...")

                failed_list.append("fsck."+DISK_INFO[disk]["FileSystem"])

            else:
                logger.debug("FSCKModules(): Found fsck."+DISK_INFO[disk]["FileSystem"]+"...")

    #Return the list, so FSCheck functions know which FSes to ignore.
    logger.info("find_missing_fsck_modules(): Done! Missing FSCK modules: "+', '.join(failed_list))
    return failed_list
def check_depends():
    """
    Check dependencies, and show an error message and kill the app if the dependencies are not met.
    """

    #Create a temporary list to allow WxFixBoot to notify the user of particular unmet
    #dependencies.
    cmd_list = ("cp", "mv", "which", "uname", "fsck", "ls", "modprobe", "mount", "umount",
                "rm", "ping", "badblocks", "arch", "file", "sh", "echo", "lshw",
                "lvdisplay", "dmidecode", "chroot", "strings", "dd", "blkid")

    #Create a list to contain names of failed commands.
    failed_list = []

    for command in cmd_list:
        #Run the command with its argument and log the output (if in debug mode)
        retval = CoreTools.start_process("which "+command, return_output=True)[0]

        if retval != 0:
            failed_list.append(command)

    #Check if any commands failed.
    if failed_list != []:
        #Missing dependencies!
        emergency_exit("The following dependencies could not be found on your system: "
                       + ', '.join(failed_list)+".\n\nPlease install the missing dependencies.")
示例#6
0
def check_filesystems():
    """Check all unmounted filesystems."""
    logger.info("check_filesystems(): Checking filesystems if possible. Running 'fsck -ARMp'...")

    if CoreTools.start_process("fsck -ARMp", privileged=True) not in (0, 8):
        logger.critical("check_filesystems(): Failed to check filesystems! Doing emergency "
                        + "exit...")

        CoreTools.emergency_exit("Failed to check filesystems! Please fix your filesystems "
                                 + "and then run WxFixBoot again.")
示例#7
0
def get_firmware_type():
    """Get the firmware type"""
    #Check if the firmware type is UEFI.
    #Also, look for UEFI variables.
    #Make sure efivars module is loaded. If it doesn't exist, continue anyway.
    CoreTools.start_process("modprobe efivars", privileged=True)

    #Look for the UEFI vars in some common directories.
    if os.path.isdir("/sys/firmware/efi/vars") \
        and CoreTools.start_process("ls /sys/firmware/efi/vars", return_output=True)[1] != "":

        uefi_variables = True
        logger.info("get_firmware_type(): Found UEFI Variables at /sys/firmware/efi/vars...")

    elif os.path.isdir("/proc/efi/vars") \
        and CoreTools.start_process("ls /proc/efi/vars", return_output=True)[1] != "":

        uefi_variables = True
        logger.info("get_firmware_type(): Found UEFI Variables at /proc/efi/vars...")

    elif os.path.isdir("/sys/firmware/efi/efivars") \
        and CoreTools.start_process("ls /sys/firmware/efi/efivars", return_output=True)[1] != "":

        uefi_variables = True
        logger.info("get_firmware_type(): Found UEFI Variables at /sys/firmware/efi/efivars...")

    else:
        logger.info("get_firmware_type(): UEFI vars not found in /sys/firmware/efi/vars, "
                    + "/sys/firmware/efi/efivars, or /proc/efi/vars. This is normal if running "
                    + "on a BIOS system. Determining firmware type a different way...")

        uefi_variables = False

    if uefi_variables:
        #It's UEFI.
        logger.info("get_firmware_type(): Detected Firmware Type as UEFI.")
        SYSTEM_INFO["FirmwareType"] = "UEFI"

    else:
        #Look a second way.
        output = CoreTools.start_process("dmidecode -q -t BIOS", return_output=True,
                                         privileged=True)[1]

        if "UEFI" not in output:
            #It's BIOS.
            logger.info("get_firmware_type(): Detected Firmware Type as BIOS...")
            SYSTEM_INFO["FirmwareType"] = "BIOS"

        else:
            #It's UEFI.
            logger.warning("get_firmware_type(): Detected Firmware Type as UEFI, but couldn't "
                           + "find UEFI variables!")

            SYSTEM_INFO["FirmwareType"] = "UEFI"
            DialogTools.show_msg_dlg(kind="warning", message="Your computer uses UEFI firmware, "
                                     + "but the UEFI variables couldn't be mounted or weren't "
                                     + "found. Please ensure you've booted in UEFI mode rather "
                                     + "than legacy mode to enable access to the UEFI variables. "
                                     + "You can attempt installing a UEFI bootloader without "
                                     + "them, but it might not work, and it isn't recommended.")
示例#8
0
def wait_until_packagemanager_free(mount_point, package_manager):
    """
    Check if the package manager is in use, and if so, wait until it is no longer in use.
    """

    if package_manager == "apt-get":
        cmd = "apt-get check"
        success_retvals = (0, 0) #100 omitted - indicates apt is in use.

    elif package_manager == "dnf":
        cmd = "dnf -C check-update"
        success_retvals = (0, 100) #100 - updates available.

    if mount_point != "":
        cmd = "chroot "+mount_point+" "+cmd

    retval = 1

    #Trap in while loop until package manager is free.
    #FIXME: Doesn't work with DNF, but doesn't strictly matter because it will just wait
    #FIXME: Handle return code 100 when updates are available.
    #until the lock is free, rather than exiting.
    while retval not in success_retvals:
        retval = CoreTools.start_process(cmd, show_output=False, privileged=True)

        #Get the package cache if there is none. 200 - locking failure.
        if package_manager == "dnf" and retval not in (0, 200):
            CoreTools.start_process("sh -c 'echo No cache available, "
                                    + "downloading package information...'")

            if mount_point != "":
                cmd2 = "chroot "+mount_point+" dnf check-update"

            else:
                cmd2 = "dnf check-update"

            CoreTools.start_process(cmd2, show_output=False, privileged=True)

        time.sleep(5)
示例#9
0
def backup_uefi_files(mount_point):
    """Backup some .efi files, just in case something goes wrong."""
    #TODO: Make this smarter when we detect Windows.
    logger.info("backup_uefi_files(): Backing up UEFI Files...")

    #We'll backup /EFI/boot/bootx64.efi if it exists, and we'll also backup Windows's uefi files,
    #if they exist. First do /EFI/boot/bootx64.efi. Fortunately, the UEFI partition is always a
    #fat32/fat16 filesystem, so case doesn't matter.
    logger.info("backup_uefi_files(): Backing up "+mount_point+"/boot/efi/boot/boot*.efi...")

    if os.path.isfile(mount_point+"/boot/efi/EFI/boot/boot*.efi"):
        if CoreTools.start_process("cp -v "+mount_point+"/boot/efi/EFI/boot/boot*.efi "
                                   + mount_point+"/boot/efi/EFI/boot/bkpbootx64.efi",
                                   show_output=False, privileged=True) != 0:
            #Log and warn user if this went wrong.
            logger.error("backup_uefi_files(): Failed to backup failsafe UEFI boot file! "
                         + "Warning user and continuing...")

            DialogTools.show_msg_dlg(kind="warning", message="WxFixBoot failed to save "
                                     + "your UEFI boot files to the backup directory! Click okay to continue.")

    #Now do Windows's files, if they exist.
    logger.info("backup_uefi_files(): Backing up Windows's boot files if they exist...")

    if os.path.isfile(mount_point+"/boot/efi/EFI/Microsoft/boot/bootmgfw.efi"):
        if CoreTools.start_process("cp -v "+mount_point+"/boot/efi/EFI/Microsoft/boot/bootmgfw.efi "
                                   + mount_point+"/boot/efi/EFI/Microsoft/boot/bkpbootmgfw.efi",
                                   show_output=False, privileged=True) != 0:
            #Log and warn user if this went wrong.
            logger.error("backup_uefi_files(): Failed to backup Windows's UEFI boot files! "
                         + "Warning user and continuing...")

            DialogTools.show_msg_dlg(kind="warning", message="WxFixBoot failed to "
                                     + "backup Windows's UEFI boot files! Click okay to continue.")

    logger.info("backup_uefi_files(): Done!")
示例#10
0
def mount_core_filesystems():
    """
    Mount all core filsystems defined in the /etc/fstab of the current operating system.
    """

    logger.info("mount_core_filesystems(): Mounting core filesystems in /etc/fstab. Calling "
                + "'mount -avw'...")

    #Don't worry about this error when running on Parted Magic.
    if CoreTools.start_process("mount -avw", privileged=True) != 0 \
        and SYSTEM_INFO["OnPartedMagic"] is False:

        logger.critical("mount_core_filesystems(): Failed to re-mount your filesystems after "
                        + "checking them! Doing emergency exit...")

        CoreTools.emergency_exit("Failed to re-mount your filesystems after checking them!")
示例#11
0
def install_grub2_to_mbr(package_manager, use_chroot, mount_point, device):
    """Install GRUB2 (BIOS version) into the MBR of the hard drive"""
    #Okay, we've modified the kernel options and the timeout. Now we need to install grub to find
    #the MBR. Use --force to make sure grub installs it even on a GPT disk with no bios boot
    #partition. Can flag as a warning on Fedora systems when just updating, but ignore it.
    if package_manager == "apt-get":
        cmd = "grub-install --force "+device

    elif package_manager == "dnf":
        cmd = "grub2-install --force --target=i386-pc "+device

    if use_chroot:
        cmd = "chroot "+mount_point+" "+cmd

    retval = CoreTools.start_process(cmd, show_output=False, privileged=True)

    #Return the return value.
    return retval
示例#12
0
def determine_os_architecture(mount_point):
    """Look for OS architecture on given partition."""
    if mount_point != "":
        logger.info("determine_os_architecture(): Trying to find OS arch for OS at "
                    + mount_point+"...")

    else:
        logger.info("determine_os_architecture(): Trying to find OS arch for Current OS...")

    #Do setup.
    os_architecture = None
    cmd = "arch"

    while True:
        if mount_point != "":
            cmd = "chroot "+mount_point+" "+cmd

        retval, os_architecture = CoreTools.start_process(cmd, return_output=True, privileged=True)

        #If the command failed, try a second approach.
        if retval != 0 and "arch" in cmd:
            cmd = "file /sbin/init"

        elif retval != 0:
            os_architecture = None
            break

        else:
            break

    #If the command that worked was 'arch', or both failed, we can just return it.
    if "arch" in cmd or retval != 0:
        #Return the arch (or None, if we didn't find it).
        return os_architecture

    else:
        if "32-bit" in os_architecture:
            os_architecture = "i386"

        else:
            os_architecture = "x86_64"

        return os_architecture
示例#13
0
def get_os_name_with_lsb(partition, mount_point, is_current_os):
    """Attempt to get an OS's name using lsb_release -sd as a fallback."""
    logger.info("get_os_name_with_lsb(): Attempting to get OS name for OS on "+partition+"...")

    if is_current_os:
        logger.info("get_os_name_with_lsb(): OS is the currently running OS...")
        cmd = "lsb_release -sd"

    else:
        logger.info("get_os_name_with_lsb(): OS isn't the currently running OS...")
        cmd = "chroot "+mount_point+" lsb_release -sd"

    retval, output = CoreTools.start_process(cmd, show_output=False,
                                             return_output=True, privileged=True)

    if retval != 0 or output == "":
        logger.error("get_os_name_with_lsb(): Couldn't get OS name! Returning None...")
        return None

    #otherwise...
    logger.info("get_os_name_with_lsb(): Success. OS name is "+output+". Returning it...")
    return output
示例#14
0
def update_grub2(_os, package_manager, use_chroot, mount_point):
    """
    Run 'update-grub' to update GRUB2's (BIOS and EFI/UEFI) configuration
    and bootloader menu
    """

    #We need to update grub.
    if package_manager == "apt-get":
        cmd = "update-grub2"

    elif package_manager == "dnf" and BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB2":
        cmd = "grub2-mkconfig -o /boot/grub2/grub.cfg"

    elif package_manager == "dnf":
        cmd = "grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg"

    if use_chroot:
        cmd = "chroot "+mount_point+" "+cmd

    retval = CoreTools.start_process(cmd, show_output=False, privileged=True)

    #Return the return value.
    return retval
示例#15
0
def install_grub2_to_efi_partition(package_manager, use_chroot, mount_point,
                                   uefi_system_partition_mount_point, arch):

    """Install GRUB2 (EFI/UEFI version) into the EFI/UEFI partition"""
    #Okay, we've modified the kernel options and the timeout. Now we need to install grub
    #to the UEFI partition.
    #NB: May need --force if EFI vars not present on newer GRUB-EFI versions (Ubuntu 18.10+) check!
    #NB: Don't think so - files touched anyway, but good to double check.
    #NB: Keep an eye on this.
    if package_manager == "apt-get":
        cmd = "grub-install --efi-directory="+uefi_system_partition_mount_point \
              + " --target="+arch+"-efi"

    elif package_manager == "dnf":
        #Don't install on fedora, it messes stuff up.
        cmd = "echo 'Disabled on Fedora'"

    if use_chroot:
        cmd = "chroot "+mount_point+" "+cmd

    retval = CoreTools.start_process(cmd, show_output=False, privileged=True)

    #Return the return value.
    return retval
示例#16
0
def determine_package_manager(apt_cmd, dnf_cmd):
    """
    Determine and return the package manager using the given command strings.
    """

    package_manager = "Unknown"

    for cmd in (apt_cmd, dnf_cmd):
        retval = CoreTools.start_process(cmd, show_output=False, privileged=True)

        if retval != 0:
            if cmd == apt_cmd:
                #Couldn't find apt!
                logger.info("MainStartupTools: Main().determine_package_manager(): Didn't find "
                            + "apt. Looking for dnf...")

                continue

            else:
                logger.info("MainStartupTools: Main().determine_package_manager(): Didn't find "
                            + "apt or dnf. Returning 'Unknown'...")

        else:
            if cmd == apt_cmd:
                #Found APT!
                logger.info("MainStartupTools: Main().determine_package_manager(): Found apt...")
                package_manager = "apt-get"
                break

            else:
                #Found DNF!
                logger.info("MainStartupTools: Main().determine_package_manager(): Found dnf...")
                package_manager = "dnf"
                break

    return package_manager
示例#17
0
def check_internet_connection():
    """Check the internet connection."""
    logger.info(
        "check_internet_connection(): Checking the Internet Connection w/ OpenDNS..."
    )

    while True:
        #Test the internet connection by pinging an OpenDNS DNS server.
        packet_loss = "100%"

        logger.debug(
            "check_internet_connection(): Running 'ping -c 5 -i 0.5 208.67.222.222'..."
        )
        retval, output = CoreTools.start_process(
            "ping -c 5 -i 0.5 208.67.222.222",
            show_output=False,
            return_output=True)

        if retval != 0:
            #This errored for some reason. Probably no internet connection.
            logger.error("check_internet_connection(): Command errored!")
            packet_loss = "100%"

        else:
            #Get the % packet loss.
            for line in output.split("\n"):
                if 'packet loss' in line:
                    packet_loss = line.split()[-5]

        if packet_loss == "0%":
            #Good! We have a reliable internet connection.
            logger.info(
                "check_internet_connection(): Internet Connection Test Succeeded!"
            )
            break

        else:
            #Uh oh! We DON'T have a reliable internet connection! Ask the user to either try again,
            #or skip Bootloader operations.
            logger.error(
                "check_internet_connection(): Internet Connection test failed! Asking "
                + "user to try again or disable bootloader operations...")

            result = DialogTools.show_yes_no_dlg(
                message="Your Internet Connection failed the " +
                "test! Without a working internet connection, " +
                "you cannot perform bootloader operations. " +
                "Click yes to try again, and click no to give " +
                "up and skip bootloader operations.",
                title="WxFixBoot - Disable Bootloader " + "Operations?",
                buttons=("Try again", "Cancel Bootloader Operations"))

            if result is False:
                logger.warning(
                    "check_internet_connection(): Disabling bootloader operations "
                    + "due to bad internet connection...")

                SYSTEM_INFO["DisableBootloaderOperations"] = True
                SYSTEM_INFO["DisableBootloaderOperationsBecause"] \
                .append("Internet Connection test failed.")

                break

            else:
                #We'll just run the loop again
                logger.info(
                    "check_internet_connection(): Testing the internet connection "
                    + "again...")
示例#18
0
def remove_old_bootloader(_os):
    """Remove the currently installed bootloader."""
    logger.info("remove_old_bootloader(): Removing " +
                BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 27)
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Removing " + BOOTLOADER_INFO[_os]["Bootloader"] +
                 " from " + _os + "......")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Removing " +
        BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...###\n")

    #If this is the current OS, let the remover function know that we aren't using chroot.
    if OS_INFO[_os]["IsCurrentOS"]:
        logger.debug(
            "remove_old_bootloader(): Modifying current OS so not using chroot..."
        )
        use_chroot, unmount_after, mount_point = (False, False, "")

    else:
        logger.debug(
            "remove_old_bootloader(): Using chroot to modify another OS...")
        use_chroot = True
        mount_point = "/mnt/wxfixboot/mountpoints" + OS_INFO[_os]["Partition"]

        #Check if the partition is mounted.
        unmount_after = not CoreTools.is_mounted(OS_INFO[_os]["Partition"],
                                                 mount_point)

        if unmount_after:
            #Mount the partition using the global mount function.
            if CoreTools.mount_partition(partition=OS_INFO[_os]["Partition"],
                                         mount_point=mount_point) != 0:

                logger.error("remove_old_bootloader(): Failed to mount " +
                             OS_INFO[_os]["Partition"] +
                             "! Warning the user and giving up...")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="WxFixBoot failed to mount the partition " +
                    "containing " + _os +
                    "! Giving up. You will be prompted " +
                    "to try again if you wish.")

                return False

        #Set up chroot.
        if CoreTools.setup_chroot(mount_point) != 0:
            logger.error(
                "remove_old_bootloader(): Failed to set up chroot at " +
                mount_point + "! Giving up...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to set up a chroot for " + _os +
                "! Giving up. You will be prompted to try again if " +
                "you wish.")
            return False

    #Mount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.mount_partition(OS_INFO[_os]["BootPartition"],
                                     mount_point + "/boot") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " + _os +
                         "'s /boot partition! " +
                         "Skipping bootloader removal for this OS.")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to mount the partition containing " +
                _os + "'s /boot partition! Giving up. You will be prompted " +
                "to try again if you wish.")

            if not OS_INFO[_os]["IsCurrentOS"]:
                CoreTools.teardown_chroot(mount_point)
                CoreTools.unmount(mount_point)

            return False

    #Mount the UEFI partition at mount_point/boot/efi, if it exists.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.mount_partition(
                partition=OS_INFO[_os]["EFIPartition"],
                mount_point=mount_point + "/boot/efi") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " +
                         OS_INFO[_os]["EFIPartition"] + "! to " + mount_point +
                         "/boot/efi! Aborting bootloader installation and " +
                         "warning user...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxfixBoot failed to mount the partition containing " +
                _os + "'s EFI partition! Giving up. You will be prompted to " +
                "try again if you wish.")

            return False

    #Wait until no other application is using APT/DNF.
    #Let user know what's happening.
    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 27)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_current_operation_text,
        message="Waiting until " + _os +
        "'s package manager is free.\nClose any open applications if this " +
        "message persists...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box,
        "\n###Waiting until " + _os + "'s package manager is free...###\n")

    logger.debug("remove_old_bootloader(): Waiting until " + _os +
                 "'s package manager is free...")
    HelperBackendTools.wait_until_packagemanager_free(mount_point=mount_point,
                                                      package_manager=\
                                                      OS_INFO[_os]["PackageManager"])

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 27)
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Removing " + BOOTLOADER_INFO[_os]["Bootloader"] +
                 " from " + _os + "...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Removing " +
        BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...###\n")

    #Make sure the GNOME APT frontend dependency is installed.
    if OS_INFO[_os]["PackageManager"] == "apt-get":
        #Ubuntu 16.04.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgnome2-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

        #All newer versions.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgtk3-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

    #Remove the bootloader.
    if BOOTLOADER_INFO[_os]["Bootloader"] == "GRUB2":
        logger.info("remove_old_bootloader(): Removing GRUB2...")

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get purge -y " \
                  "--allow-remove-essential grub-pc grub-pc-bin grub-common'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y remove grub2"

    elif BOOTLOADER_INFO[_os]["Bootloader"] == "GRUB-UEFI":
        logger.info("remove_old_bootloader(): Removing GRUB-UEFI...")

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get purge -y " \
                  "--allow-remove-essential grub-efi grub-efi-amd64 grub-efi-amd64-bin" \
                  " grub-efi-ia32 grub-efi-ia32-bin grub-common grub2-common'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y remove grub2-efi-x64 grub2-efi-ia32 shim-x64"

    else:
        #Bootloader is unknown. Just output a warning message.
        logger.warning(
            "remove_old_bootloader(): Cannot remove unknown bootloader! " +
            "Continuing anyway...")

        cmd = "echo 'WARNING: Bootloader is " \
              "unknown, cannot remove. Continuing anyway...'"

    if use_chroot:
        cmd = "chroot " + mount_point + " " + cmd

    retval = CoreTools.start_process(cmd, privileged=True)

    if retval != 0:
        logger.error("remove_old_bootloader(): Failed to remove " +
                     BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
                     "! Warning user...")

        DialogTools.show_msg_dlg(kind="error",
                                 message="WxFixBoot failed to remove " +
                                 BOOTLOADER_INFO[_os]["Bootloader"] +
                                 " from " + _os + "!")
        return False

    #If there's a seperate EFI partition for this OS, make sure it's unmounted before removing
    #the chroot.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot/efi") != 0:
            logger.error("remove_old_bootloader(): Failed to unmount " +
                         mount_point +
                         "/boot/efi! This probably doesn't matter...")

    #unmount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot") != 0:
            logger.error("remove_old_bootloader(): Failed to unmount " + _os +
                         "'s /boot partition! Continuing anyway...")

    #Tear down chroot if needed.
    if use_chroot:
        if CoreTools.teardown_chroot(mount_point=mount_point) != 0:
            logger.error(
                "remove_old_bootloader(): Failed to remove chroot at " +
                mount_point + "! Attempting to continue anyway...")

    #unmount partition if needed.
    if unmount_after:
        if CoreTools.unmount(mount_point) != 0:
            logger.error("remove_old_bootloader(): Couldn't unmount " +
                         mount_point + "! Continuing anyway...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Finished removing " +
        BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os + "...###\n")

    if retval != 0:
        #Something went wrong! Log it and notify the user.
        logger.error("remove_old_bootloader(): Failed to remove " +
                     BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
                     "! We'll continue anyway. Warn the user.")

        DialogTools.show_msg_dlg(
            kind="error",
            message="WxFixBoot failed to remove " +
            BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
            "! This probably doesn't matter; when we install the new " +
            "bootloader, it should take precedence over the old one " +
            "anyway. Make sure you check that " + _os + " boots correctly " +
            "after WxFixBoot finishes its operations. Reinstalling the " +
            "bootloader again afterwards is recommended.")

    #Attempt to clear any stuck logical volumes that may have been created by os-prober.
    CoreTools.start_process("dmsetup remove_all -y", privileged=True)

    #Make sure any LVM volume groups are active.
    for disk in DISK_INFO:
        if "VGName" in DISK_INFO[disk]:
            CoreTools.start_process("vgchange -a y " +
                                    DISK_INFO[disk]["VGName"],
                                    privileged=True)

    #Log and notify the user that we're finished removing bootloaders.
    logger.info("remove_old_bootloader(): Finished removing " +
                BOOTLOADER_INFO[_os]["Bootloader"] + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finished removing " +
                 BOOTLOADER_INFO[_os]["Bootloader"] + " from " + _os +
                 "......")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 50)

    return True
示例#19
0
def get_oss():
    """Get the names of all OSs on the HDDs."""
    logger.info("get_oss(): Finding operating systems...")
    root_filesystem = CoreTools.get_partition_mounted_at("/")
    os_info = {}

    #Get Linux OSs.
    keys = list(DISK_INFO.keys())
    keys.sort()

    for partition in keys:
        if DISK_INFO[partition]["Type"] == "Device":
            continue

        elif DISK_INFO[partition]["FileSystem"] in ("hfsplus", "hfs", "apfs"):
            #TODO Check if this is what APFS shows up as.
            #Look for macOS.
            os_name = "macOS ("+partition+")"
            logger.debug("get_oss(): Looking for macOS on "+partition+"...")

            #Check if we need to mount the partition.
            was_mounted = False

            if CoreTools.is_mounted(partition):
                #If mounted, get the mountpoint.
                mount_point = CoreTools.get_mount_point_of(partition)

            else:
                #Mount the partition and check if anything went wrong.
                mount_point = "/mnt/wxfixboot/mountpoints"+partition

                if CoreTools.mount_partition(partition=partition, mount_point=mount_point) != 0:
                    #Ignore the partition.
                    logger.warning("get_oss(): Couldn't mount "+partition
                                   + "! Skipping this partition...")

                    continue

                was_mounted = True

            if os.path.exists(mount_point+"/mach_kernel") \
                or os.path.exists(mount_point+"/System/Library/Kernels/kernel"):

                #Create OS_INFO entry for it.
                logger.debug("get_oss(): Found "+os_name+"...")
                os_info[os_name] = {}
                os_info[os_name]["Name"] = os_name
                os_info[os_name]["IsCurrentOS"] = False
                os_info[os_name]["Arch"] = "Unknown"
                os_info[os_name]["Partition"] = partition
                os_info[os_name]["PackageManager"] = "Mac App Store"

                os_info[os_name]["RawFSTabInfo"], os_info[os_name]["EFIPartition"], \
                os_info[os_name]["BootPartition"] = (["Unknown"], "Unknown", "Unknown")

            #unmount the filesystem if needed.
            if was_mounted:
                if CoreTools.unmount(mount_point) != 0:
                    logger.error("get_oss(): Couldn't unmount "+partition
                                 + "! Doing emergency exit...")

                    CoreTools.emergency_exit("Couldn't unmount "+partition+" after looking for "
                                             + "operating systems on it! Please reboot your "
                                             + "computer and try again.")

        elif DISK_INFO[partition]["FileSystem"] in ("vfat", "ntfs", "exfat"):
            #Look for Windows. NOTE: It seems NTFS volumes can't be mounted twice, which is why
            #we're being more careful here.
            #TODO ^ Check, I think it worked before. Good to be cautious either way.
            logger.debug("get_oss(): Looking for Windows on "+partition+"...")

            #Check if we need to mount the partition.
            was_mounted = False

            if CoreTools.is_mounted(partition):
                #If mounted, get the mountpoint.
                mount_point = CoreTools.get_mount_point_of(partition)

            else:
                #Mount the partition and check if anything went wrong.
                mount_point = "/mnt/wxfixboot/mountpoints"+partition

                if CoreTools.mount_partition(partition=partition, mount_point=mount_point) != 0:
                    #Ignore the partition.
                    logger.warning("get_oss(): Couldn't mount "+partition
                                   + "! Skipping this partition...")

                    continue

                was_mounted = True

            #Check if there's a Windows/WinNT dir.
            if not (os.path.isdir(mount_point+"/WinNT") or os.path.isdir(mount_point+"/Windows") \
                or os.path.isdir(mount_point+"/WINDOWS")):

                #Skip this partition, and unmount if needed.
                logger.info("get_oss(): Windows wasn't found...")

            else:
                #Look for lots of different Windows editions.
                #Look for the newest ones first, due to references to old versions
                #in the licenses messing up our version detection.
                if CoreStartupTools.has_windows_10(mount_point):
                    os_name = "Windows 10"

                elif CoreStartupTools.has_windows_8(mount_point):
                    os_name = "Windows 8/8.1"

                elif CoreStartupTools.has_windows_7(mount_point):
                    os_name = "Windows 7"

                elif CoreStartupTools.has_windows_vista(mount_point):
                    os_name = "Windows Vista"

                elif CoreStartupTools.has_windows_xp(mount_point):
                    os_name = "Windows XP"

                elif CoreStartupTools.has_windows_9x(mount_point):
                    os_name = "Windows 95/98/ME"

                else:
                    #Unknown Windows.
                    os_name = "Windows"

                #Create os_info entry for it.
                os_name = os_name+" ("+partition+")"
                logger.debug("get_oss(): Found "+os_name+"...")
                os_info[os_name] = {}
                os_info[os_name]["Name"] = os_name
                os_info[os_name]["IsCurrentOS"] = False
                os_info[os_name]["Arch"] = "Unknown"
                os_info[os_name]["Partition"] = partition
                os_info[os_name]["PackageManager"] = "Windows Installer"

                os_info[os_name]["RawFSTabInfo"], os_info[os_name]["EFIPartition"], \
                os_info[os_name]["BootPartition"] = (["Unknown"], "Unknown", "Unknown")

            #unmount the filesystem if needed.
            if was_mounted:
                if CoreTools.unmount(mount_point) != 0:
                    logger.error("get_oss(): Couldn't unmount "+partition
                                 +"! Doing emergency exit...")

                    CoreTools.emergency_exit("Couldn't unmount "+partition+" after looking for "
                                             + "operating systems on it! Please reboot your "
                                             + "computer and try again.")

        else:
            #Look for Linux.
            #The python command runs on python 3.
            logger.debug("get_oss(): Looking for Linux on "+partition+"...")

            #If there are aliases for partition, check if the root FS is one of those too.
            root_filesystem_is_alias = False

            if "Aliases" in DISK_INFO[partition]:
                logger.debug("get_oss(): Checking if RootFS is an alias for "+partition+"...")

                if root_filesystem in DISK_INFO[partition]["Aliases"]:
                    logger.debug("get_oss(): RootFS is an alias...")
                    root_filesystem_is_alias = True

                else:
                    logger.debug("get_oss(): RootFS isn't an alias...")
                    root_filesystem_is_alias = False

            if partition == root_filesystem or root_filesystem_is_alias:
                cmd = "cat /etc/os-release"

                apt_cmd = "which apt-get"
                dnf_cmd = "which dnf"
                chroot = False
                is_current_os = True
                mount_point = ""

            else:
                mount_point = "/mnt/wxfixboot/mountpoints"+partition
                cmd = "cat "+mount_point+"/etc/os-release"

                apt_cmd = "chroot "+mount_point+" which apt-get"
                dnf_cmd = "chroot "+mount_point+" which dnf"
                chroot = True
                is_current_os = False

                #Mount the partition and check if anything went wrong.
                if CoreTools.mount_partition(partition=partition, mount_point=mount_point) != 0:
                    #Ignore the partition.
                    logger.warning("get_oss(): Couldn't mount "+partition
                                   + "! Skipping this partition...")

                    continue

            #Look for Linux on this partition.
            retval, temp = CoreTools.start_process(cmd, return_output=True)

            os_name = ""

            try:
                for line in temp.split("\n"):
                    if "PRETTY_NAME" in line:
                        os_name = line.split("=")[1].replace('\"', '')

            except IndexError:
                os_name = ""

            #Run the function to get the architechure.
            os_architecture = CoreStartupTools.determine_os_architecture(mount_point=mount_point)

            #If the OS's name wasn't found, but its architecture was, there must be an OS here, so
            #try to use lsb_release if possible before asking the user. Catch if the name is just
            #whitespace too.
            if (retval != 0 or os_name == "" or os_name.isspace()) and os_architecture != None:
                os_name = CoreStartupTools.get_os_name_with_lsb(partition=partition,
                                                                mount_point=mount_point,
                                                                is_current_os=is_current_os)

                #If we really have to, ask the user.
                if os_name is None:
                    logger.warning("get_oss(): Asking user for OS name instead...")
                    os_name = CoreStartupTools.ask_for_os_name(partition=partition,
                                                               is_current_os=is_current_os)

            #Look for APT.
            package_manager = CoreStartupTools.determine_package_manager(apt_cmd=apt_cmd,
                                                                         dnf_cmd=dnf_cmd)

            #Also check if CoreStartupTools.ask_for_os_name was used to determine the name.
            #If the user skipped naming the OS, ignore it and skip the rest of this loop iteration.
            if os_name is not None and os_architecture is not None and package_manager != "Unknown":
                #Add this information to os_info.
                os_info[os_name] = {}
                os_info[os_name]["Name"] = os_name
                os_info[os_name]["IsCurrentOS"] = is_current_os
                os_info[os_name]["Arch"] = os_architecture
                os_info[os_name]["Partition"] = partition
                os_info[os_name]["PackageManager"] = package_manager

                os_info[os_name]["RawFSTabInfo"], os_info[os_name]["EFIPartition"], \
                os_info[os_name]["BootPartition"] = \
                CoreStartupTools.get_fstab_info(mount_point, os_name)

                if chroot is False:
                    SYSTEM_INFO["CurrentOS"] = os_info[os_name].copy()

            if chroot:
                #unmount the filesystem.
                if CoreTools.unmount(mount_point) != 0:
                    logger.error("get_oss(): Couldn't unmount "+partition
                                 + "! Doing emergency exit...")
                    CoreTools.emergency_exit("Couldn't unmount "+partition+" after looking for "
                                             + "operating systems on it! Please reboot your "
                                             + "computer and try again.")

    #Check that at least one Linux OS was detected.
    linux_oss = []

    #Get list of Linux OSs.
    for _os in os_info:
        if _os[0] not in ("Windows", "macOS"):
            linux_oss.append(os_name)

    if not linux_oss:
        logger.critical("get_oss(): No Linux installations found! If you do have Linux "
                        + "installations but WxFixBoot hasn't found them, please file a bug or "
                        + "ask a question on WxFixBoot's launchpad page. If you're using Windows "
                        + "or macOS, then sorry as WxFixBoot has no support for these operating "
                        + "systems. You could instead use the tools provided by Microsoft and "
                        + "Apple to fix any issues with your computer. Exiting...")

        #Exit.
        CoreTools.emergency_exit("You don't appear to have any Linux installations on your hard "
                                 + "disks. If you do have Linux installations but WxFixBoot "
                                 + "hasn't found them, please file a bug or ask a question on "
                                 + "WxFixBoot's launchpad page. If you're using Windows or macOS, "
                                 + "then sorry as WxFixBoot has no support for these operating "
                                 + "systems. You could instead use the tools provided by Microsoft "
                                 + "and Apple to fix any issues with your computer.")

    #Otherwise...
    logger.debug("get_oss(): Done, os_info Populated okay. Contents: "+str(os_info))
    return os_info, SYSTEM_INFO
示例#20
0
def install_new_bootloader(_os):
    """Install a new bootloader."""
    logger.info("install_new_bootloader(): Preparing to install " +
                BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 52)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Preparing to install " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
        "...###\n")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Preparing to install " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                 _os + "...")

    #If this is the current OS, let the installer functions know that we aren't using chroot.
    if OS_INFO[_os]["IsCurrentOS"]:
        logger.debug(
            "install_new_bootloader(): Modifying current OS so not using chroot..."
        )
        use_chroot, unmount_after, mount_point = (False, False, "")

    #Otherwise, setup the chroot and everything else first, and tell them we are using chroot,
    #and pass the mountpoint to them.
    else:
        logger.debug(
            "install_new_bootloader(): Using chroot to modify another OS...")
        use_chroot = True
        mount_point = "/mnt/wxfixboot/mountpoints" + OS_INFO[_os]["Partition"]

        #Check if the partition is mounted.
        unmount_after = not CoreTools.is_mounted(OS_INFO[_os]["Partition"],
                                                 mount_point)

        if unmount_after:
            if CoreTools.mount_partition(partition=OS_INFO[_os]["Partition"],
                                         mount_point=mount_point) != 0:
                logger.error("install_new_bootloader(): Failed to mount " +
                             OS_INFO[_os]["Partition"] +
                             "! Warn the user and skip this OS.")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="WxFixBoot failed to mount the partition " +
                    "containing " + _os + "! Bootloader installation cannot " +
                    "continue! This may leave your system, or this OS, in " +
                    "an unbootable state. Please close any open programs, " +
                    "then try again when prompted.")

                return False

        #Set up chroot.
        if CoreTools.setup_chroot(mount_point=mount_point) != 0:
            logger.error(
                "install_new_bootloader(): Failed to set up chroot at " +
                mount_point + "! Warning user and giving up...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to set up a chroot for " + _os +
                "! Giving up. You will be prompted to try again if " +
                "you wish.")
            return False

    #If there's a seperate /boot partition for this OS, make sure it's mounted.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.mount_partition(partition=OS_INFO[_os]["BootPartition"],
                                     mount_point=mount_point + "/boot") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " +
                         OS_INFO[_os]["BootPartition"] +
                         "! Warn the user and skip this OS.")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to mount the partition " +
                "containing " + _os + "'s /boot partition! Giving up. " +
                "You will be prompted to try again if you wish.")

            return False

    #Update the package lists.
    if OS_INFO[_os]["PackageManager"] == "apt-get":
        cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get update'"

    elif OS_INFO[_os]["PackageManager"] == "dnf":
        cmd = "dnf check-update"

    if use_chroot:
        cmd = "chroot " + mount_point + " " + cmd

    if CoreTools.start_process(cmd, privileged=True) not in (0, 100):
        logger.error(
            "install_new_bootloader(): Failed to Update the Package Information! "
            + "Continuing anyway...")

        DialogTools.show_msg_dlg(
            kind="error",
            message="WxfixBoot failed to update " + _os +
            "'s package information! Giving up. You will be prompted " +
            "to try again if you wish.")

        return False

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Installing " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                 _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 55)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Installing " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
        "...###\n")

    #Make sure all GNOME APT frontend dependency is installed.
    if OS_INFO[_os]["PackageManager"] == "apt-get":
        #Ubuntu 16.04.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgnome2-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

        #All newer versions.
        cmd = "sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y libgtk3-perl'"

        if use_chroot:
            cmd = "chroot " + mount_point + " " + cmd

        retval = CoreTools.start_process(cmd, privileged=True)

    #Install the bootloader.
    if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB2":
        logger.info("install_new_bootloader(): Installing GRUB2...")

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get install -y grub-pc os-prober'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y install grub2"

    elif BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI":
        logger.info("install_new_bootloader(): Installing GRUB-UEFI...")

        #Mount the UEFI partition at mount_point/boot/efi.
        if CoreTools.mount_partition(
                partition=OS_INFO[_os]["EFIPartition"],
                mount_point=mount_point + "/boot/efi") != 0:

            logger.error("install_new_bootloader(): Failed to mount " +
                         OS_INFO[_os]["EFIPartition"] + " to " + mount_point +
                         "/boot/efi! Aborting bootloader installation and " +
                         "warning user...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxfixBoot failed to mount the partition containing " +
                _os + "'s EFI partition! Giving up. You will be prompted to " +
                "try again if you wish.")

            return False

        if OS_INFO[_os]["PackageManager"] == "apt-get":
            cmd = "sh -c 'DEBIAN_FRONTEND=gnome DISPLAY=:0 apt-get install -y grub-efi os-prober'"

        elif OS_INFO[_os]["PackageManager"] == "dnf":
            cmd = "dnf -y install grub2-efi-ia32 grub2-efi-x64 shim-x64 "

    if use_chroot:
        cmd = "chroot " + mount_point + " " + cmd

    retval = CoreTools.start_process(cmd, privileged=True)

    if retval != 0:
        logger.error(
            "install_new_bootloader(): Failed to install new bootloader. Warn user..."
        )
        DialogTools.show_msg_dlg(kind="error",
                                 message="WxfixBoot failed to install " + _os +
                                 "'s new bootloader! Continuing anyway...")

    #If there's a seperate EFI partition for this OS, make sure it's unmounted before removing
    #the chroot.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot/efi") != 0:
            logger.error("install_new_bootloader(): Failed to unmount " +
                         mount_point +
                         "/boot/efi! This probably doesn't matter...")

    #If there's a seperate /boot partition for this OS, make sure it's unmounted before
    #removing the chroot.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot") != 0:
            logger.error("install_new_bootloader(): Failed to unmount " +
                         mount_point +
                         "/boot! This probably doesn't matter...")

    if use_chroot:
        logger.debug("install_new_bootloader(): Removing chroot...")

        #Tear down chroot.
        if CoreTools.teardown_chroot(mount_point=mount_point) != 0:
            logger.error(
                "install_new_bootloader(): Failed to remove chroot at " +
                mount_point + "! Attempting to continue anyway...")

    if unmount_after:
        if CoreTools.unmount(mount_point) != 0:
            logger.error("install_new_bootloader(): Failed to unmount " +
                         mount_point + "! Continuing anyway...")

    if retval != 0:
        #Something went wrong! Log it and notify the user.
        logger.error(
            "install_new_bootloader(): Failed to install " +
            BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
            "! This may mean the system (or this OS) is now unbootable! " +
            "Warning the user and asking to try again.")

        DialogTools.show_msg_dlg(
            kind="error",
            message="WxFixBoot failed to install " +
            BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
            "! This may leave this OS, or your system, in an unbootable " +
            "state. You will now be prompted to try again.")

        return False

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Finished installing " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " + _os +
        "...###\n")

    #Attempt to clear any stuck logical volumes that may have been created by os-prober.
    CoreTools.start_process("dmsetup remove_all -y", privileged=True)

    #Make sure any LVM volume groups are active.
    for disk in DISK_INFO:
        if "VGName" in DISK_INFO[disk]:
            CoreTools.start_process("vgchange -a y " +
                                    DISK_INFO[disk]["VGName"],
                                    privileged=True)

    #Log and notify the user that we're finished installing the bootloader.
    logger.info("install_new_bootloader(): Finished installing " +
                BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finish installing " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + " in " +
                 _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 75)
    return True
示例#21
0
def check_for_live_disk():
    """Try to determine if we're running on a live disk."""
    logger.info("MainStartupTools(): check_for_live_disk(): Attempting to check if we're on a "
                + "live disk...")

    #Detect Parted Magic automatically.
    if "pmagic" in CoreTools.start_process("uname -r", return_output=True)[1]:
        logger.info("MainStartupTools(): check_for_live_disk(): Running on Parted Magic...")
        SYSTEM_INFO["IsLiveDisk"] = True
        SYSTEM_INFO["OnPartedMagic"] = True

    #Try to detect ubuntu-based livecds.
    elif CoreTools.is_mounted("/cow", "/") and os.path.isfile("/cdrom/casper/filesystem.squashfs"):
        logger.info("MainStartupTools(): check_for_live_disk(): "
                    + "Running on Ubuntu-based live disk...")

        SYSTEM_INFO["IsLiveDisk"] = True
        SYSTEM_INFO["OnPartedMagic"] = False

    #Try to detect fedora-based livecds.
    elif CoreTools.is_mounted("/dev/mapper/live-rw", "/") \
        and os.path.isfile("/run/initramfs/live/LiveOS/squashfs.img"):

        logger.info("MainStartupTools(): check_for_live_disk(): "
                    + "Running on Fedora-based live disk...")

        SYSTEM_INFO["IsLiveDisk"] = True
        SYSTEM_INFO["OnPartedMagic"] = False

    #Try to detect Disk Verifier/any other live disks.
    elif CoreTools.is_mounted("overlay", "/") \
        or os.path.isfile("/run/live/medium/live/filesystem.squashfs"):

        logger.info("MainStartupTools(): check_for_live_disk(): "
                    + "Running on live disk...")

        SYSTEM_INFO["IsLiveDisk"] = True
        SYSTEM_INFO["OnPartedMagic"] = False

    #Try to detect if we're not running on a live disk (on HDD/NVME).
    elif "/dev/sd" in CoreTools.get_partition_mounted_at("/") \
        or "/dev/nvme" in CoreTools.get_partition_mounted_at("/"):

        logger.info("MainStartupTools(): check_for_live_disk(): Not running on live disk...")
        SYSTEM_INFO["IsLiveDisk"] = False
        SYSTEM_INFO["OnPartedMagic"] = False

    #Try to detect if we're not running on a live disk (on LVM).
    elif "/dev/mapper/" in CoreTools.get_partition_mounted_at("/"):
        logger.info("MainStartupTools(): check_for_live_disk(): Not running on live disk...")
        SYSTEM_INFO["IsLiveDisk"] = False
        SYSTEM_INFO["OnPartedMagic"] = False

    #Ask the user if we're running on a live disk.
    else:
        logger.info("MainStartupTools(): check_for_live_disk(): Asking the user if we're running "
                    + "on live media...")

        SYSTEM_INFO["IsLiveDisk"] = DialogTools.show_yes_no_dlg(message="Is WxFixBoot being run "
                                                                + "on live media, such as an "
                                                                + "Ubuntu Installer Disk?",
                                                                title="WxFixBoot - Live Media?")

        SYSTEM_INFO["OnPartedMagic"] = False
        logger.info("MainStartupTools(): check_for_live_disk(): Result: "
                    + str(SYSTEM_INFO["IsLiveDisk"]))

    #Get current OS architecture.
    logger.info("MainStartupTools(): check_for_live_disk(): Getting architecture of current OS...")
    SYSTEM_INFO["CurrentOSArch"] = CoreStartupTools.determine_os_architecture(mount_point="")
示例#22
0
def set_new_bootloader_config(_os):
    """Manage setting new bootloader config."""
    logger.info("set_new_bootloader_config(): Setting " +
                BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                "'s config for " + _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Setting " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                 " config for " + _os + "...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 79)
    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box,
        "\n###Setting " + BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
        "'s config for " + _os + "...###\n")

    #If this is the current OS, let the config functions know that we aren't using chroot.
    if OS_INFO[_os]["IsCurrentOS"]:
        logger.debug(
            "set_new_bootloader_config(): We're modifying the current OS...")
        #If so, make sure this will work for this OS too, and avoid setting mountpoint, so the
        #config instructions below look in the right place for the config files.
        use_chroot, unmount_after, mount_point = (False, False, "")

    else:
        logger.debug(
            "set_new_bootloader_config(): We're modifying another OS...")
        use_chroot = True
        mount_point = "/mnt/wxfixboot/mountpoints" + OS_INFO[_os]["Partition"]

        #Check if the partition is mounted.
        unmount_after = not CoreTools.is_mounted(OS_INFO[_os]["Partition"],
                                                 mount_point)

        if unmount_after:
            #Mount the partition.
            if CoreTools.mount_partition(partition=OS_INFO[_os]["Partition"],
                                         mount_point=mount_point) != 0:
                #Ignore this partition.
                logger.warning(
                    "set_new_bootloader_config(): Failed to mount " +
                    OS_INFO[_os]["Partition"] + "! Giving up...")

                return False

        #Set up chroot.
        if CoreTools.setup_chroot(mount_point=mount_point) != 0:
            logger.error(
                "set_new_bootloader_config(): Failed to set up chroot at " +
                mount_point + "! Giving up...")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to set up a chroot for " + _os +
                "! Giving up. You will be prompted to try again if " +
                "you wish.")

            return False

        wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 81)

    #Mount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.mount_partition(OS_INFO[_os]["BootPartition"],
                                     mount_point + "/boot") != 0:
            logger.error(
                "set_new_bootloader_config(): Failed to mount " + _os +
                "'s /boot partition! Skipping bootloader config setting for this OS."
            )

            if not OS_INFO[_os]["IsCurrentOS"]:
                CoreTools.teardown_chroot(mount_point)
                CoreTools.unmount(mount_point)

            return False

    #If there's a seperate EFI partition for this OS, make sure it's mounted.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.mount_partition(
                partition=OS_INFO[_os]["EFIPartition"],
                mount_point=mount_point + "/boot/efi") != 0:
            logger.error("remove_old_bootloader(): Failed to mount " +
                         OS_INFO[_os]["EFIPartition"] +
                         "! Warn the user and skip this OS.")

            DialogTools.show_msg_dlg(
                kind="error",
                message="WxFixBoot failed to mount the partition containing " +
                _os + "'s EFI partition! Giving up. You will be prompted to " +
                "try again if you wish.")

            return False

    #On GRUB2, get the new menuentries so we can set the default OS.
    logger.info(
        "set_new_bootloader_config(): Reading GRUB2's menu entries to set default OS..."
    )

    if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] in ("GRUB2",
                                                             "GRUB-UEFI"):
        #Update GRUB.
        logger.info(
            "set_new_bootloader_config(): Updating GRUB2 Configuration...")
        BootloaderConfigSettingTools.update_grub2(
            _os=_os,
            package_manager=OS_INFO[_os]["PackageManager"],
            use_chroot=use_chroot,
            mount_point=mount_point)

        BOOTLOADER_INFO[_os]["NewMenuEntries"] = \
        BootloaderConfigObtainingTools.parse_grub2_menu_data(menu_data="",
                                                             mount_point=mount_point)[1]

    #Look for the configuration file, based on which SetConfig() function we're about to run.
    if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] in ("GRUB2",
                                                             "GRUB-UEFI"):
        #Check mount_point/etc/default/grub exists.
        if os.path.isfile(mount_point + "/etc/default/grub"):
            #It does, we'll run the function to set the config now.
            logger.info(
                "set_new_bootloader_config(): Setting GRUB2 Configuration...")
            BootloaderConfigSettingTools.set_grub2_config(
                _os=_os,
                filetoopen=mount_point + "/etc/default/grub",
                bootloader_timeout=BOOTLOADER_INFO[_os]["Settings"]
                ["NewTimeout"],
                kernel_options=BOOTLOADER_INFO[_os]["Settings"]
                ["NewKernelOptions"],
                package_manager=OS_INFO[_os]["PackageManager"])

        if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI":
            #Mount the UEFI partition at mount_point/boot/efi.
            if CoreTools.mount_partition(
                    partition=OS_INFO[_os]["EFIPartition"],
                    mount_point=mount_point + "/boot/efi") != 0:
                logger.error(
                    "set_new_bootloader_config(): Couldn't mount EFI partition "
                    + OS_INFO[_os]["EFIPartition"] +
                    " to install bootloader! Giving up " +
                    "and warning user...")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="WxFixBoot failed to mount " + _os +
                    "'s EFI partition! You will now be promtped to give " +
                    "up or try again.")

                return False

            #Now Install GRUB-UEFI to the UEFI Partition.
            logger.info(
                "set_new_bootloader_config(): Installing GRUB-UEFI to " +
                OS_INFO[_os]["EFIPartition"] + "...")

            BootloaderConfigSettingTools.install_grub2_to_efi_partition(
                package_manager=OS_INFO[_os]["PackageManager"],
                mount_point=mount_point,
                use_chroot=use_chroot,
                uefi_system_partition_mount_point="/boot/efi",
                arch=OS_INFO[_os]["Arch"])

        else:
            #Now Install GRUB2 to the MBR.
            logger.info("set_new_bootloader_config(): Installing GRUB2 to " +
                        DISK_INFO[OS_INFO[_os]["Partition"]]["HostDevice"] +
                        "...")

            BootloaderConfigSettingTools.install_grub2_to_mbr(
                package_manager=OS_INFO[_os]["PackageManager"],
                use_chroot=use_chroot,
                mount_point=mount_point,
                device=DISK_INFO[OS_INFO[_os]["Partition"]]["HostDevice"])

        #Update GRUB.
        logger.info(
            "set_new_bootloader_config(): Updating GRUB2 Configuration...")
        BootloaderConfigSettingTools.update_grub2(
            _os=_os,
            package_manager=OS_INFO[_os]["PackageManager"],
            use_chroot=use_chroot,
            mount_point=mount_point)

        if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI":
            #Make an entry in fstab for the UEFI Partition, if needed.
            HelperBackendTools.write_fstab_entry_for_uefi_partition(
                _os=_os, mount_point=mount_point)

            #Copy and backup EFI files where needed.
            HelperBackendTools.backup_uefi_files(mount_point=mount_point)
            HelperBackendTools.manage_uefi_files(_os=_os,
                                                 mount_point=mount_point)

        if BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB-UEFI" \
            and OS_INFO[_os]["PackageManager"] == "dnf":

            #If we're switching to GRUB-UEFI from BIOS it can mess up GRUB2 and change the boot
            #commands to linux and initrd instead of linuxefi and initrdefi, preventing boot.
            #Fix this. The next time GRUB is updated from within the OS it will fix itself.
            logger.info(
                "set_new_bootloader_config(): Fixing Fedora's GRUB2-UEFI config (when "
                + "booted with BIOS, it can go wrong)...")

            logger.info(
                "set_new_bootloader_config(): Finding and opening GRUB config file..."
            )

            #Find grub.cfg. (Ubuntu).
            if os.path.isdir(mount_point + "/boot/grub"):
                grub_dir = mount_point + "/boot/grub"

            #(Fedora, EFI)
            elif os.path.isdir(mount_point + "/boot/efi/EFI/fedora"):
                grub_dir = mount_point + "/boot/efi/EFI/fedora"

            #Correct the commands if needed.
            config = CoreTools.read_privileged_file(grub_dir + "/grub.cfg")

            new_config = []

            for line in config:
                if "linux16" in line and "/vmlinu" in line:
                    new_config.append(
                        line.replace("linux16", "linuxefi") + "\n")

                elif "linux" in line and "linuxefi" not in line and "/vmlinu" in line:
                    new_config.append(line.replace("linux", "linuxefi") + "\n")

                elif "initrd16" in line and ("/initrd" in line
                                             or "/initramfs" in line):
                    new_config.append(
                        line.replace("initrd16", "initrdefi") + "\n")

                elif "initrd" in line and "initrdefi" not in line \
                    and ("/initrd" in line or "/initramfs" in line):

                    new_config.append(
                        line.replace("initrd", "initrdefi") + "\n")

                else:
                    new_config.append(line + "\n")

            #Write the fixed config.
            CoreTools.write_privileged_file(grub_dir + "/grub.cfg",
                                            ''.join(new_config))

            #unmount the EFI partition.
            if CoreTools.unmount(OS_INFO[_os]["EFIPartition"]) != 0:
                logger.error(
                    "set_new_bootloader_config(): Couldn't unmount EFI partition! "
                    +
                    "This probably won't matter, so we'll continue anyway...")

            logger.info("set_new_bootloader_config(): Done!")

        elif BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] == "GRUB2" \
            and OS_INFO[_os]["PackageManager"] == "dnf":

            #If we're switching to GRUB2 from UEFI it can mess up GRUB2 and change the boot
            #commands to linuxefi and initrdefi instead of linux and initrd, preventing boot.
            #Fix this. The next time GRUB is updated from within the OS it will fix itself.
            logger.info(
                "set_new_bootloader_config(): Fixing Fedora's GRUB2-BIOS config (when "
                + "booted with EFI, it can go wrong)...")

            logger.info(
                "set_new_bootloader_config(): Finding and opening GRUB config file..."
            )

            #Find grub.cfg. (Ubuntu).
            if os.path.isdir(mount_point + "/boot/grub"):
                grub_dir = mount_point + "/boot/grub"

            #(Fedora, BIOS)
            elif os.path.isdir(mount_point + "/boot/grub2"):
                grub_dir = mount_point + "/boot/grub2"

            #Correct the commands if needed.
            config = CoreTools.read_privileged_file(grub_dir + "/grub.cfg")

            new_config = []

            for line in config:
                new_config.append(line.replace("linuxefi", "linux")\
                .replace("initrdefi", "initrd")+"\n")

            #Write the fixed config.
            CoreTools.write_privileged_file(grub_dir + "/grub.cfg",
                                            ''.join(new_config))

            logger.info("set_new_bootloader_config(): Done!")

    #If there's a seperate EFI partition for this OS, make sure it's unmounted before
    #removing the chroot.
    if OS_INFO[_os]["EFIPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot/efi") != 0:
            logger.error("set_new_bootloader_config(): Failed to unmount " +
                         mount_point +
                         "/boot/efi! This probably doesn't matter...")

    #unmount a /boot partition if it exists.
    if OS_INFO[_os]["BootPartition"] != "Unknown":
        if CoreTools.unmount(mount_point + "/boot") != 0:
            logger.error("set_new_bootloader_config(): Failed to unmount " +
                         _os + "'s /boot partition! Continuing anyway...")

    #Tear down chroot if needed.
    if use_chroot:
        if CoreTools.teardown_chroot(mount_point=mount_point) != 0:
            logger.error(
                "set_new_bootloader_config(): Failed to remove chroot at " +
                mount_point + "! Attempting to continue anyway...")

    #unmount the partition if needed.
    if unmount_after:
        if CoreTools.unmount(mount_point) != 0:
            logger.error("set_new_bootloader_config(): Failed to unmount " +
                         mount_point + "! Continuing anyway...")

    #Attempt to clear any stuck logical volumes that may have been created by os-prober.
    CoreTools.start_process("dmsetup remove_all -y", privileged=True)

    #Make sure any LVM volume groups are active.
    for disk in DISK_INFO:
        if "VGName" in DISK_INFO[disk]:
            CoreTools.start_process("vgchange -a y " +
                                    DISK_INFO[disk]["VGName"],
                                    privileged=True)

    logger.debug("set_new_bootloader_config(): Finished setting " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                 "'s config for " + _os + "...")

    wx.CallAfter(
        wx.GetApp().TopWindow.update_output_box, "\n###Finished setting " +
        BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] + "'s config for " +
        _os + "...###\n")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finished setting " +
                 BOOTLOADER_INFO[_os]["Settings"]["NewBootloader"] +
                 "'s config for " + _os + "!")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 100)
    return True
示例#23
0
def write_fstab_entry_for_uefi_partition(_os, mount_point):
    """
    Write an /etc/fstab entry for the UEFI System Partition, if there isn't already one.
    DISABLED***
    """
    #FIXME Disabled cos breaks things.
    #TODO When I try to fix this, use the new config file readers/writers.
    return True

    logger.info("write_fstab_entry_for_uefi_partition(): Preparing to write an fstab entry for "
                + "the UEFI partition ("+OS_INFO[_os]["EFIPartition"]+")...")

    write_entry = True

    #Make the directory mount_point/boot/efi if it doesn't already exist.
    if os.path.isdir(mount_point+"/boot/efi") is False:
        CoreTools.start_process("mkdir -p "+mount_point+"/boot/efi", show_output=False,
                                privileged=True)

    #Open the mount_point/etc/fstab file for reading. If we aren't using chroot, this'll just be
    #/etc/fstab, otherwise, /mnt/wxfixboot/mountpoints/dev/sdxy/etc/fstab. Also, save its contents
    #in a variable.
    fstab = open(mount_point+"/etc/fstab", "r")
    new_file_contents = []

    for line in fstab:
        if OS_INFO[_os]["EFIPartition"] in line \
            or "UUID="+DISK_INFO[OS_INFO[_os]["EFIPartition"]]["UUID"] in line:

            #This fstab already has an entry for the UEFI System Partition!
            write_entry = False

        new_file_contents.append(line)

    #Check if we need to write the entry.
    if write_entry is False:
        #We don't!
        logger.info("write_fstab_entry_for_uefi_partition(): fstab entry already present! "
                    + "Skipping...")

        fstab.close()

    else:
        #We do. If we can use the UUID, then we will, but otherwise we'll use the standard
        #device name.
        logger.info("write_fstab_entry_for_uefi_partition(): Writing fstab entry...")
        new_file_contents.append("\n#fstab entry for UEFI System Partition ("
                                 + OS_INFO[_os]["EFIPartition"]+"), written by WxFixBoot.\n")

        if DISK_INFO[OS_INFO[_os]["EFIPartition"]]["UUID"] != "Unknown":
            logger.info("write_fstab_entry_for_uefi_partition(): Using UUID to prevent problems "
                        + "down the line...")

            new_file_contents.append("UUID="+DISK_INFO[OS_INFO[_os]["EFIPartition"]]["UUID"]
                                     + " /boot/efi vfat defaults 0 2\n")

        else:
            logger.warning("write_fstab_entry_for_uefi_partition(): We have no UUID for the "
                           + "UEFI Partition: "+OS_INFO[_os]["EFIPartition"]+"! This isn't good, "
                           + "and may cause problems down the line. Continuing anyway, using "
                           + "device name instead...")

            new_file_contents.append(OS_INFO[_os]["EFIPartition"]+" /boot/efi vfat defaults 0 2\n")

        #Write the finished lines to the file.
        fstab.close()
        fstab = open(mount_point+"/etc/fstab", 'w')
        fstab.write(''.join(new_file_contents))
        fstab.close()

        logger.info("write_fstab_entry_for_uefi_partition(): Done!")
示例#24
0
def look_for_bootloaders_on_partition(the_os, package_manager, mount_point, using_chroot):
    """Look for bootloaders installed in the OS in the given mount point."""
    if using_chroot:
        logger.debug("look_for_bootloaders_on_partition(): Looking for bootloaders in "
                     + mount_point+"...")

    else:
        logger.debug("look_for_bootloaders_on_partition(): Looking for bootloaders in / "
                     + "(Current OS)...")

    bootloader = "Unknown"
    available_bootloaders = []

    #Okay, let's run a command in the chroot that was set up in FindBootloaderRemovalOSs(),
    #depending on which package manager this OS uses, and which bootloader is currently installed.
    if package_manager == "apt-get":
        cmd = "dpkg --get-selections"

    else:
        cmd = "dnf -C list installed"

    if using_chroot:
        cmd = "chroot "+mount_point+" "+cmd

    output = CoreTools.start_process(cmd, show_output=False, return_output=True,
                                     privileged=True)[1].split("\n")

    #Look for them in a specific order to be as fast a possible and to avoid false positives.
    if package_manager == "apt-get":
        bootloader_packages = ("grub-efi", "grub-pc")
        package_dictionary = {"grub-efi": "GRUB-UEFI", "grub-pc": "GRUB2"}

    else:
        bootloader_packages = ("grub2-efi-x64", "grub2-pc")
        package_dictionary = {"grub2-efi-x64": "GRUB-UEFI", "grub2-pc": "GRUB2"}

    for package in bootloader_packages:
        found = False

        for line in output:
            if package in line:
                if package_manager == "apt-get":
                    if line.split()[1] != "install":
                        continue

                found = True
                break

        if found:
            #On Fedora, GRUB2 for BIOS and GRUB2 for UEFI are both installed by default!
            #To figure out which way we're booting (and which is being used), see whether
            #we are booting in EFI mode or not.
            if package_dictionary[package] == "GRUB-UEFI" \
                and OS_INFO[the_os]["PackageManager"] == "dnf" \
                and SYSTEM_INFO["FirmwareType"] == "BIOS":

                #We're booting with GRUB2.
                continue

            bootloader = package_dictionary[package]
            logger.info("look_for_bootloaders_on_partition(): Found "+bootloader+"...")
            break

    #Look for any other bootloaders that might be available for installation.
    for package in bootloader_packages:
        if package_manager == "apt-get":
            cmd = "apt-cache search "+package

        else:
            cmd = "dnf -C search "+package

        if using_chroot:
            cmd = "chroot "+mount_point+" "+cmd

        output = CoreTools.start_process(cmd, show_output=False, return_output=True,
                                         privileged=True)[1].split("\n")

        #Only look in the package name.
        for line in output:
            try:
                if package_manager == "apt-get":
                    correct_section = line.split()[0]

                else:
                    correct_section = line.split()[0].split(".")[0]

            except IndexError:
                continue

            if package == correct_section:
                if package_dictionary[package] not in available_bootloaders:
                    available_bootloaders.append(package_dictionary[package])

    #Log info.
    available_bootloaders.sort()
    logger.info("look_for_bootloaders_on_partition(): Found available bootloaders: "
                + ', '.join(available_bootloaders))

    #Return info.
    return bootloader, available_bootloaders
def get_oss():
    """Get the names of all OSs on the HDDs."""
    root_fs = CoreTools.get_partition_mounted_at("/")

    #Get Linux OSs.
    keys = list(DISK_INFO.keys())
    keys.sort()

    for partition in keys:
        if DISK_INFO[partition]["Type"] == "Device":
            continue

        elif DISK_INFO[partition]["FileSystem"] in ("hfsplus", "hfs", "apfs"):
            #Look for Mac OS X.
            os_name = "Mac OS X ("+partition+")"

            #Check if we need to mount the partition.
            was_mounted = False

            if CoreTools.is_mounted(partition):
                #If mounted, get the mountpoint.
                mount_point = CoreTools.get_mount_point_of(partition)

            else:
                #Mount the partition and check if anything went wrong.
                mount_point = "/mnt/wxfixboot/mountpoints"+partition

                if CoreTools.mount_partition(partition=partition, mount_point=mount_point) != 0:
                    #Ignore the partition.
                    continue

                was_mounted = True

            if os.path.exists(mount_point+"/mach_kernel") or os.path.exists(mount_point+"/System/Library/Kernels/kernel"):
                #Create OS_INFO entry for it.
                OS_INFO[os_name] = {}
                OS_INFO[os_name]["Name"] = os_name
                OS_INFO[os_name]["IsCurrentOS"] = False
                OS_INFO[os_name]["Arch"] = "Unknown"
                OS_INFO[os_name]["Partition"] = partition
                OS_INFO[os_name]["PackageManager"] = "Mac App Store"
                OS_INFO[os_name]["RawFSTabInfo"], OS_INFO[os_name]["EFIPartition"], OS_INFO[os_name]["BootPartition"] = (["Unknown"], "Unknown", "Unknown")

            #Unmount the filesystem if needed.
            if was_mounted:
                if CoreTools.unmount(mount_point) != 0:
                    break
                    #CoreTools.emergency_exit("Couldn't unmount "+partition+" after looking for"
                    #                         + "operating systems on it! Please reboot your "
                    #                         + "computer and try again.")

        elif DISK_INFO[partition]["FileSystem"] in ("vfat", "ntfs", "exfat"):
            #Look for Windows. NOTE: It seems NTFS volumes can't be mounted twice, which is why
            #we're being more careful here.
            #Check if we need to mount the partition.
            was_mounted = False

            if CoreTools.is_mounted(partition):
                #If mounted, get the mountpoint.
                mount_point = CoreTools.get_mount_point_of(partition)

            else:
                #Mount the partition and check if anything went wrong.
                mount_point = "/mnt/wxfixboot/mountpoints"+partition

                if CoreTools.mount_partition(partition=partition, mount_point=mount_point) != 0:
                    #Ignore the partition.
                    continue

                was_mounted = True

            #Check if there's a Windows/WinNT dir.
            if not (os.path.isdir(mount_point+"/WinNT") or os.path.isdir(mount_point+"/Windows") or os.path.isdir(mount_point+"/WINDOWS")):
                #Skip this partition, and unmount if needed.
                pass

            else:
                #Look for lots of different Windows editions.
                if CoreStartupTools.has_windows_9x(mount_point):
                    os_name = "Windows 95/98/ME"

                elif CoreStartupTools.has_windows_xp(mount_point):
                    os_name = "Windows XP"

                elif CoreStartupTools.has_windows_vista(mount_point):
                    os_name = "Windows Vista"

                elif CoreStartupTools.has_windows_7(mount_point):
                    os_name = "Windows 7"

                elif CoreStartupTools.has_windows_8(mount_point):
                    os_name = "Windows 8/8.1"

                elif CoreStartupTools.has_windows_10(mount_point):
                    os_name = "Windows 10"

                else:
                    #Unknown Windows.
                    os_name = "Windows"

                #Create OS_INFO entry for it.
                os_name = os_name+" ("+partition+")"
                OS_INFO[os_name] = {}
                OS_INFO[os_name]["Name"] = os_name
                OS_INFO[os_name]["IsCurrentOS"] = False
                OS_INFO[os_name]["Arch"] = "Unknown"
                OS_INFO[os_name]["Partition"] = partition
                OS_INFO[os_name]["PackageManager"] = "Windows Installer"
                OS_INFO[os_name]["RawFSTabInfo"], OS_INFO[os_name]["EFIPartition"], OS_INFO[os_name]["BootPartition"] = (["Unknown"], "Unknown", "Unknown")

            #Unmount the filesystem if needed.
            if was_mounted:
                if CoreTools.unmount(mount_point) != 0:
                    break
                    #CoreTools.emergency_exit("Couldn't unmount "+partition+" after looking for"
                    #                         + "operating systems on it! Please reboot your "
                    #                         + "computer and try again.")

        else:
            #Look for Linux.
            #The python command runs on python 2 and python 3.
            #If there are aliases for partition, check if the root FS is one of those too.
            root_fs_is_alias = False

            if "Aliases" in DISK_INFO[partition]:
                root_fs_is_alias = (root_fs in DISK_INFO[partition]["Aliases"])

            if partition == root_fs or root_fs_is_alias:
                cmd = "python -c \"from __future__ import print_function; import platform; print(' '.join(platform.linux_distribution()));\""
                apt_cmd = "which apt-get"
                dnf_cmd = "which dnf"
                chroot = False
                is_current_os = True
                mount_point = ""

            else:
                mount_point = "/mnt/wxfixboot/mountpoints"+partition
                cmd = "chroot "+mount_point+" python -c \"from __future__ import print_function; import platform; print(' '.join(platform.linux_distribution()));\""
                apt_cmd = "chroot "+mount_point+" which apt-get"
                dnf_cmd = "chroot "+mount_point+" which dnf"
                chroot = True
                is_current_os = False

                #Mount the partition and check if anything went wrong.
                if CoreTools.mount_partition(partition=partition, mount_point=mount_point) != 0:
                    #Ignore the partition.
                    continue

            #Look for Linux on this partition.
            retval, temp = CoreTools.start_process(cmd, return_output=True)
            os_name = temp.replace('\n', '')

            #Run the function to get the architechure.
            os_arch = CoreStartupTools.determine_os_architecture(mount_point=mount_point)

            #If the OS's name wasn't found, but its architecture was, there must be an OS here,
            #so try to use lsb_release if possible before asking the user. Catch if the name is
            #just whitespace too.
            if (retval != 0 or os_name == "" or os_name.isspace()) and os_arch != None:
                os_name = CoreStartupTools.get_os_name_with_lsb(partition=partition,
                                                                mount_point=mount_point,
                                                                is_current_os=is_current_os)

                #If we really have to, ask the user.
                if os_name is None:
                    os_name = CoreStartupTools.ask_for_os_name(partition=partition,
                                                               is_current_os=is_current_os)

            #Look for APT.
            package_manager = CoreStartupTools.determine_package_manager(apt_cmd=apt_cmd,
                                                                         dnf_cmd=dnf_cmd) 

            #Also check if CoreStartupTools.ask_for_os_name was used to determine the name.
            #If the user skipped naming the OS, ignore it and skip the rest of this loop iteration.
            if os_name != None and os_arch != None and package_manager != "Unknown":
                #Add this information to OS_INFO.
                OS_INFO[os_name] = {}
                OS_INFO[os_name]["Name"] = os_name
                OS_INFO[os_name]["IsCurrentOS"] = is_current_os
                OS_INFO[os_name]["Arch"] = os_arch
                OS_INFO[os_name]["Partition"] = partition
                OS_INFO[os_name]["PackageManager"] = package_manager
                OS_INFO[os_name]["RawFSTabInfo"], OS_INFO[os_name]["EFIPartition"], OS_INFO[os_name]["BootPartition"] = CoreStartupTools.get_fstab_info(mount_point, os_name)

                if chroot is False:
                    SYSTEM_INFO["CurrentOS"] = OS_INFO[os_name].copy()

            if chroot:
                #Unmount the filesystem.
                if CoreTools.unmount(mount_point) != 0: break
                    #CoreTools.emergency_exit("Couldn't unmount "+partition+" after looking for"
                    #                         + "operating systems on it! Please reboot your "
                    #                         + "computer and try again.")

                #Remove the temporary mountpoint
                os.rmdir(mount_point)

    #Check that at least one OS was detected.
    if len(OS_INFO) >= 1:
        return OS_INFO, SYSTEM_INFO

    #Otherwise...
    return (False, False)
示例#26
0
def filesystem_check(_type, manage_bootloader_function):
    """Quickly check all filesystems."""
    logger.debug("filesystem_check(): Starting...")

    #Update Current Operation Text.
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Preparing for Filesystem Check...")

    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 10)
    wx.CallAfter(wx.GetApp().TopWindow.update_output_box,
                 "\n###Preparing to do the Filesystem Check...###\n")

    #Determine which Disks are to be checked.
    filesystems_to_check = HelperBackendTools.find_checkable_file_systems()
    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 30)

    #Find the length of the list (this is needed to update the progressbars).
    filesystems_to_check_length = len(filesystems_to_check)
    checked = 0

    DialogTools.show_msg_dlg(
        kind="info",
        message="WxFixBoot will now perform the disk checks. " +
        "You may wish to open the terminal output box to view the " +
        "progress information.")

    #Run the check on the checkable Disks
    for disk in filesystems_to_check:
        #Gather info.
        logger.info("filesystem_check():: Checking " + disk + "...")
        wx.CallAfter(wx.GetApp().TopWindow.update_output_box,
                     "\n###Checking Disk: " + disk + "###\n")
        wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                     message="Checking Disk: " + disk)
        wx.CallAfter(
            wx.GetApp().TopWindow.update_current_progress,
            30 + ((50 // filesystems_to_check_length) * (checked + 1)))

        run_badblocks = False

        #Create a command list that will work based on the fstype of this Disk and the type of
        #check we're performing. If there aren't any use cases for the fstype, display a message
        #to the user and skip it.
        if _type == "Quick":
            if DISK_INFO[disk]["FileSystem"] == "jfs":
                exec_cmds = "fsck.jfs -vf " + disk

            elif DISK_INFO[disk]["FileSystem"] == "minix":
                exec_cmds = "fsck.minix -avf " + disk

            elif DISK_INFO[disk]["FileSystem"] == "reiserfs":
                exec_cmds = "fsck.reiserfs -apf " + disk

            elif DISK_INFO[disk]["FileSystem"] == "xfs":
                exec_cmds = "xfs_repair -Pvd " + disk

            elif DISK_INFO[disk]["FileSystem"] in ("hfs", "hfsplus"):
                exec_cmds = "fsck.hfsplus -fy " + disk

            elif DISK_INFO[disk]["FileSystem"] == "vfat":
                exec_cmds = "fsck.vfat -yv " + disk

            elif DISK_INFO[disk]["FileSystem"] in ('ext2', 'ext3', 'ext4',
                                                   'ext4dev'):
                exec_cmds = "fsck." + DISK_INFO[disk][
                    "FileSystem"] + " -yvf " + disk

            else:
                exec_cmds = ""
                logger.warning(
                    "filesystem_check(): Skipping Disk: " + disk +
                    ", as WxFixBoot doesn't support checking it yet...")

                DialogTools.show_msg_dlg(
                    kind="error",
                    message="The filesystem on Disk: " + disk +
                    " could not be checked, as WxFixBoot doesn't support " +
                    "checking it yet. " + disk + " will now be skipped.")

        else:
            #For disks that doesn't do bad sector checks with the normal FS checker,
            #run badblocks manually on them.
            if DISK_INFO[disk]["FileSystem"] == "jfs":
                exec_cmds = "fsck.jfs -vf " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "minix":
                exec_cmds = "fsck.minix -avf " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "reiserfs":
                exec_cmds = "fsck.reiserfs -apf " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "xfs":
                exec_cmds = "xfs_repair -Pvd " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] in ("hfs", "hfsplus"):
                exec_cmds = "fsck.hfsplus -fy " + disk
                run_badblocks = True

            elif DISK_INFO[disk]["FileSystem"] == "vfat":
                exec_cmds = "fsck.vfat -yvt " + disk

            elif DISK_INFO[disk]["FileSystem"] in ('ext2', 'ext3', 'ext4',
                                                   'ext4dev'):
                exec_cmds = "fsck." + DISK_INFO[disk][
                    "FileSystem"] + " -yvcf " + disk

            else:
                exec_cmds = ""
                DialogTools.show_msg_dlg(
                    kind="info",
                    message="The filesystem on Disk: " + disk +
                    " could not be checked, as WxFixBoot doesn't support " +
                    "checking it yet. " + disk + " will now be skipped.")

        #Run the command, and remount the Disk if needed.
        if exec_cmds != "":
            retval = CoreTools.start_process(exec_cmds, privileged=True)

            #Check the return values, and run the handler if needed.
            if retval == 0:
                #Success.
                logger.info("filesystem_check(): Checked Disk: " + disk +
                            ". No Errors Found!")

            else:
                handle_filesystem_check_return_values(
                    exec_cmds=exec_cmds,
                    retval=retval,
                    partition=disk,
                    manage_bootloader_function=manage_bootloader_function)

        #Run bad blocks if requested.
        if run_badblocks:
            retval = CoreTools.start_process("badblocks -sv " + disk,
                                             privileged=True)

            #Check the return values, and run the handler if needed.
            if retval == 0:
                #Success.
                logger.info("filesystem_check(): Checked Disk: " + disk +
                            " for bad sectors. " + "No Errors Found!")

            else:
                handle_filesystem_check_return_values(
                    exec_cmds="badblocks -sv " + disk,
                    retval=retval,
                    partition=disk,
                    manage_bootloader_function=manage_bootloader_function)

        if filesystems_to_check[disk]["Remount"]:
            logger.debug("filesystem_check(): Remounting Disk: " + disk +
                         " Read-Write...")
            retval = CoreTools.mount_partition(
                partition=disk,
                mount_point=filesystems_to_check[disk]["MountPoint"])

            if retval != 0:
                logger.warning(
                    "filesystem_check(): Failed to remount " + disk +
                    " after check. We probably need to reboot first. Never mind..."
                )

        checked += 1

    #Update Current Operation Text.
    wx.CallAfter(wx.GetApp().TopWindow.update_current_operation_text,
                 message="Finished Filesystem Check!")
    wx.CallAfter(wx.GetApp().TopWindow.update_current_progress, 100)
    wx.CallAfter(wx.GetApp().TopWindow.update_output_box,
                 "\n###Finished Filesystem Check!###\n")