Implement Root Volume backups

Closes https://github.com/dortania/OpenCore-Legacy-Patcher/issues/378
This commit is contained in:
Mykola Grymalyuk
2021-08-02 16:34:19 -06:00
parent 03f65d1766
commit 33653a7108
7 changed files with 151 additions and 30 deletions

View File

@@ -64,6 +64,8 @@ class PatchSysVolume:
if Path(self.mount_extensions).exists():
print("- Root Volume is already mounted")
if patch is True:
if self.constants.detected_os < self.constants.big_sur or Utilities.check_seal() is True:
self.backup_volume()
self.patch_root_vol()
return True
else:
@@ -76,6 +78,8 @@ class PatchSysVolume:
if Path(self.mount_extensions).exists():
print("- Successfully mounted the Root Volume")
if patch is True:
if self.constants.detected_os < self.constants.big_sur or Utilities.check_seal() is True:
self.backup_volume()
self.patch_root_vol()
return True
else:
@@ -91,6 +95,95 @@ class PatchSysVolume:
if self.constants.gui_mode is False:
input("- Press [ENTER] to exit: ")
def backup_volume(self):
for location in SysPatchArray.BackupLocations:
Utilities.cls()
print("Backing up root volume before patching (This may take some time)")
print(f"- Attempting to backup {location}")
location_zip = f"{location}-Backup.zip"
location_zip_path = Path(self.mount_location) / Path(location_zip)
if location_zip_path.exists():
print(f"- Found existing {location_zip}, skipping")
else:
print(f"- Backing up {location}")
# cp -r ./Extensions ./Extensions-Backup
# ditto -c -k --sequesterRsrc --keepParent ./Extensions-Backup ./Extensions-Backup.zip
# rm -r ./Extensions-Backup
print("- Creating Backup folder")
Utilities.process_status(
self.elevated(
["cp", "-r", f"{self.mount_location}/{location}", f"{self.mount_location}/{location}-Backup"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
)
print("- Zipping Backup folder")
Utilities.process_status(
self.elevated(
["ditto", "-c", "-k", "--sequesterRsrc", "--keepParent", f"{self.mount_location}/{location}-Backup", f"{self.mount_location}/{location_zip}"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
)
print("- Removing Backup folder")
Utilities.process_status(
self.elevated(
["rm", "-r", f"{self.mount_location}/{location}-Backup"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
)
def manual_root_patch_revert(self):
print("- Attempting to revert patches")
if (Path(self.mount_location) / Path("System/Library/Extensions-Backup.zip")).exists():
print("- Verified manual unpatching is available")
for location in SysPatchArray.BackupLocations:
Utilities.cls()
print("Reverting root volume patches (This may take some time)")
print(f"- Attempting to unpatch {location}")
location_zip = f"{location}-Backup.zip"
location_zip_path = Path(self.mount_location) / Path(location_zip)
location_old_path = Path(self.mount_location) / Path(location)
if "PrivateFrameworks" in location:
copy_path = Path(self.mount_location) / Path("System/Library/PrivateFrameworks")
elif "Frameworks" in location:
copy_path = Path(self.mount_location) / Path("System/Library/Frameworks")
else:
copy_path = Path(self.mount_location) / Path("System/Library")
if location_zip_path.exists():
print(f"- Found {location_zip}")
print(f"- Unzipping {location_zip}")
Utilities.process_status(self.elevated(["unzip", location_zip_path, "-d", copy_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
if location_old_path.exists():
print(f"- Renaming {location}")
Utilities.process_status(self.elevated(["mv", location_old_path, f"{location_old_path}-Patched"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
print(f"- Renaming {location}-Backup")
Utilities.process_status(self.elevated(["mv", f"{location_old_path}-Backup", location_old_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
print(f"- Removing {location_old_path}-Patched")
Utilities.process_status(self.elevated(["rm", "-r", f"{location_old_path}-Patched"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
# ditto will create a '__MACOSX' folder
# print("- Removing __MACOSX folder")
# Utilities.process_status(self.elevated(["rm", "-r", f"{copy_path}/__MACOSX"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
else:
print(f"- Failed to find {location_zip}, unable to unpatch")
self.rebuild_snapshot()
else:
print("- Could not find Extensions.zip, cannot manually unpatch root volume")
def unpatch_root_vol(self):
if self.constants.detected_os > self.constants.catalina:
print("- Reverting to last signed APFS snapshot")
@@ -99,13 +192,13 @@ class PatchSysVolume:
print("- Unable to revert root volume patches")
print("Reason for unpatch Failure:")
print(result.stdout.decode())
# print("- Failed to revert snapshot via bless, falling back on manual restoration")
# self.undo_root_patch()
print("- Failed to revert snapshot via bless, falling back on manual restoration")
self.manual_root_patch_revert()
else:
print("- Unpatching complete")
print("\nPlease reboot the machine for patches to take effect")
# else:
# self.undo_root_patch()
else:
self.manual_root_patch_revert()
def rebuild_snapshot(self):
if self.constants.gui_mode is False: