Clover.app v1.08 Beta

Fixes and improvement for the Disable Sleep Proxy client and the save NVRAM  functions. Other small fixes.
This commit is contained in:
vectorsigma72 2019-11-21 00:13:41 +01:00
parent d447228625
commit c822eefd22
5 changed files with 175 additions and 113 deletions

View File

@ -855,7 +855,7 @@
CODE_SIGN_ENTITLEMENTS = Clover/Clover.entitlements; CODE_SIGN_ENTITLEMENTS = Clover/Clover.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.07; CURRENT_PROJECT_VERSION = 1.08;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Clover/Frameworks", "$(PROJECT_DIR)/Clover/Frameworks",
@ -869,7 +869,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Clover/Frameworks", "$(PROJECT_DIR)/Clover/Frameworks",
); );
MARKETING_VERSION = 1.07; MARKETING_VERSION = 1.08;
PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover; PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -884,7 +884,7 @@
CODE_SIGN_ENTITLEMENTS = Clover/Clover.entitlements; CODE_SIGN_ENTITLEMENTS = Clover/Clover.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.07; CURRENT_PROJECT_VERSION = 1.08;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Clover/Frameworks", "$(PROJECT_DIR)/Clover/Frameworks",
@ -898,7 +898,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Clover/Frameworks", "$(PROJECT_DIR)/Clover/Frameworks",
); );
MARKETING_VERSION = 1.07; MARKETING_VERSION = 1.08;
PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover; PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View File

@ -147,6 +147,7 @@ func getMediaName(from diskOrMtp: String) -> String? {
return name return name
} }
/// Get Media Name (kDADiskDescriptionDeviceProtocolKey). /// Get Media Name (kDADiskDescriptionDeviceProtocolKey).
func getDeviceProtocol(from diskOrMtp: String) -> String { func getDeviceProtocol(from diskOrMtp: String) -> String {
var prot : String = kNotAvailable var prot : String = kNotAvailable
@ -343,6 +344,7 @@ func isMountPoint(path: String) -> Bool {
return (mtp != nil) return (mtp != nil)
} }
/// mount the given disk object. The path for the mount point is optional.
func mount(disk bsdName: String, at path: String?) { func mount(disk bsdName: String, at path: String?) {
var disk : String = bsdName var disk : String = bsdName
if disk.hasPrefix("disk") || disk.hasPrefix("/dev/disk") { if disk.hasPrefix("disk") || disk.hasPrefix("/dev/disk") {
@ -401,6 +403,7 @@ func mount(disk bsdName: String, at path: String?) {
} }
} }
/// mount the given disk object. The path for the mount point is optional. Code executed in a closure that return a boolean value.
func mount(disk bsdName: String, func mount(disk bsdName: String,
at path: String?, at path: String?,
reply: @escaping (Bool) -> ()) { reply: @escaping (Bool) -> ()) {
@ -467,6 +470,7 @@ func mount(disk bsdName: String,
reply(false) reply(false)
} }
/// unmount the given disk object or mount point. force used to kill any pid is using the disk.
func umount(disk diskOrMtp: String, force: Bool) { func umount(disk diskOrMtp: String, force: Bool) {
let disk : String = diskOrMtp let disk : String = diskOrMtp
let mtp : String? = getMountPoint(from: diskOrMtp) let mtp : String? = getMountPoint(from: diskOrMtp)
@ -517,6 +521,7 @@ func umount(disk diskOrMtp: String, force: Bool) {
} }
} }
/// unmount the given disk object or mount point. force used to kill any pid is using the disk. Code executed in a closure that return a boolean value.
func umount(disk diskOrMtp: String, func umount(disk diskOrMtp: String,
force: Bool, force: Bool,
reply: @escaping (Bool) -> ()) { reply: @escaping (Bool) -> ()) {
@ -574,6 +579,7 @@ func umount(disk diskOrMtp: String,
reply(false) reply(false)
} }
/// Helper function for the mount/umout call back
fileprivate func printDAReturn(r: DAReturn) -> String { fileprivate func printDAReturn(r: DAReturn) -> String {
switch Int(r) { switch Int(r) {
case kDAReturnError: case kDAReturnError:
@ -603,5 +609,4 @@ fileprivate func printDAReturn(r: DAReturn) -> String {
default: default:
return "Unknown" return "Unknown"
} }
} }

View File

@ -392,7 +392,7 @@ class SettingsViewController: NSViewController, NSTextFieldDelegate, URLSessionD
let nvdata = nvram.object(forKey: key) as? Data let nvdata = nvram.object(forKey: key) as? Data
value = String(decoding: nvdata ?? Data(), as: UTF8.self) value = String(decoding: nvdata ?? Data(), as: UTF8.self)
} }
self.disbaleSleepProxyButton.state = (value == "true") ? .on : .off self.makeRootRWButton.state = (value == "true") ? .on : .off
} }
} }

View File

@ -9,11 +9,16 @@
import Foundation import Foundation
let fm = FileManager.default let fm = FileManager.default
let daemonVersion = "1.0.4" let daemonVersion = "1.0.7"
let wrapperPath = "/Library/Application Support/Clover/CloverWrapper.sh" let wrapperPath = "/Library/Application Support/Clover/CloverWrapper.sh"
let loginwindow = "/var/root/Library/Preferences/com.apple.loginwindow.plist" let loginWindowPath = "/var/root/Library/Preferences/com.apple.loginwindow.plist"
let lh = "/Library/Application Support/Clover/CloverLogOut" let cloverLogOut = "/Library/Application Support/Clover/CloverLogOut"
let cloverDaemonNewPath = "/Library/Application Support/Clover/CloverDaemonNew"
let launchPlistPath = "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist"
let oldLaunchPlistPath = "/Library/LaunchDaemons/com.projectosx.clover.daemon.plist"
func execAttr() -> [FileAttributeKey : Any] { func execAttr() -> [FileAttributeKey : Any] {
var attributes = [FileAttributeKey : Any]() var attributes = [FileAttributeKey : Any]()
@ -62,46 +67,59 @@ func checkSleepProxyClient(nvram: NSDictionary) {
let mDNSResponderPath = "/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist" let mDNSResponderPath = "/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist"
let disableOption = "-DisableSleepProxyClient" let disableOption = "-DisableSleepProxyClient"
var value = "false"
if let nvdata = nvram.object(forKey: "Clover.DisableSleepProxyClient") as? Data { if let nvdata = nvram.object(forKey: "Clover.DisableSleepProxyClient") as? Data {
let value = String(decoding: nvdata, as: UTF8.self) value = String(decoding: nvdata, as: UTF8.self)
print("Clover.DisableSleepProxyClient=\(value)") print("Clover.DisableSleepProxyClient=\(value)")
if !fm.fileExists(atPath: mDNSResponderPath) { } else {
print("Error: cannot found \(mDNSResponderPath)") print("Clover.DisableSleepProxyClient is not set.")
return }
}
if !fm.isWritableFile(atPath: "/") { if !fm.fileExists(atPath: mDNSResponderPath) {
print("Cannot go ahead as / is still read-only at this moment, will try again at power off.") print("Error: cannot found \(mDNSResponderPath)")
return return
} }
// check if enabled or disabled if !fm.isWritableFile(atPath: "/") {
if let mDNSResponder = NSDictionary(contentsOfFile: mDNSResponderPath) { print("Cannot go ahead as / is read-only")
if let ProgramArguments = mDNSResponder.object(forKey: "ProgramArguments") as? NSArray { return
var index : Int = -1 }
var serviceDisabled = false
for i in 0..<ProgramArguments.count { let toDisable : Bool = value == "true"
if let arg = ProgramArguments.object(at: i) as? String { // check if enabled or disabled
if arg == disableOption { if let mDNSResponder = NSDictionary(contentsOfFile: mDNSResponderPath) {
index = i if let ProgramArguments = mDNSResponder.object(forKey: "ProgramArguments") as? NSArray {
serviceDisabled = true var index : Int = -1
break var serviceIsDisabled = false
} for i in 0..<ProgramArguments.count {
if let arg = ProgramArguments.object(at: i) as? String {
if arg == disableOption {
index = i
serviceIsDisabled = true
break
} }
} }
}
if value == "true" && !serviceDisabled {
print("Trying to disable Sleep Proxy Client service as requested.") // no need to do anything if already as user wants.
let cmd = "/usr/libexec/PlistBuddy -c \"Add ProgramArguments: string \(disableOption)\" \(mDNSResponderPath)" if toDisable && serviceIsDisabled {
print("Sleep Proxy Client is already disabled.")
return
} else if !toDisable && !serviceIsDisabled {
print("Sleep Proxy Client is already enabled as default.")
return
}
if toDisable {
print("Trying to disable Sleep Proxy Client service.")
let cmd = "/usr/libexec/PlistBuddy -c \"Add ProgramArguments: string \(disableOption)\" \(mDNSResponderPath)"
run(cmd: cmd)
} else {
print("Trying to enable Sleep Proxy Client service as default.")
if index >= 0 {
let cmd = "/usr/libexec/PlistBuddy -c \"delete :ProgramArguments:\(index)\" \(mDNSResponderPath)"
run(cmd: cmd) run(cmd: cmd)
} else if value != "true" && serviceDisabled {
print("Trying to enable Sleep Proxy Client service as requested.")
if index >= 0 {
let cmd = "/usr/libexec/PlistBuddy -c \"delete :ProgramArguments:\(index)\" \(mDNSResponderPath)"
run(cmd: cmd)
} else {
print("Bug: cant find the index of '\(disableOption)'.\n")
}
} else {
print("Sleep Proxy Client \(serviceDisabled ? "disabled" : "enabled") as requested.")
} }
} }
} }
@ -109,7 +127,44 @@ func checkSleepProxyClient(nvram: NSDictionary) {
} }
func getLogOutHook() -> String? { func getLogOutHook() -> String? {
return NSDictionary(contentsOfFile: loginwindow)?.object(forKey: "LogoutHook") as? String return NSDictionary(contentsOfFile: loginWindowPath)?.object(forKey: "LogoutHook") as? String
}
func removeCloverRCScripts() {
if fm.fileExists(atPath: oldLaunchPlistPath) {
print("unloading old CloverDaemon..")
run(cmd: "launchctl unload \(oldLaunchPlistPath)")
try? fm.removeItem(atPath: oldLaunchPlistPath)
if fm.fileExists(atPath: "/Library/Application Support/Clover/CloverDaemon") {
try? fm.removeItem(atPath: "/Library/Application Support/Clover/CloverDaemon")
}
if fm.fileExists(atPath: "/Library/Application Support/Clover/CloverDaemon-stopservice") {
try? fm.removeItem(atPath: "/Library/Application Support/Clover/CloverDaemon-stopservice")
}
}
let oldRCScripts : [String] = ["/etc/rc.boot.d/10.save_and_rotate_boot_log.local",
"/etc/rc.boot.d/20.mount_ESP.local",
"/etc/rc.boot.d/70.disable_sleep_proxy_client.local.disabled",
"/etc/rc.boot.d/70.disable_sleep_proxy_client.local",
"/etc/rc.clover.lib",
"/etc/rc.shutdown.d/80.save_nvram_plist.local"];
for rc in oldRCScripts {
if fm.fileExists(atPath: rc) {
if !fm.isWritableFile(atPath: "/") {
run(cmd: "mount -uw /")
sleep(2)
}
print("Removing \(rc).")
do {
try fm.removeItem(atPath: rc)
} catch {
print(error)
}
}
}
} }
func main() { func main() {
@ -135,38 +190,7 @@ func main() {
} }
// check if old daemon exist // check if old daemon exist
let oldLaunchDaemon = "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist" removeCloverRCScripts()
if fm.fileExists(atPath: oldLaunchDaemon) {
print("unloading old CloverDaemon")
run(cmd: "launchctl unload \(oldLaunchDaemon)")
try? fm.removeItem(atPath: oldLaunchDaemon)
if fm.fileExists(atPath: "/Library/Application Support/Clover/CloverDaemon") {
try? fm.removeItem(atPath: "/Library/Application Support/Clover/CloverDaemon")
}
if fm.fileExists(atPath: "/Library/Application Support/Clover/CloverDaemon-stopservice") {
try? fm.removeItem(atPath: "/Library/Application Support/Clover/CloverDaemon-stopservice")
}
}
let oldRCScripts : [String] = ["/Library/Application Support/Clover/CloverDaemon-stopservice",
"/etc/rc.boot.d/10.save_and_rotate_boot_log.local",
"/etc/rc.boot.d/20.mount_ESP.local",
"/etc/rc.boot.d/70.disable_sleep_proxy_client.local.disabled",
"/etc/rc.boot.d/70.disable_sleep_proxy_client.local",
"/etc/rc.clover.lib",
"/etc/rc.shutdown.d/80.save_nvram_plist.local"];
if fm.fileExists(atPath: "/etc/rc.clover.lib") {
for rc in oldRCScripts {
print("Removing old rc scripts..")
run(cmd: "mount -uw /")
sleep(2)
if fm.fileExists(atPath: rc) {
try? fm.removeItem(atPath: rc)
}
}
}
/* /*
Clean some lines from clover.daemon.log. Clean some lines from clover.daemon.log.
@ -210,8 +234,7 @@ func main() {
} }
} }
} }
// using the logout Hook only if EmuVariableUefiPresent // using the logout Hook only if EmuVariableUefiPresent
let loh = getLogOutHook() let loh = getLogOutHook()
@ -220,12 +243,12 @@ func main() {
// if a hook exist and is not our one, then add a wrapper // if a hook exist and is not our one, then add a wrapper
if (loh != nil) { if (loh != nil) {
if loh! != lh && fm.fileExists(atPath: loh!) { if loh! != cloverLogOut && fm.fileExists(atPath: loh!) {
let wrapper = let wrapper =
""" """
#!/bin/sh #!/bin/sh
'\(lh)' '\(cloverLogOut)'
# This file is automatically generated by CloverDaemonNew because # This file is automatically generated by CloverDaemonNew because
# it has detected you added a logout script somewhere else. # it has detected you added a logout script somewhere else.
@ -248,10 +271,10 @@ func main() {
print(error) print(error)
} }
} else { } else {
run(cmd: "defaults write com.apple.loginwindow LogoutHook '\(lh)'") run(cmd: "defaults write com.apple.loginwindow LogoutHook '\(cloverLogOut)'")
} }
} else { } else {
run(cmd: "defaults write com.apple.loginwindow LogoutHook '\(lh)'") run(cmd: "defaults write com.apple.loginwindow LogoutHook '\(cloverLogOut)'")
} }
if !fm.isWritableFile(atPath: "/") { if !fm.isWritableFile(atPath: "/") {
@ -263,7 +286,7 @@ func main() {
} else { } else {
// what to do? remove the logout hook if it's our // what to do? remove the logout hook if it's our
if (loh != nil) { if (loh != nil) {
if loh! == lh { if loh! == cloverLogOut {
// it is CloverLogOut // it is CloverLogOut
print("Removing CloverLogOut hook as EmuVariable is no longer present.") print("Removing CloverLogOut hook as EmuVariable is no longer present.")
run(cmd: "defaults delete com.apple.loginwindow LogoutHook") run(cmd: "defaults delete com.apple.loginwindow LogoutHook")
@ -305,12 +328,15 @@ func main() {
/* /*
Clean old nvram.plist user may have in all volumes Clean old nvram.plist user may have in all volumes
Note: never delete in / as this will be done at shut down/restart Note: never delete in / as this will be done at shut down/restart
if the nvram is correctly saved somewhere else (e.g. in the ESP) if the nvram is correctly saved somewhere else (e.g. in the ESP).
Also don't delete nvram.plist from external devices as this is not or
shouldn't be our business.
*/ */
/*
for v in getVolumes() { for v in getVolumes() {
let nvramtPath = v.addPath("nvram.plist") let nvramtPath = v.addPath("nvram.plist")
if v != "/" { if v != "/" && isInternalDevice(diskOrMtp: v) {
if fm.fileExists(atPath: nvramtPath) { if fm.fileExists(atPath: nvramtPath) {
if fm.isDeletableFile(atPath: nvramtPath) { if fm.isDeletableFile(atPath: nvramtPath) {
do { do {
@ -325,7 +351,7 @@ func main() {
} }
} }
} }
*/
} else { } else {
print("Error: nvram not present in this System.") print("Error: nvram not present in this System.")
} }
@ -359,10 +385,11 @@ if CommandLine.arguments.contains("--install") {
launch.setValue("/Library/Logs/CloverEFI/clover.daemon.log", forKey: "StandardErrorPath") launch.setValue("/Library/Logs/CloverEFI/clover.daemon.log", forKey: "StandardErrorPath")
launch.setValue("/Library/Logs/CloverEFI/clover.daemon.log", forKey: "StandardOutPath") launch.setValue("/Library/Logs/CloverEFI/clover.daemon.log", forKey: "StandardOutPath")
let ProgramArguments = NSArray(object: "/Library/Application Support/Clover/CloverDaemonNew") let ProgramArguments = NSArray(object: cloverDaemonNewPath)
launch.setValue(ProgramArguments, forKey: "ProgramArguments") launch.setValue(ProgramArguments, forKey: "ProgramArguments")
removeCloverRCScripts()
do { do {
if !fm.fileExists(atPath: "/Library/Application Support/Clover") { if !fm.fileExists(atPath: "/Library/Application Support/Clover") {
try fm.createDirectory(atPath: "/Library/Application Support/Clover", try fm.createDirectory(atPath: "/Library/Application Support/Clover",
@ -370,41 +397,39 @@ if CommandLine.arguments.contains("--install") {
attributes: nil) attributes: nil)
} }
if fm.fileExists(atPath: "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") { if fm.fileExists(atPath: launchPlistPath) {
try fm.removeItem(atPath: "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") try fm.removeItem(atPath: launchPlistPath)
} }
if fm.fileExists(atPath: "/Library/Application Support/Clover/\(myName)") { if fm.fileExists(atPath: cloverDaemonNewPath) {
try fm.removeItem(atPath: "/Library/Application Support/Clover/\(myName)") try fm.removeItem(atPath: cloverDaemonNewPath)
} }
launch.write(toFile: "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist", launch.write(toFile: launchPlistPath, atomically: true)
atomically: true)
try fm.copyItem(atPath: myPath, toPath: "/Library/Application Support/Clover/\(myName)") try fm.copyItem(atPath: myPath, toPath: cloverDaemonNewPath)
try fm.setAttributes(execAttr(), try fm.setAttributes(execAttr(),
ofItemAtPath: "/Library/Application Support/Clover/\(myName)") ofItemAtPath: cloverDaemonNewPath)
let logouthookSrc = myPath.deletingLastPath.addPath("CloverLogOut") let logouthookSrc = myPath.deletingLastPath.addPath("CloverLogOut")
if fm.fileExists(atPath: lh) { if fm.fileExists(atPath: cloverLogOut) {
try fm.removeItem(atPath: lh) try fm.removeItem(atPath: cloverLogOut)
} }
if fm.fileExists(atPath: logouthookSrc) { if fm.fileExists(atPath: logouthookSrc) {
try fm.copyItem(atPath: logouthookSrc, try fm.copyItem(atPath: logouthookSrc,
toPath: lh) toPath: cloverLogOut)
try fm.setAttributes(execAttr(), try fm.setAttributes(execAttr(),
ofItemAtPath: lh) ofItemAtPath: cloverLogOut)
} }
try fm.setAttributes(launchAttr(), try fm.setAttributes(launchAttr(), ofItemAtPath: launchPlistPath)
ofItemAtPath: "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") if fm.fileExists(atPath: launchPlistPath) {
if fm.fileExists(atPath: "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") { run(cmd: "launchctl unload \(launchPlistPath)")
run(cmd: "launchctl unload /Library/LaunchDaemons/com.slice.CloverDaemonNew.plist")
} }
run(cmd: "launchctl load /Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") run(cmd: "launchctl load \(launchPlistPath)")
run(cmd: "launchctl start /Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") run(cmd: "launchctl start \(launchPlistPath)")
exit(EXIT_SUCCESS) exit(EXIT_SUCCESS)
} catch { } catch {
print(error) print(error)
@ -412,13 +437,21 @@ if CommandLine.arguments.contains("--install") {
} else if CommandLine.arguments.contains("--uninstall") { } else if CommandLine.arguments.contains("--uninstall") {
print("uninstalling daemon...") print("uninstalling daemon...")
do { do {
if fm.fileExists(atPath: "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") { if fm.fileExists(atPath: launchPlistPath) {
run(cmd: "launchctl unload /Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") run(cmd: "launchctl unload \(launchPlistPath)")
try fm.removeItem(atPath: "/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist") try fm.removeItem(atPath: launchPlistPath)
} }
if fm.fileExists(atPath: "/Library/Application Support/Clover/CloverDaemonNew") { if fm.fileExists(atPath: cloverDaemonNewPath) {
try fm.removeItem(atPath: "/Library/Application Support/Clover/CloverDaemonNew") try fm.removeItem(atPath: cloverDaemonNewPath)
}
if fm.fileExists(atPath: cloverLogOut) {
try fm.removeItem(atPath: cloverLogOut)
}
if fm.fileExists(atPath: wrapperPath) {
try fm.removeItem(atPath: wrapperPath)
} }
exit(EXIT_SUCCESS) exit(EXIT_SUCCESS)
} catch { } catch {

View File

@ -10,6 +10,7 @@ import Foundation
let cmdVersion = "1.0.2" let cmdVersion = "1.0.2"
let savedNVRAMPath = "/tmp/NVRAM_saved" let savedNVRAMPath = "/tmp/NVRAM_saved"
let NVRAMSavedToRoot = "/tmp/NVRAM_savedToRoot"
func log(_ str: String) { func log(_ str: String) {
let logUrl = URL(fileURLWithPath: "/Library/Logs/CloverEFI/clover.daemon.log") let logUrl = URL(fileURLWithPath: "/Library/Logs/CloverEFI/clover.daemon.log")
@ -75,6 +76,16 @@ func saveNVRAM(nvram: NSMutableDictionary, volume: String) {
log("\(error)") log("\(error)")
} }
} }
if fm.fileExists(atPath: NVRAMSavedToRoot) {
do {
try fm.removeItem(atPath: NVRAMSavedToRoot)
} catch {
log("\(error)")
}
}
} else {
try? "".write(toFile: NVRAMSavedToRoot, atomically: false, encoding: .utf8)
} }
} else { } else {
log("Error: nvram cannot be saved to \(volume) with UUID: \(uuid).") log("Error: nvram cannot be saved to \(volume) with UUID: \(uuid).")
@ -110,7 +121,20 @@ func main() {
if fm.fileExists(atPath: savedNVRAMPath) { if fm.fileExists(atPath: savedNVRAMPath) {
if let old = NSDictionary(contentsOfFile: savedNVRAMPath) { if let old = NSDictionary(contentsOfFile: savedNVRAMPath) {
if nvram.isEqual(to: old) { if nvram.isEqual(to: old) {
log("nvram not changed, nothing to do.") /*
We are going to exit but if the nvram is already saved
and is saved in the ESP, then remove /.nvram.plist
*/
if !fm.fileExists(atPath: NVRAMSavedToRoot) {
if fm.fileExists(atPath: "/nvram.plist") {
do {
try fm.removeItem(atPath: "/nvram.plist")
} catch {
log("\(error)")
}
}
}
log("nvram not changed, nothing to do.") // hope user didn't delete it :-)
log("- CloverLogOut: end at \(now)") log("- CloverLogOut: end at \(now)")
exit(EXIT_SUCCESS) exit(EXIT_SUCCESS)
} }