diff --git a/CloverApp/Clover.xcodeproj/project.pbxproj b/CloverApp/Clover.xcodeproj/project.pbxproj index c3be25f20..244e0355d 100644 --- a/CloverApp/Clover.xcodeproj/project.pbxproj +++ b/CloverApp/Clover.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 95337172237070CD003F1AF4 /* Cloverhelper in Copy tools */ = {isa = PBXBuildFile; fileRef = 9533716F237070B3003F1AF4 /* Cloverhelper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 9533718323709517003F1AF4 /* bootsectors-install in Resources */ = {isa = PBXBuildFile; fileRef = 9533718223709517003F1AF4 /* bootsectors-install */; }; 9533718523709A36003F1AF4 /* bootsectors-install in Copy CloverV2 */ = {isa = PBXBuildFile; fileRef = 9533718223709517003F1AF4 /* bootsectors-install */; }; 953BC20323720C0A0039755D /* FixedWidthViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 953BC20223720C0A0039755D /* FixedWidthViews.swift */; }; @@ -47,20 +46,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 9533716E237070B3003F1AF4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 958505A92364D36400BCB4A3; - remoteInfo = Cloverhelper; - }; - 95337170237070BB003F1AF4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 958505A82364D36400BCB4A3; - remoteInfo = Cloverhelper; - }; 9542ABBC2373780C00DC03E6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 9542ABB82373780C00DC03E6 /* boot1-inst.xcodeproj */; @@ -143,7 +128,6 @@ 95509171238B1E3A00933A7E /* daemonInstaller in Copy tools */, 9546AE1B23806299007155A6 /* CloverLogOut in Copy tools */, 9542ABC02373783400DC03E6 /* boot1-install in Copy tools */, - 95337172237070CD003F1AF4 /* Cloverhelper in Copy tools */, 9552D748236F33CA00C93377 /* CloverDaemonNew in Copy tools */, ); name = "Copy tools"; @@ -322,7 +306,6 @@ 9569EC8C238DD7C6003AD72C /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Settings.strings; sourceTree = ""; }; 9569EC8E238DD7C8003AD72C /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Settings.strings; sourceTree = ""; }; 9569EC90238DD7CA003AD72C /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Settings.strings; sourceTree = ""; }; - 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Cloverhelper.xcodeproj; path = cloverhelper/Cloverhelper.xcodeproj; sourceTree = ""; }; 958861D9235F75FB00B64173 /* Driver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Driver.swift; sourceTree = ""; }; 95C515212369BAF500E4A3A8 /* NVRAM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NVRAM.swift; sourceTree = ""; }; 95C5152E236A0A7400E4A3A8 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; @@ -356,14 +339,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 9533716B237070B3003F1AF4 /* Products */ = { - isa = PBXGroup; - children = ( - 9533716F237070B3003F1AF4 /* Cloverhelper */, - ); - name = Products; - sourceTree = ""; - }; 9542ABB92373780C00DC03E6 /* Products */ = { isa = PBXGroup; children = ( @@ -428,7 +403,6 @@ 95E68AC8235B862F002B37A5 /* Clover */, 95524B83238051F3005F6425 /* CloverLogOut.xcodeproj */, 9542ABB82373780C00DC03E6 /* boot1-inst.xcodeproj */, - 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */, 95C51577236B21AE00E4A3A8 /* CloverRunAtLogin.xcodeproj */, 9552D740236F33A700C93377 /* CloverDaemonNew.xcodeproj */, 95509169238B1DFA00933A7E /* daemonInstaller.xcodeproj */, @@ -514,7 +488,6 @@ dependencies = ( 95509170238B1E1C00933A7E /* PBXTargetDependency */, 9546AE1923806286007155A6 /* PBXTargetDependency */, - 95337171237070BB003F1AF4 /* PBXTargetDependency */, 9552D747236F33B900C93377 /* PBXTargetDependency */, 9542ABBF2373781300DC03E6 /* PBXTargetDependency */, 95C5157E236B21D400E4A3A8 /* PBXTargetDependency */, @@ -597,10 +570,6 @@ ProductGroup = 9552D741236F33A700C93377 /* Products */; ProjectRef = 9552D740236F33A700C93377 /* CloverDaemonNew.xcodeproj */; }, - { - ProductGroup = 9533716B237070B3003F1AF4 /* Products */; - ProjectRef = 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */; - }, { ProductGroup = 95524B84238051F3005F6425 /* Products */; ProjectRef = 95524B83238051F3005F6425 /* CloverLogOut.xcodeproj */; @@ -622,13 +591,6 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 9533716F237070B3003F1AF4 /* Cloverhelper */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = Cloverhelper; - remoteRef = 9533716E237070B3003F1AF4 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 9542ABBD2373780C00DC03E6 /* boot1-install */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; @@ -753,11 +715,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 95337171237070BB003F1AF4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Cloverhelper; - targetProxy = 95337170237070BB003F1AF4 /* PBXContainerItemProxy */; - }; 9542ABBF2373781300DC03E6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "boot1-install"; @@ -1064,7 +1021,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.13; + CURRENT_PROJECT_VERSION = 1.14; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Clover/Frameworks", @@ -1080,7 +1037,7 @@ "$(inherited)", "$(PROJECT_DIR)/Clover/Frameworks", ); - MARKETING_VERSION = 1.13; + MARKETING_VERSION = 1.14; OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1100,7 +1057,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.13; + CURRENT_PROJECT_VERSION = 1.14; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Clover/Frameworks", @@ -1115,7 +1072,7 @@ "$(inherited)", "$(PROJECT_DIR)/Clover/Frameworks", ); - MARKETING_VERSION = 1.13; + MARKETING_VERSION = 1.14; OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/CloverApp/Clover/Installer/Installer.swift b/CloverApp/Clover/Installer/Installer.swift index 1a8dd37ae..e0f1cb76c 100644 --- a/CloverApp/Clover/Installer/Installer.swift +++ b/CloverApp/Clover/Installer/Installer.swift @@ -803,7 +803,10 @@ class InstallerViewController: NSViewController { let supportedFS = ["exfat", "fat32", "hfs"] if !supportedFS.contains(filesystem) { NSSound.beep() - post(text: "Error: can't install on \(filesystem.uppercased()) filesystem.", add: false, color: nil, scroll: false) + post(text: "Error: can't install on \(filesystem.uppercased()) filesystem.", + add: false, + color: nil, + scroll: false) return } AppSD.isInstalling = true @@ -922,7 +925,6 @@ class InstallerViewController: NSViewController { if settingDict.write(toFile: "/tmp/Cloverapp", atomically: false) { AppSD.isInstalling = true - DispatchQueue.main.async { self.spinner.startAnimation(nil) self.installButton.isEnabled = false @@ -935,8 +937,8 @@ class InstallerViewController: NSViewController { let task = Process() let msg = "Install Clover".locale - let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("Cloverhelper") - let script = "do shell script \"'\(helperPath)'\" with prompt \"\(msg)\" with administrator privileges" + let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("CloverDaemonNew") + let script = "do shell script \"'\(helperPath)' --CLOVER\" with prompt \"\(msg)\" with administrator privileges" task.launchPath = "/usr/bin/osascript" task.arguments = ["-e", script] let pipe: Pipe = Pipe() diff --git a/CloverApp/Clover/Installer/InstallerOutline.swift b/CloverApp/Clover/Installer/InstallerOutline.swift index 763b58b9b..10f7ea178 100644 --- a/CloverApp/Clover/Installer/InstallerOutline.swift +++ b/CloverApp/Clover/Installer/InstallerOutline.swift @@ -850,9 +850,9 @@ class InstallerOutViewController: NSViewController { DispatchQueue.main.asyncAfter(deadline: .now() + 6.0) { self.view.window?.level = .normal } - let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("Cloverhelper") + let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("CloverDaemonNew") - let script = "do shell script \"'\(helperPath)'\" with administrator privileges" + let script = "do shell script \"'\(helperPath)' --CLOVER\" with administrator privileges" var err : NSDictionary? = nil let result : NSAppleEventDescriptor = NSAppleScript(source: script)!.executeAndReturnError(&err) diff --git a/CloverApp/CloverDaemonNew/CloverDaemonNew.xcodeproj/project.pbxproj b/CloverApp/CloverDaemonNew/CloverDaemonNew.xcodeproj/project.pbxproj index 76c25beb1..9e3f2a15c 100644 --- a/CloverApp/CloverDaemonNew/CloverDaemonNew.xcodeproj/project.pbxproj +++ b/CloverApp/CloverDaemonNew/CloverDaemonNew.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 954FF20E2371B13C00C3D94C /* DiskArbitration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 954FF20D2371B13C00C3D94C /* DiskArbitration.framework */; }; 954FF2102371B16300C3D94C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 954FF20F2371B16300C3D94C /* IOKit.framework */; }; 956034F623B7185B00E138D9 /* IO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956034F523B7185A00E138D9 /* IO.swift */; }; + 95620BCD23BF71A500CCBFB2 /* BootInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95620BCC23BF71A500CCBFB2 /* BootInstaller.swift */; }; 95A9A87E23B63F570060F1CA /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A9A87D23B63F570060F1CA /* Constants.swift */; }; /* End PBXBuildFile section */ @@ -28,6 +29,7 @@ 954FF20D2371B13C00C3D94C /* DiskArbitration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiskArbitration.framework; path = System/Library/Frameworks/DiskArbitration.framework; sourceTree = SDKROOT; }; 954FF20F2371B16300C3D94C /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 956034F523B7185A00E138D9 /* IO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IO.swift; path = ../../Clover/IO.swift; sourceTree = ""; }; + 95620BCC23BF71A500CCBFB2 /* BootInstaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BootInstaller.swift; sourceTree = ""; }; 95A9A87D23B63F570060F1CA /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -71,6 +73,7 @@ 953B8DEF2370BB5C007E36E3 /* NVRAM.swift */, 953B8DED2370BB1A007E36E3 /* bdmesg.swift */, 953B8DF12370BF5A007E36E3 /* Extensions.swift */, + 95620BCC23BF71A500CCBFB2 /* BootInstaller.swift */, ); path = CloverDaemonNew; sourceTree = ""; @@ -142,6 +145,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 95620BCD23BF71A500CCBFB2 /* BootInstaller.swift in Sources */, 953B8DF22370BF5B007E36E3 /* Extensions.swift in Sources */, 953D98872377094A003B369E /* Disks.swift in Sources */, 953DBFDF236F037400B0C4FB /* main.swift in Sources */, diff --git a/CloverApp/CloverDaemonNew/CloverDaemonNew/BootInstaller.swift b/CloverApp/CloverDaemonNew/CloverDaemonNew/BootInstaller.swift new file mode 100644 index 000000000..11f4a43a6 --- /dev/null +++ b/CloverApp/CloverDaemonNew/CloverDaemonNew/BootInstaller.swift @@ -0,0 +1,605 @@ +// +// BootInstaller.swift +// CloverDaemonNew +// +// Created by vector sigma on 03/01/2020. +// Copyright © 2020 CloverHackyColor. All rights reserved. +// + +import Foundation + + +class Installer: NSObject { + let ktempLogPath = "/tmp/cltmplog" + private var realTime : Bool = true + private var gTargetVolume : String? = nil + + public var realTimeOutPut:Bool { + get { + return self.realTime + } + set { + self.realTime = newValue + } + } + + private func cleanUp() { + let t = Process() + t.environment = ProcessInfo().environment + if #available(OSX 10.13, *) { + t.executableURL = URL(fileURLWithPath: "/bin/bash") + } else { + t.launchPath = "/bin/bash" + } + t.arguments = ["-c", "rm -f /tmp/Clover* && rm -f /tmp/boot0* && rm -f /tmp/boot1*"] + t.launch() + } + + private func saveLog() { + if (self.gTargetVolume != nil) + && fm.fileExists(atPath: self.gTargetVolume!) + && fm.fileExists(atPath: ktempLogPath) { + let finalLogPath = self.gTargetVolume!.addPath("EFI/CLOVER/Clover.app_install.log") + do { + let data = try Data(contentsOf: URL(fileURLWithPath: finalLogPath)) + (data as NSData).write(toFile: finalLogPath, atomically: false) + } catch { + print(error) + } + } + } + + private func addToLog(_ str: String) { + let output : String = str.hasSuffix("\n") ? str : "\n\(str)" + if let data = output.data(using: .utf8) { + if fm.fileExists(atPath: ktempLogPath) { + if let fh = try? FileHandle(forWritingTo: URL(fileURLWithPath: ktempLogPath)) { + fh.seekToEndOfFile() + fh.write(data) + fh.closeFile() + } + } else { + (data as NSData).write(toFile: ktempLogPath, atomically: false) + } + } + } + + private func log(_ msg: String) { + self.addToLog(msg) + print(msg) + } + + private func exit(_ msg: String) { + print(msg) + self.addToLog(msg) + self.saveLog() + self.cleanUp() + Darwin.exit(EXIT_FAILURE) + } + + private func copyReplace(src: String, dst: String, attr: [FileAttributeKey: Any]?, log: Bool) -> Bool { + var attributes : [FileAttributeKey: Any]? = attr + let upperDir = dst.deletingLastPath + if log { + if upperDir == "/" { + self.log("+ \(dst)") + } else { + self.log("+ ../\(upperDir.lastPath)/\(dst.lastPath)") + } + } + + if !fm.fileExists(atPath: src) { + self.log("Error: \(src) doesn't exist.") + return false + } + + // if attr is nil take attributes from source + if attr == nil { + do { + attributes = try fm.attributesOfItem(atPath: src) + } catch { + print("Warning: can't get attributes from '\(src)'") + } + } + + // remove destination if already exist + if fm.fileExists(atPath: dst) { + do { + try fm.removeItem(atPath: dst) + } catch { + print(error) + return false + } + } + + // create upper directory if needed + if !fm.fileExists(atPath: upperDir) { + do { + try fm.createDirectory(atPath: upperDir, + withIntermediateDirectories: true, + attributes: attributes) + } catch { + print(error) + return false + } + } + + // copy file to destination + do { + try fm.copyItem(atPath: src, toPath: dst) + } catch { + print(error) + return false + } + return true + } + + private func createDirectory(at path: String, attr: [FileAttributeKey: Any]?, exitOnError: Bool) { + var isDir : ObjCBool = false + if fm.fileExists(atPath: path, isDirectory: &isDir) { + if isDir.boolValue { + return + } else { + do { + try fm.removeItem(atPath: path) + } catch { + exit("\(error)") + } + } + } + do { + try fm.createDirectory(atPath: path, + withIntermediateDirectories: true, + attributes: attr) + } catch { + exit("\(error)") + } + } + + // MARK: Install + func install() { + + let df = DateFormatter() + df.locale = Locale(identifier: "en_US") + df.dateFormat = "yyyy-MM-dd hh:mm:ss" + let now = df.string(from: Date()) + + if fm.fileExists(atPath: ktempLogPath) { + try? fm.removeItem(atPath: ktempLogPath) + } + + guard let CloverappDict = NSDictionary(contentsOfFile: "/tmp/Cloverapp") as? [String:AnyObject] else { + exit("Error: can't load Cloverapp dictionary.") + return // make the compiler happy + } + cleanUp() + + let bootSectorsInstall = "/tmp/bootsectors-install" + + let targetVol = CloverappDict["targetVol"] as! String + let disk = CloverappDict["disk"] as! String + let filesystem = CloverappDict["filesystem"] as! String + let shemeMap = CloverappDict["shemeMap"] as! String + let boot0 = CloverappDict["boot0"] as? String + let boot1 = CloverappDict["boot1"] as? String + let boot2 = CloverappDict["boot2"] as? String + let CloverV2 = CloverappDict["CloverV2"] as! String + let boot1installPath = CloverappDict["boot1install"] as? String + let bootSectorsInstallSrc = CloverappDict["bootsectors-install"] as? String + let backUpPath = CloverappDict["BackUpPath"] as? String + let version = CloverappDict["version"] as! String + let isESP = (CloverappDict["isESP"] as! NSNumber).boolValue + + let alt : Bool = (CloverappDict["alt"] as? NSNumber)?.boolValue ?? false + + log("\(version) (v\(daemonVersion)), \(now)") + log("SELF = \(CommandLine.arguments[0])") + if geteuid() != 0 { + exit("Error: you don't have root permissions.") + } + + + if (backUpPath != nil) { + log("Backup made at:\n\(backUpPath!).") + } + + if fm.fileExists(atPath: bootSectorsInstall) { + do { + try fm.removeItem(atPath: bootSectorsInstall) + } catch { + exit("Error: can't remove old bootsectors-install.") + } + } + + if (bootSectorsInstallSrc != nil) { + log("bootSectorsInstallSrc = \(bootSectorsInstallSrc!)") + } + + // MARK: Preferences dict init + let preferences = NSMutableDictionary() + + // MARK: Attributes init + let attributes : [FileAttributeKey: Any] = [FileAttributeKey.posixPermissions: 0777] + + // MARK: Check Volume + + self.gTargetVolume = targetVol + if !fm.fileExists(atPath: targetVol) { + exit("Error: target volume \"\(targetVol)\" doesn't exist.") + } + + if !fm.fileExists(atPath: CloverV2) { + exit("Error: cannot found CloverV2 directory.") + } + + log("Target volume: \(targetVol)") + + if !fm.isWritableFile(atPath: targetVol) { + exit("Error: target volume \"\(targetVol)\" is not writable.") + } + + // MARK: Check paths + var boot0Path: String? = nil + var boot1Path: String? = nil + var boot2Path: String? = nil + if (boot0 != nil) { + log("boot0: \(boot0!)") + preferences.setValue(boot0!, forKey: "boot0") + boot0Path = CloverV2.addPath("BootSectors").addPath(boot0!) + if !fm.fileExists(atPath: boot0Path!) { + exit("Error: cannot found \"\(boot0!)\".") + } + } + + if (boot1 != nil) { + log("boot1: \(boot1!)") + boot1Path = CloverV2.addPath("BootSectors").addPath(boot1!) + if !fm.fileExists(atPath: boot1Path!) { + exit("Error: cannot found \"\(boot1!)\".") + } + } + + if (boot2 != nil) { + log("boot2: \(boot2!)") + preferences.setValue(boot2!, forKey: "boot2") + boot2Path = CloverV2.addPath("Bootloaders/x64").addPath(boot2!) + if !fm.fileExists(atPath: boot2Path!) { + exit("Error: cannot found \"\(boot2!)\".") + } + } + + // MARK: Create Directories + createDirectory(at: targetVol.addPath("EFI/CLOVER"), attr: attributes, exitOnError: true) + createDirectory(at: targetVol.addPath("EFI/BOOT"), attr: attributes, exitOnError: true) + createDirectory(at: targetVol.addPath("EFI/CLOVER/misc"), attr: attributes, exitOnError: true) + + let subDirs = ["ACPI/origin", + "ACPI/patched", + "ACPI/WINDOWS", + "kexts/10", + "kexts/10_recovery", + "kexts/10_installer", + "kexts/10.11", + "kexts/10.12", + "kexts/10.13", + "kexts/10.14", + "kexts/10.15", + "kexts/Other", + "ROM"] + + for dir in subDirs { + createDirectory(at: targetVol.addPath("EFI/CLOVER").addPath(dir), + attr: attributes, + exitOnError: true) + + + } + + for dir in subDirs { + if !fm.fileExists(atPath: targetVol.addPath("EFI/CLOVER/OEM")) { + createDirectory(at: targetVol.addPath("EFI/CLOVER/OEM/SystemProductName").addPath(dir), + attr: attributes, + exitOnError: true) + + if dir != "ROM" { + createDirectory(at: targetVol.addPath("EFI/CLOVER/OEM/SystemProductName/UEFI").addPath(dir), + attr: attributes, + exitOnError: true) + } + } + } + + // MARK: Install Clover and drivers + self.log("\nInstalling/Updating Clover:") + if !copyReplace(src: CloverV2.addPath("EFI/BOOT/BOOTX64.efi"), + dst: targetVol.addPath("EFI/BOOT/BOOTX64.efi"), + attr: attributes, + log: true) { + exit("Error: cannot copy BOOTX64.efi to destination.") + } + + if !copyReplace(src: CloverV2.addPath("EFI/CLOVER/CLOVERX64.efi"), + dst: targetVol.addPath("EFI/CLOVER/CLOVERX64.efi"), + attr: attributes, + log: true) { + exit("Error: cannot copy CLOVERX64.efi to destination.") + } + + self.log("\nInstalling/Updating drivers:") + if let toDelete = CloverappDict["toDelete"] as? [String] { + for dpath in toDelete { + if fm.fileExists(atPath: dpath) { + self.log("- ../\(dpath.deletingLastPath.lastPath)/\(dpath.lastPath)") + do { + try fm.removeItem(atPath: dpath) + } catch { + exit("\(error)") + } + } + } + } + + let UEFIdest = targetVol.addPath("EFI/CLOVER/drivers/UEFI") + let BIOSdest = targetVol.addPath("EFI/CLOVER/drivers/BIOS") + if let UEFI = CloverappDict["UEFI"] as? [String] { + for dpath in UEFI { + if !copyReplace(src: dpath, + dst: UEFIdest.addPath(dpath.lastPath), + attr: attributes, + log: true) { + exit("Error: cannot copy '\(dpath)' to destination.") + } + } + } + + if let BIOS = CloverappDict["BIOS"] as? [String] { + for dpath in BIOS { + if !copyReplace(src: dpath, + dst: BIOSdest.addPath(dpath.lastPath), + attr: attributes, + log: true) { + exit("Error: cannot copy '\(dpath)' to destination.") + } + } + } + + // MARK: Install tools + let cv2tools = CloverV2.addPath("EFI/CLOVER/tools") + if fm.fileExists(atPath: cv2tools) { + self.log("\nInstalling/Updating tools:") + var tools : [String] = [String]() + do { + tools = try fm.contentsOfDirectory(atPath: cv2tools) + } catch { } + + for t in tools { + if t.fileExtension == "efi" { + if !copyReplace(src: cv2tools.addPath(t), + dst: targetVol.addPath("EFI/CLOVER/tools").addPath(t), + attr: attributes, + log: true) { + exit("Error: cannot copy '\(cv2tools.addPath(t))' to destination.") + } + } + } + } + + // MARK: Install docs + let cv2docs = CloverV2.addPath("EFI/CLOVER/doc") + if fm.fileExists(atPath: cv2docs) { + self.log("\nInstalling/Updating docs:") + var docs : [String] = [String]() + do { + docs = try fm.contentsOfDirectory(atPath: cv2docs) + } catch { } + + for d in docs { + if d.fileExtension == "efi" { + var a : [FileAttributeKey: Any]? = nil + do { + a = try fm.attributesOfItem(atPath: cv2docs.addPath(d)) + } catch { } + if !copyReplace(src: cv2docs.addPath(d), + dst: targetVol.addPath("EFI/CLOVER/doc").addPath(d), + attr: a, + log: true) { + // do not fail the installation fro a document. So just log: + self.log("Error: cannot copy '\(cv2tools.addPath(d))' to destination.") + } + } + } + } + + // MARK: Create config.plist + let configPath = targetVol.addPath("EFI/CLOVER/config.plist") + let configSamplePath = CloverV2.addPath("EFI/CLOVER/config-sample.plist") + if !fm.fileExists(atPath: configPath) { + if !copyReplace(src: configSamplePath, + dst: configPath, + attr: attributes, + log: true) { + self.log("Error: cannot copy '\(configSamplePath)' to destination.") + } + } + + // MARK: Install theme + // install the theme defined in config.plist + // Also do nothing if the theme directory already exist + // as Clover is already installed and user as its own free will, + // even to run w/o a theme + if let config = NSDictionary(contentsOfFile: configPath) { + let themesSourceDir = CloverV2.addPath("themespkg") + let themesDestDir = targetVol.addPath("EFI/CLOVER/themes") + if !fm.fileExists(atPath: themesDestDir) { + if let GUI = config.object(forKey: "GUI") as? NSDictionary { + if let Theme = GUI.object(forKey: "Theme") as? String { + if fm.fileExists(atPath: themesSourceDir.addPath(Theme)) { + self.log("\nInstalling Theme \"\(Theme)\":") + if !copyReplace(src: themesSourceDir.addPath(Theme), + dst: themesDestDir.addPath(Theme), + attr: attributes, + log: true) { + // do not fail for a theme, just log: + self.log("Error: cannot copy '\(themesSourceDir.addPath(Theme))' to destination.") + } + } else { + self.log("Warning: cannot found Theme '\(Theme)' defined in config.") + } + } + } + } + } else { + self.log("Warning: cannot read '\(configPath)' into a valid Dictionary.") + } + + // MARK: Stage 2 Installation + if boot2Path != nil { + self.log("\nInstalling stage 2..") + if !copyReplace(src: boot2Path!, + dst: targetVol.addPath("boot"), + attr: attributes, + log: true) { + self.log("Error: cannot copy '\(boot2Path!)' to destination.") + } + + if alt { + preferences.setValue(true, forKey: "boot2Alt") + let bootX64path = CloverV2.addPath("Bootloaders/x64") + var loaders : [String] = [String]() + do { + loaders = try fm.contentsOfDirectory(atPath: bootX64path) + } catch { } + + for boot in loaders { + if boot.hasPrefix("boot") { + self.log("\nInstalling stage 2 \"\(boot) (alt)\".") + if !copyReplace(src: bootX64path.addPath(boot), + dst: targetVol.addPath(boot), + attr: attributes, + log: true) { + exit("Error: cannot copy '\(bootX64path.addPath(boot))' to destination.") + } + } + } + } + // ------------- end stage 2 + } + + // MARK: Write Preferences + preferences.write(toFile: targetVol.addPath("EFI/CLOVER/pref.plist"), atomically: true) + try? fm.setAttributes(attributes, ofItemAtPath: targetVol.addPath("EFI/CLOVER/pref.plist")) + saveLog() + + // MARK: Boot sectors installation + if (boot0Path != nil && boot1Path != nil && bootSectorsInstallSrc != nil) { + if !copyReplace(src: bootSectorsInstallSrc!, + dst: bootSectorsInstall, + attr: nil, + log: false) { + exit("Error: cannot copy '\(bootSectorsInstallSrc!)' to destination.") + } + + + if !copyReplace(src: boot0Path!, + dst: "/tmp".addPath(boot0!), + attr: nil, + log: false) { + exit("Error: cannot copy '\(boot0Path!)' to destination.") + } + + if !copyReplace(src: boot1Path!, + dst: "/tmp".addPath(boot1!), + attr: nil, + log: false) { + exit("Error: cannot copy '\(boot1Path!)' to destination.") + } + + if !copyReplace(src: boot1installPath!, + dst: "/tmp/boot1-install", + attr: nil, + log: false) { + exit("Error: cannot copy '\(boot1installPath!)' to destination.") + } + + let esp = isESP ? "ESP" : "OTHER" + let task = Process() + task.environment = ProcessInfo().environment + if #available(OSX 10.13, *) { + task.executableURL = URL(fileURLWithPath: bootSectorsInstall) + } else { + task.launchPath = bootSectorsInstall + } + task.arguments = [ disk, filesystem, shemeMap, boot0!, boot1!, esp ] + let pipe = Pipe() + + if self.realTime { + task.standardOutput = pipe + task.standardError = pipe + let fh = pipe.fileHandleForReading + fh.waitForDataInBackgroundAndNotify() + + var op1 : NSObjectProtocol! + op1 = NotificationCenter.default.addObserver(forName: NSNotification.Name.NSFileHandleDataAvailable, + object: fh, queue: nil) { + notification -> Void in + let data = fh.availableData + if data.count > 0 { + let output = String(decoding: data, as: UTF8.self) + self.log(output) + fh.waitForDataInBackgroundAndNotify() + } else { + NotificationCenter.default.removeObserver(op1 as Any) + } + } + + var op2 : NSObjectProtocol! + op2 = NotificationCenter.default.addObserver(forName: Process.didTerminateNotification, + object: task, queue: nil) { + notification -> Void in + NotificationCenter.default.removeObserver(op2 as Any) + if task.terminationStatus != 0 { + self.exit("Error: failed installing boot sectors.") + } + + } + + task.launch() + task.waitUntilExit() + } else { + task.standardOutput = pipe + task.standardError = pipe + + let fh = pipe.fileHandleForReading + task.terminationHandler = { (t) in + if t.terminationStatus != 0 { + self.exit("Error: failed installing boot sectors.") + } + } + task.launch() + task.waitUntilExit() + + // TODO: make output in real time + let data = fh.readDataToEndOfFile() + if let out = String(data: data, encoding: .utf8) { + self.log(out) + } + } + } else { + saveLog() + if (isESP) { + let task = Process() + task.environment = ProcessInfo().environment + if #available(OSX 10.13, *) { + task.executableURL = URL(fileURLWithPath: "/usr/sbin/diskutil") + } else { + task.launchPath = "/usr/sbin/diskutil" + } + task.arguments = [ "umount", "force", disk ] + task.launch() + } + cleanUp() + } + Darwin.exit(EXIT_SUCCESS) + // ------------- end + } +} diff --git a/CloverApp/CloverDaemonNew/CloverDaemonNew/main.swift b/CloverApp/CloverDaemonNew/CloverDaemonNew/main.swift index 5840d23d6..d0e2b0bf6 100644 --- a/CloverApp/CloverDaemonNew/CloverDaemonNew/main.swift +++ b/CloverApp/CloverDaemonNew/CloverDaemonNew/main.swift @@ -8,7 +8,7 @@ import Foundation -let daemonVersion = "1.0.9" +let daemonVersion = "1.1.0" let fm = FileManager.default @@ -435,7 +435,7 @@ func main() { exit(EXIT_SUCCESS) } sigtermSource.resume() - + RunLoop.current.run() //dispatchMain() } @@ -443,7 +443,7 @@ func main() { let myPath = CommandLine.arguments[0] let myName = (myPath as NSString).lastPathComponent -if CommandLine.arguments.contains("--install") { +if CommandLine.arguments[1] == "--install" { print("Installing daemon...") // build the launch daemon let launch = NSMutableDictionary() @@ -520,7 +520,7 @@ if CommandLine.arguments.contains("--install") { } catch { print(error) } -} else if CommandLine.arguments.contains("--uninstall") { +} else if CommandLine.arguments[1] == "--uninstall" { print("uninstalling daemon...") do { if fm.fileExists(atPath: launchPlistPath) { @@ -549,6 +549,11 @@ if CommandLine.arguments.contains("--install") { } catch { print(error) } +} else if CommandLine.arguments[1] == "--CLOVER" { + let installer = Installer() + installer.realTimeOutPut = true + installer.install() + RunLoop.current.run() } else { main() } diff --git a/CloverApp/bootsectors-install b/CloverApp/bootsectors-install index f33602f31..a56992360 100755 --- a/CloverApp/bootsectors-install +++ b/CloverApp/bootsectors-install @@ -1,9 +1,10 @@ #!/bin/bash +# Created by vector sigma on 04/11/2019. +# Copyright © 2019 CloverHackyColor. All rights reserved. + logPath="/tmp/cltmplog" exec > >(tee -a $logPath) 2>&1 -# Created by vector sigma on 04/11/2019. -# Copyright © 2019 CloverHackyColor. All rights reserved. cd /tmp diff --git a/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.pbxproj b/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.pbxproj deleted file mode 100644 index edf9aeaa0..000000000 --- a/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.pbxproj +++ /dev/null @@ -1,294 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - 958505AD2364D36400BCB4A3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 958505AC2364D36400BCB4A3 /* main.m */; }; - 95E61978236F87D100D20FCB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95E61977236F87D100D20FCB /* Foundation.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 958505A72364D36400BCB4A3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 958505A92364D36400BCB4A3 /* Cloverhelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Cloverhelper; sourceTree = BUILT_PRODUCTS_DIR; }; - 958505AC2364D36400BCB4A3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 95E61977236F87D100D20FCB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 958505A62364D36400BCB4A3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 95E61978236F87D100D20FCB /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 958505A02364D36300BCB4A3 = { - isa = PBXGroup; - children = ( - 958505AB2364D36400BCB4A3 /* Cloverhelper */, - 958505AA2364D36400BCB4A3 /* Products */, - 95E61976236F87D100D20FCB /* Frameworks */, - ); - sourceTree = ""; - }; - 958505AA2364D36400BCB4A3 /* Products */ = { - isa = PBXGroup; - children = ( - 958505A92364D36400BCB4A3 /* Cloverhelper */, - ); - name = Products; - sourceTree = ""; - }; - 958505AB2364D36400BCB4A3 /* Cloverhelper */ = { - isa = PBXGroup; - children = ( - 958505AC2364D36400BCB4A3 /* main.m */, - ); - path = Cloverhelper; - sourceTree = ""; - }; - 95E61976236F87D100D20FCB /* Frameworks */ = { - isa = PBXGroup; - children = ( - 95E61977236F87D100D20FCB /* Foundation.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 958505A82364D36400BCB4A3 /* Cloverhelper */ = { - isa = PBXNativeTarget; - buildConfigurationList = 958505B02364D36400BCB4A3 /* Build configuration list for PBXNativeTarget "Cloverhelper" */; - buildPhases = ( - 958505A52364D36400BCB4A3 /* Sources */, - 958505A62364D36400BCB4A3 /* Frameworks */, - 958505A72364D36400BCB4A3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Cloverhelper; - productName = cloverhelper; - productReference = 958505A92364D36400BCB4A3 /* Cloverhelper */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 958505A12364D36300BCB4A3 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1130; - ORGANIZATIONNAME = CloverHackyColor; - TargetAttributes = { - 958505A82364D36400BCB4A3 = { - CreatedOnToolsVersion = 11.2; - }; - }; - }; - buildConfigurationList = 958505A42364D36300BCB4A3 /* Build configuration list for PBXProject "Cloverhelper" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 958505A02364D36300BCB4A3; - productRefGroup = 958505AA2364D36400BCB4A3 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 958505A82364D36400BCB4A3 /* Cloverhelper */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 958505A52364D36400BCB4A3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 958505AD2364D36400BCB4A3 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 958505AE2364D36400BCB4A3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - 958505AF2364D36400BCB4A3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = macosx; - }; - name = Release; - }; - 958505B12364D36400BCB4A3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 958505B22364D36400BCB4A3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 958505A42364D36300BCB4A3 /* Build configuration list for PBXProject "Cloverhelper" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 958505AE2364D36400BCB4A3 /* Debug */, - 958505AF2364D36400BCB4A3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 958505B02364D36400BCB4A3 /* Build configuration list for PBXNativeTarget "Cloverhelper" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 958505B12364D36400BCB4A3 /* Debug */, - 958505B22364D36400BCB4A3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 958505A12364D36300BCB4A3 /* Project object */; -} diff --git a/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index edb313a20..000000000 --- a/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/CloverApp/cloverhelper/Cloverhelper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/CloverApp/cloverhelper/Cloverhelper/main.m b/CloverApp/cloverhelper/Cloverhelper/main.m deleted file mode 100644 index a48d55d25..000000000 --- a/CloverApp/cloverhelper/Cloverhelper/main.m +++ /dev/null @@ -1,540 +0,0 @@ -// -// main.m -// Cloverhelper -// -// Created by vector sigma on 26/10/2019. -// Copyright © 2019 CloverHackyColor. All rights reserved. -// - - -/* - This command line must be run as root and it is responsible for creating the Clover tree - and to install boot sectors and drivers. - */ - -// TODO: redone in swift as swift command line are now small in size, with no hurry... -#import - -#define ktempLogPath "/tmp/cltmplog" -#define kfm [NSFileManager defaultManager] - -#pragma mark - -#pragma mark copy and replace files -#pragma mark - - -void cleanUp() { - NSTask *task = [[NSTask alloc] init]; - - [task setEnvironment:[[NSProcessInfo new] environment]]; - [task setLaunchPath:@"/bin/bash"]; - [task setArguments:@[ @"-c", @"rm -f /tmp/Clover* && rm -f /tmp/boot0* && rm -f /tmp/boot1*" ]]; - - [task launch]; -} - -NSString *gTargetVolume; - -void saveLog() { - if (gTargetVolume != nil - && [kfm fileExistsAtPath:gTargetVolume] - && [kfm fileExistsAtPath:@ktempLogPath]) { - NSString *finalLogPath = - [gTargetVolume stringByAppendingPathComponent:@"EFI/CLOVER/Clover.app_install.log"]; - if ([kfm fileExistsAtPath: finalLogPath]) { - [kfm removeItemAtPath:finalLogPath error:nil]; - } - NSData *log = [NSData dataWithContentsOfFile:@ktempLogPath]; - if (log != nil) { - [log writeToFile:finalLogPath atomically:NO]; - } - } -} - -void addToLog(NSString *str) { - if (![kfm fileExistsAtPath:@ktempLogPath]) { - system([[NSString stringWithFormat:@"echo > %s", ktempLogPath] UTF8String]); - } - NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:@ktempLogPath]; - [fh seekToEndOfFile]; - [fh writeData:[str dataUsingEncoding:NSUTF8StringEncoding]]; - [fh closeFile]; -} - -void post(NSString *format, ...) { - va_list arguments; - va_start(arguments, format); - NSString *str = [[NSString alloc] initWithFormat:format arguments:arguments]; - addToLog(str); - va_end(arguments); - printf("%s", [str UTF8String]); - -} - -void exitWithMessage(NSString *format, ...) { - va_list arguments; - va_start(arguments, format); - NSString *str = [[NSString alloc] initWithFormat:format arguments:arguments]; - - va_end(arguments); - printf("%s", [str UTF8String]); - addToLog(str); - saveLog(); - cleanUp(); - exit(EXIT_FAILURE); -} - -BOOL copyReplace(NSString *source, NSString *dest, NSDictionary *attributes) { - NSError *err = nil; - NSString *upperDir = [dest stringByDeletingLastPathComponent]; - - if ([upperDir isEqualToString:@"/"]) { - post(@"+ ../%@\n", [dest lastPathComponent]); - } else { - post(@"+ ../%@/%@\n", - [[dest stringByDeletingLastPathComponent] lastPathComponent], [dest lastPathComponent]); - } - - if (![kfm fileExistsAtPath:source]) { - post(@"Error: %@ doesn't exist\n", source); - return NO; - } - // remove destination if already exist - if ([kfm fileExistsAtPath:dest]) { - [kfm removeItemAtPath:dest error:&err]; - } - - // create upper directory if needed - if (err == nil) { - if (![kfm fileExistsAtPath:upperDir]) { - [kfm createDirectoryAtPath:upperDir - withIntermediateDirectories:YES - attributes:attributes - error:&err]; - } - } - - // copy the new item - if (err == nil) { - if ([kfm copyItemAtPath:source toPath:dest error:&err] && attributes) { - [kfm setAttributes:attributes ofItemAtPath:dest error:nil]; - } - } - - // print any errors if any - if (err != nil) { - post(@"%@\n", err.description); - } - - return (err == nil); -} - -#pragma mark - -#pragma mark Main -#pragma mark - - -int main(int argc, char * const * argv) { - @autoreleasepool { - if ([kfm fileExistsAtPath:@ktempLogPath]) { - [kfm removeItemAtPath:@ktempLogPath error:nil]; - } - - NSDateFormatter * df = [NSDateFormatter new]; - [df setDateFormat:@"yyyy-MMM-dd HH:mm:ss"]; - NSLocale *locale = [[NSLocale alloc] - initWithLocaleIdentifier:@"en_US"]; - [df setLocale:locale]; - NSString *dateString = [df stringFromDate:[NSDate new]]; - - if (geteuid() != 0) { - exitWithMessage(@"Error: you don't have root permissions\n"); - } - - NSDictionary *CloverappDict = [NSDictionary dictionaryWithContentsOfFile:@"/tmp/Cloverapp"]; - if (CloverappDict == nil) { - exitWithMessage(@"Error: can't load Cloverapp dictionary\n"); - } - cleanUp(); - - NSString *bootSectorsInstall = @"/tmp/bootsectors-install"; - - NSString *targetVol = [CloverappDict objectForKey:@"targetVol"]; - NSString *disk = [CloverappDict objectForKey:@"disk"]; - NSString *filesystem = [CloverappDict objectForKey:@"filesystem"]; - NSString *shemeMap = [CloverappDict objectForKey:@"shemeMap"]; - NSString *boot0 = [CloverappDict objectForKey:@"boot0"]; - NSString *boot1 = [CloverappDict objectForKey:@"boot1"]; - NSString *boot2 = [CloverappDict objectForKey:@"boot2"]; - NSString *cloverv2 = [CloverappDict objectForKey:@"CloverV2"]; - NSString *boot1installPath = [CloverappDict objectForKey:@"boot1install"]; - NSString *bootSectorsInstallSrc = [CloverappDict objectForKey:@"bootsectors-install"]; - NSString *backUpPath = [CloverappDict objectForKey:@"BackUpPath"]; - NSString *version = [CloverappDict objectForKey:@"version"]; - BOOL isESP = [[CloverappDict objectForKey:@"isESP"] boolValue]; - - post(@"%@, %@\n\n", version, dateString); - post(@"My Path = %s\n", argv[0]); - if (backUpPath != nil) { - post(@"Backup made at:\n%@.\n", backUpPath); - } - - if ([kfm fileExistsAtPath:bootSectorsInstall]) { - post(@"Note: found old bootsectors-install..removing it..\n"); - if (![kfm removeItemAtPath:bootSectorsInstall error:nil]) { - exitWithMessage(@"Error: can't remove old bootsectors-install."); - } - } - - if (bootSectorsInstallSrc != nil) { - post(@"bootSectorsInstallSrc = %@\n", bootSectorsInstallSrc); - } - - BOOL alt = NO; - if ([CloverappDict objectForKey:@"alt"] != nil) { - alt = [[CloverappDict objectForKey:@"alt"] boolValue]; - } - -#pragma mark Preferences dict init - NSMutableDictionary *preferences = [NSMutableDictionary new]; - -#pragma mark Attributes init - NSDictionary * attributes = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithShort:0777], NSFilePosixPermissions, nil]; -#pragma mark Check Volume - BOOL isDir = NO; - - if (targetVol == nil) { - exitWithMessage(@"Error: option targetVol [path to volume] not specified\n"); - } - gTargetVolume = targetVol; - - if (![kfm fileExistsAtPath:targetVol]) { - exitWithMessage(@"Error: target volume \"%@\" doesn't exist.\n", targetVol); - } - - if (cloverv2 == nil || ![kfm fileExistsAtPath:cloverv2]) { - exitWithMessage(@"Error: cannot found CloverV2 directory\n"); - } - - post(@"Target volume: %@\n", targetVol); - /* - // check if target volume is writable - NSString *volEnds = targetVol; - if (![volEnds hasSuffix:@"/"]) { - volEnds = [targetVol stringByAppendingString:@"/"]; - } - - - if (![kfm isWritableFileAtPath:volEnds]) { - exitWithMessage(@"Error: target volume \"%@\" is not writable.\n", targetVol); - } - */ -#pragma mark Check paths - // check other options before proceed - NSString *boot0Path = nil, *boot1Path = nil, *boot2Path = nil; - if (boot0 != nil) { - post(@"boot0: %@\n", boot0); - [preferences setValue:boot0 forKey:@"boot0"]; - boot0Path = [[cloverv2 stringByAppendingPathComponent:@"BootSectors"] stringByAppendingPathComponent:boot0]; - if (![kfm fileExistsAtPath:boot0Path]) { - exitWithMessage(@"Error: cannot found \"%@\".\n", boot0); - } - } - - if (boot1 != nil) { - post(@"boot1: %@\n", boot1); - boot1Path = [[cloverv2 stringByAppendingPathComponent:@"BootSectors"] stringByAppendingPathComponent:boot1]; - if (![kfm fileExistsAtPath:boot1Path]) { - exitWithMessage(@"Error: cannot found \"%@\".\n", boot1); - } - } - - if (boot2 != nil) { - post(@"boot2: %@\n", boot2); - [preferences setValue:boot2 forKey:@"boot2"]; - boot2Path = [[cloverv2 stringByAppendingPathComponent:@"Bootloaders/x64"] stringByAppendingPathComponent:boot2]; - if (![kfm fileExistsAtPath:boot2Path]) { - exitWithMessage(@"Error: cannot found \"%@\".\n", boot2); - } - } - - NSError *err = nil; - if ([kfm fileExistsAtPath: - [targetVol stringByAppendingPathComponent:@"EFI/CLOVER"] isDirectory:&isDir]) { - if (!isDir) { - [kfm removeItemAtPath: - [targetVol stringByAppendingPathComponent:@"EFI/CLOVER"] error:&err]; - } - } - - if (![kfm fileExistsAtPath:[targetVol stringByAppendingPathComponent:@"EFI/CLOVER"]]) { - [kfm createDirectoryAtPath:[targetVol stringByAppendingPathComponent:@"EFI/CLOVER"] - withIntermediateDirectories:YES - attributes:attributes - error:&err]; - } - - if (err != nil) { - exitWithMessage(@"%@\n", err.description); - } - -#pragma mark Create directories - NSArray *sub = [NSArray arrayWithObjects: - @"EFI/BOOT", - @"EFI/CLOVER/ACPI/origin", - @"EFI/CLOVER/ACPI/patched", - @"EFI/CLOVER/ACPI/WINDOWS", - @"EFI/CLOVER/kexts/10", - @"EFI/CLOVER/kexts/10_recovery", - @"EFI/CLOVER/kexts/10_installer", - @"EFI/CLOVER/kexts/10.11", - @"EFI/CLOVER/kexts/10.12", - @"EFI/CLOVER/kexts/10.13", - @"EFI/CLOVER/kexts/10.14", - @"EFI/CLOVER/kexts/10.15", - @"EFI/CLOVER/kexts/Other", - @"EFI/CLOVER/misc", - @"EFI/CLOVER/ROM", - nil]; - - for (int i = 0; i < [sub count]; i++) { - err = nil; - NSString *fp = [targetVol stringByAppendingPathComponent:[sub objectAtIndex:i]]; - if (![kfm fileExistsAtPath:fp]) { - [kfm createDirectoryAtPath:fp withIntermediateDirectories:YES attributes:attributes error:&err]; - if (err != nil) { - exitWithMessage(@"%@\n", err.description); - } - } - } - -#pragma mark Install Clover and drivers - post(@"\nInstalling/Updating Clover:\n"); - if (!copyReplace([cloverv2 stringByAppendingPathComponent:@"EFI/BOOT/BOOTX64.efi"], - [targetVol stringByAppendingPathComponent:@"EFI/BOOT/BOOTX64.efi"], - attributes)) { - exitWithMessage(@"Error: cannot copy BOOTX64.efi to destination.\n"); - } - - if (!copyReplace([cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/CLOVERX64.efi"], - [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/CLOVERX64.efi"], - attributes)) { - exitWithMessage(@"Error: cannot copy CLOVERX64.efi to destination.\n"); - } - - post(@"\nInstalling/Updating drivers:\n"); - NSArray * toDelete = [CloverappDict objectForKey:@"toDelete"]; - NSArray * UEFI = [CloverappDict objectForKey:@"UEFI"]; - NSArray * BIOS = [CloverappDict objectForKey:@"BIOS"]; - NSString *UEFIdest = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/drivers/UEFI"]; - NSString *BIOSdest = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/drivers/BIOS"]; - - if (UEFI != nil) { - for (int i = 0; i < [UEFI count]; i++) { - NSString *dpath = [UEFI objectAtIndex:i]; - NSString *dname = [dpath lastPathComponent]; - if (!copyReplace(dpath, [UEFIdest stringByAppendingPathComponent:dname], attributes)) { - exitWithMessage(@"Error: cannot copy %@ to destination.\n", dpath); - } - } - } - - if (BIOS != nil) { - for (int i = 0; i < [BIOS count]; i++) { - NSString *dpath = [BIOS objectAtIndex:i]; - NSString *dname = [dpath lastPathComponent]; - if (!copyReplace(dpath, [BIOSdest stringByAppendingPathComponent:dname], attributes)) { - exitWithMessage(@"Error: cannot copy %@ to destination.\n", dpath); - } - } - } - - if (toDelete != nil) { - for (int i = 0; i < [toDelete count]; i++) { - NSString *dpath = [toDelete objectAtIndex:i]; - err = nil; - if ([kfm fileExistsAtPath:dpath]) { - post(@"- ../%@/%@\n", - [[dpath stringByDeletingLastPathComponent] lastPathComponent], - [dpath lastPathComponent]); - [kfm removeItemAtPath:dpath error:&err]; - if (err != nil) { - exitWithMessage(@"%@\n", err.description); - } - } - } - } - -#pragma mark Install tools - NSString *cv2tools = [cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/tools"]; - if ([kfm fileExistsAtPath:cv2tools]) { - post(@"\nInstalling/Updating tools:\n"); - err = nil; - NSArray *tools = [kfm contentsOfDirectoryAtPath:cv2tools error:&err]; - if (err == nil && tools != nil) { - for (int i = 0; i < [tools count]; i++) { - NSString *t = [tools objectAtIndex:i]; - if ([[t pathExtension] isEqualToString:@"efi"]) { - if (!copyReplace([cv2tools stringByAppendingPathComponent:t], - [[targetVol stringByAppendingPathComponent:@"EFI/CLOVER/tools"] - stringByAppendingPathComponent:t], - attributes)) { - exitWithMessage(@"Error: cannot copy %@ to destination.\n", t); - } - } - } - } - } - err = nil; - -#pragma mark Install docs - NSString *cv2docs = [cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/doc"]; - if ([kfm fileExistsAtPath:cv2tools]) { - post(@"\nInstalling/Updating doc:\n"); - err = nil; - NSArray *docs = [kfm contentsOfDirectoryAtPath:cv2docs error:&err]; - if (err == nil && docs != nil) { - for (int i = 0; i < [docs count]; i++) { - NSString *d = [docs objectAtIndex:i]; - if (![d hasPrefix:@"."]) { - NSString *docpath = [cv2docs stringByAppendingPathComponent:d]; - NSDictionary *docattr = [kfm attributesOfItemAtPath:docpath error:nil]; - if (!copyReplace(docpath, - [[targetVol stringByAppendingPathComponent:@"EFI/CLOVER/doc"] - stringByAppendingPathComponent:d], - docattr)) { - - //exitWithMessage(@"Error: cannot copy %@ to destination.\n", d); - // ... will not fail for a doc.. - post(@"Error: cannot copy %@ to destination.\n", d); - } - } - } - } - } - err = nil; - -#pragma mark Create config.plist - NSString *configPath = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/config.plist"]; - NSString *configSamplePath = [cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/config-sample.plist"]; - if (![kfm fileExistsAtPath:configPath]) { - post(@"\nInstalling config.plist:\n"); - copyReplace(configSamplePath, configPath, attributes); - } - -#pragma mark Install theme - // install the theme defined in config if doesn't exist - NSDictionary *config = [NSDictionary dictionaryWithContentsOfFile:configPath]; - NSString *themesSourceDir = [cloverv2 stringByAppendingPathComponent:@"themespkg"]; - NSString *themesDestDir = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/themes"]; - - if (config != nil && ![kfm fileExistsAtPath:themesDestDir]) { - NSString *theme = nil; - NSDictionary *GUI = [config objectForKey:@"GUI"]; - if (GUI != nil) { - theme = [GUI objectForKey:@"Theme"]; - } - - // don't overwrite the theme if already exist as one from CTM can be newer - if (theme != nil && ![kfm fileExistsAtPath: - [themesDestDir stringByAppendingPathComponent:theme]]) { - post(@"\nInstalling Theme \"%@\":\n", theme); - copyReplace([themesSourceDir stringByAppendingPathComponent:theme], - [themesDestDir stringByAppendingPathComponent:theme], - attributes); - } - } - -#pragma mark Stage 2 installation - if (boot2Path != nil) { - post(@"\nInstalling stage 2..\n"); - if (!copyReplace(boot2Path, [targetVol stringByAppendingPathComponent:@"boot"], attributes)) { - exitWithMessage(@"Error: cannot copy bootloader to detination.\n"); - } - - if (alt) { - [preferences setValue:[NSNumber numberWithBool:YES] forKey:@"boot2Alt"]; - NSString *altPath = [boot2Path stringByDeletingLastPathComponent]; - NSArray *files = [kfm contentsOfDirectoryAtPath:altPath error:nil]; - if (files) { - for (int i = 0; i < [files count]; i++) { - NSString *f = [files objectAtIndex:i]; - if ([f hasPrefix:@"boot"]) { - post(@"\nInstalling stage 2 \"%@ (alt)\".\n", f); - copyReplace([altPath stringByAppendingPathComponent: f], - [targetVol stringByAppendingPathComponent:f], - attributes); - } - } - } - } - } - -#pragma mark Write Preferences - NSString *prefPath = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/pref.plist"]; - if ([preferences writeToFile:prefPath atomically:YES]) { - [kfm setAttributes:attributes ofItemAtPath:prefPath error:nil]; - } - - saveLog(); -#pragma mark Boot sectors installation - if (boot0Path != nil && boot1Path != nil && bootSectorsInstallSrc != nil) { - // copy bootsectors-install - [kfm copyItemAtPath:bootSectorsInstallSrc toPath:bootSectorsInstall error:nil]; - NSDictionary *bsiAttr = [kfm attributesOfItemAtPath:bootSectorsInstallSrc error:nil]; - [kfm setAttributes:bsiAttr ofItemAtPath:bootSectorsInstall error:nil]; - - // copy boot0 - [kfm copyItemAtPath:boot0Path toPath:[@"/tmp" stringByAppendingPathComponent:boot0] error:nil]; - // copy boot1 - [kfm copyItemAtPath:boot1Path toPath:[@"/tmp" stringByAppendingPathComponent:boot1] error:nil]; - - [kfm copyItemAtPath:boot1installPath toPath:@"/tmp/boot1-install" error:nil]; - - /* - /tmp/bootsectors-install disk4s1 hfs FDisk_partition_scheme boot0af boot1h - */ - NSTask *task = [[NSTask alloc] init]; - NSPipe *pipe = [NSPipe new]; - - task.standardOutput = pipe; - task.standardError = pipe; - - NSFileHandle * fh = [pipe fileHandleForReading]; - - [task setEnvironment:[[NSProcessInfo new] environment]]; - [task setLaunchPath:bootSectorsInstall]; - - NSString *esp = isESP ? @"ESP" : @"OTHER"; - [task setArguments:@[ disk, filesystem, shemeMap, boot0, boot1, esp ]]; - - task.terminationHandler = ^(NSTask *theTask) { - if (theTask.terminationStatus != 0) { - exitWithMessage(@"Error: failed installing boot sectors.\n"); - } - }; - [task launch]; - //[task waitUntilExit]; - NSData *data = [fh readDataToEndOfFile]; - if (data) { - NSString *output = [[NSString alloc] initWithData:data - encoding:NSUTF8StringEncoding]; - post(@"%@\n", output); - } - - } else { - saveLog(); - if (isESP) { - NSTask *task = [[NSTask alloc] init]; - [task setEnvironment:[[NSProcessInfo new] environment]]; - [task setLaunchPath:@"/usr/sbin/diskutil"]; - [task setArguments:@[ @"umount", @"force", disk ]]; - [task launch]; - } - } - cleanUp(); - exit(EXIT_SUCCESS); - - } - return 0; -} -