from Scripts import *
import os, datetime, shutil, time, sys, argparse
class buildMacOSInstallApp:
def __init__(self):
self.r = run.Run()
self.u = utils.Utils("Build macOS Install App")
self.target_files = [
"BaseSystem.dmg",
"BaseSystem.chunklist",
"InstallESDDmg.pkg",
"InstallInfo.plist",
"AppleDiagnostics.dmg",
"AppleDiagnostics.chunklist"
]
if not sys.platform == "darwin":
self.u.head("WARNING")
print("")
print("This script only runs on macOS!")
print("")
exit(1)
def mount_dmg(self, dmg, no_browse = False):
args = ["/usr/bin/hdiutil", "attach", dmg, "-plist", "-noverify"]
if no_browse:
args.append("-nobrowse")
out = self.r.run({"args":args})
if out[2] != 0:
raise Exception("Mount Failed!", "{} failed to mount:\n\n{}".format(os.path.basename(dmg), out[1]))
try:
plist_data = plist.loads(out[0])
mounts = [x["mount-point"] for x in plist_data.get("system-entities", []) if "mount-point" in x]
return mounts
except:
raise Exception("Mount Failed!", "No mount points returned from {}".format(os.path.basename(dmg)))
def unmount_dmg(self, mount_point):
if not type(mount_point) is list:
mount_point = [mount_point]
unmounted = []
for m in mount_point:
args = ["/usr/bin/hdiutil", "detach", m]
out = self.r.run({"args":args})
if out[2] != 0:
args.append("-force")
out = self.r.run({"args":args})
if out[2] != 0:
print(out[1])
continue
unmounted.append(m)
return unmounted
def main(self):
while True:
self.u.head()
print("")
print("Q. Quit")
print("")
fold = self.u.grab("Please drag and drop the output folder from gibMacOS here: ")
print("")
if fold.lower() == "q":
self.u.custom_quit()
f_path = self.u.check_path(fold)
if not f_path:
print("That path does not exist!\n")
self.u.grab("Press [enter] to return...")
continue
if not os.path.isdir(f_path):
f_path = os.path.dirname(os.path.realpath(f_path))
lower_contents = [y.lower() for y in os.listdir(f_path)]
if "installassistant.pkg" in lower_contents:
self.u.head("InstallAssistant.pkg Found")
print("")
print("Located InstallAssistant.pkg in the passed folder.\n")
print("As of macOS Big Sur (11.x), Apple changed how they distribute the OS files in")
print("the software update catalog.\n")
print("Double clicking the InstallAssistant.pkg will open it in Installer, which will")
print("copy the Install macOS [version].app to your /Applications folder.\n")
print("Opening InstallAssistant.pkg...")
self.r.run({"args":["open",os.path.join(f_path,"InstallAssistant.pkg")]})
print("")
self.u.grab("Press [enter] to return...")
continue
missing_list = [x for x in self.target_files if not x.lower() in lower_contents]
if len(missing_list):
self.u.head("Missing Required Files")
print("")
print("That folder is missing the following required files:")
print(", ".join(missing_list))
print("")
self.u.grab("Press [enter] to return...")
cwd = os.getcwd()
os.chdir(f_path)
base_mounts = []
try:
self.u.head("Building Installer")
print("")
print("Taking ownership of downloaded files...")
for x in self.target_files:
print(" - {}...".format(x))
self.r.run({"args":["chmod","a+x",x]})
print("Mounting BaseSystem.dmg...")
base_mounts = self.mount_dmg("BaseSystem.dmg")
if not len(base_mounts):
raise Exception("Mount Failed!", "No mount points were returned from BaseSystem.dmg")
base_mount = base_mounts[0]
print("Locating Installer app...")
install_app = next((x for x in os.listdir(base_mount) if os.path.isdir(os.path.join(base_mount,x)) and x.lower().endswith(".app") and not x.startswith(".")),None)
if not install_app:
raise Exception("Installer app not located in {}".format(base_mount))
print(" - Found {}".format(install_app))
out = self.r.run({"args":["cp","-R",os.path.join(base_mount,install_app),os.path.join(f_path,install_app)]})
if out[2] != 0:
raise Exception("Copy Failed!", out[1])
print("Unmounting BaseSystem.dmg...")
for x in base_mounts:
self.unmount_dmg(x)
base_mounts = []
shared_support = os.path.join(f_path,install_app,"Contents","SharedSupport")
if not os.path.exists(shared_support):
print("Creating SharedSupport directory...")
os.makedirs(shared_support)
print("Copying files to SharedSupport...")
for x in self.target_files:
y = "InstallESD.dmg" if x.lower() == "installesddmg.pkg" else x
print(" - {}{}".format(x, " --> {}".format(y) if y != x else ""))
out = self.r.run({"args":["cp","-R",os.path.join(f_path,x),os.path.join(shared_support,y)]})
if out[2] != 0:
raise Exception("Copy Failed!", out[1])
print("Patching InstallInfo.plist...")
with open(os.path.join(shared_support,"InstallInfo.plist"),"rb") as f:
p = plist.load(f)
if "Payload Image Info" in p:
pii = p["Payload Image Info"]
if "URL" in pii: pii["URL"] = pii["URL"].replace("InstallESDDmg.pkg","InstallESD.dmg")
if "id" in pii: pii["id"] = pii["id"].replace("com.apple.pkg.InstallESDDmg","com.apple.dmg.InstallESD")
pii.pop("chunklistURL",None)
pii.pop("chunklistid",None)
with open(os.path.join(shared_support,"InstallInfo.plist"),"wb") as f:
plist.dump(p,f)
print("")
print("Created: {}".format(install_app))
print("Saved to: {}".format(os.path.join(f_path,install_app)))
print("")
self.u.grab("Press [enter] to return...")
except Exception as e:
print("An error occurred:")
print(" - {}".format(e))
print("")
if len(base_mounts):
for x in base_mounts:
print(" - Unmounting {}...".format(x))
self.unmount_dmg(x)
print("")
self.u.grab("Press [enter] to return...")
if __name__ == '__main__':
b = buildMacOSInstallApp()
b.main()