CloverBootloader/CloverApp/CloverLogOut/CloverLogOut/main.swift

213 lines
6.0 KiB
Swift

//
// main.swift
// CloverLogOut
//
// Created by vector sigma on 16/11/2019.
// Copyright © 2019 CloverHackyColor. All rights reserved.
//
import Foundation
let cmdVersion = "1.0.4"
let savedNVRAMPath = "/tmp/NVRAM_saved"
let NVRAMSavedToRoot = "/tmp/NVRAM_savedToRoot"
func log(_ str: String) {
let logUrl = URL(fileURLWithPath: "/Library/Logs/CloverEFI/clover.daemon.log")
if !fm.fileExists(atPath: "/Library/Logs/CloverEFI") {
try? fm.createDirectory(at: URL(fileURLWithPath: "/Library/Logs/CloverEFI"),
withIntermediateDirectories: false,
attributes: nil)
}
if !fm.fileExists(atPath: "/Library/Logs/CloverEFI/clover.daemon.log") {
try? "".write(to: logUrl, atomically: false, encoding: .utf8)
}
if let fh = try? FileHandle(forUpdating: logUrl) {
fh.seekToEndOfFile()
fh.write("\n\(str)".data(using: .utf8)!)
fh.closeFile()
}
}
func run(cmd: String) {
let task = Process()
if #available(OSX 10.13, *) {
task.executableURL = URL(fileURLWithPath: "/bin/bash")
} else {
task.launchPath = "/bin/bash"
}
task.environment = ProcessInfo.init().environment
task.arguments = ["-c", cmd]
task.launch()
}
func saveNVRAM(nvram: NSMutableDictionary, volume: String) {
let bsdname = getBSDName(of: volume) ?? ""
let uuid = getVolumeUUID(from: bsdname) ?? kNotAvailable
if nvram.write(toFile: volume.addPath("nvram.plist"), atomically: false) {
log("nvram correctly saved to \(volume) with UUID: \(uuid).")
nvram.write(toFile: savedNVRAMPath, atomically: false)
if volume != "/" {
if fm.fileExists(atPath: "/nvram.plist") {
do {
try fm.removeItem(atPath: "/nvram.plist")
} catch {
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 {
log("Error: nvram cannot be saved to \(volume) with UUID: \(uuid).")
}
}
func disableInsexing(for volume: String) {
if fm.fileExists(atPath: volume) {
var file = volume.addPath(".metadata_never_index")
if !fm.fileExists(atPath: file) {
try? "".write(toFile: file, atomically: false, encoding: .utf8)
}
file = volume.addPath(".Spotlight-V100")
if fm.fileExists(atPath: volume.addPath("")) {
try? fm.removeItem(atPath: file)
}
}
}
func main() {
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd hh:mm:ss"
df.locale = Locale(identifier: "en_US")
var now = df.string(from: Date())
log("- CloverLogOut v\(cmdVersion): logout begin at \(now)")
if let nvram = getNVRAM() {
// we already saved once? Check if the nvram is changed
if fm.fileExists(atPath: savedNVRAMPath) {
if let old = NSDictionary(contentsOfFile: savedNVRAMPath) {
if nvram.isEqual(to: old) {
/*
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)")
exit(EXIT_SUCCESS)
}
}
}
var disk : String? = nil
var espList = [String]()
/* find all internal ESP in the System as we don't want
to save the nvram in a USB pen drive (user will lost the nvram if not plugged in)
*/
for esp in getAllESPs() {
if isInternalDevice(diskOrMtp: esp) {
espList.append(esp)
}
}
// find the boot partition device and check if it is a ESP
if let bd = findBootPartitionDevice() {
if espList.contains(bd) {
// boot device is a ESP :-)
disk = bd
log("Detected ESP \(bd) as boot device.")
}
}
if (disk == nil) {
// boot device not found
if espList.count > 0 {
// we have an internal ESP, using that
disk = espList[0]
log("Will use ESP on \(disk!) as boot device is not found (or is not internal).")
} else {
// use root
disk = getBSDName(of: "/")
log("Will use / as nor the boot device nor an internal ESP was found.")
}
}
if (disk != nil) {
// get the mount point or mount it
var mounted : Bool = false
if let mp = getMountPoint(from: disk!) {
log("\(disk!) was already mounted.")
saveNVRAM(nvram: nvram, volume: mp)
if espList.contains(disk!) {
disableInsexing(for: mp)
}
return
}
if !mounted {
log("mounting \(disk!)..")
mount(disk: disk!, at: nil) { (result) in
if result == true {
sleep(1)
var attempts = 0
repeat {
attempts+=1
if let mp = getMountPoint(from: disk!) {
mounted = true
saveNVRAM(nvram: nvram, volume: mp)
if espList.contains(disk!) {
disableInsexing(for: mp)
}
sleep(1)
umount(disk: disk!, force: true)
break
}
} while (mounted || attempts == 5)
}
}
}
if !mounted {
log("mount failed for \(disk!).")
saveNVRAM(nvram: nvram, volume: "/")
}
} else {
// CloverDaemonNew should have made the fs read-write for us.
saveNVRAM(nvram: nvram, volume: "/")
}
} else {
log("Error: no nvram to be saved.")
}
now = df.string(from: Date())
log("- CloverLogOut: end at \(now)")
}
main()
exit(EXIT_SUCCESS)