119 lines
3.7 KiB
Swift
119 lines
3.7 KiB
Swift
|
//
|
||
|
// UtilityMethods.swift
|
||
|
// UnzipKit
|
||
|
//
|
||
|
// Created by Dov Frankel on 6/7/17.
|
||
|
// Copyright © 2017 Abbey Code. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
|
||
|
#if os(OSX)
|
||
|
|
||
|
public enum FileSystem: String {
|
||
|
case HFS = "HFS+"
|
||
|
case APFS = "APFS"
|
||
|
}
|
||
|
|
||
|
public func createAndMountDMG(path dmgURL: URL, source: URL, fileSystem: FileSystem) -> URL? {
|
||
|
let task = Process()
|
||
|
task.launchPath = "/usr/bin/hdiutil"
|
||
|
|
||
|
var args = ["create",
|
||
|
"-fs", fileSystem.rawValue]
|
||
|
|
||
|
switch fileSystem {
|
||
|
case .HFS:
|
||
|
args += ["-format", "UDRW",
|
||
|
"-srcfolder", source.path]
|
||
|
break;
|
||
|
|
||
|
case .APFS:
|
||
|
args += ["-size", "100m"]
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
args += ["-volname", dmgURL.deletingPathExtension().lastPathComponent,
|
||
|
"-attach", "-plist",
|
||
|
// "-verbose",
|
||
|
dmgURL.path]
|
||
|
|
||
|
task.arguments = args
|
||
|
|
||
|
let outputPipe = Pipe()
|
||
|
task.standardOutput = outputPipe
|
||
|
|
||
|
let errorPipe = Pipe()
|
||
|
task.standardError = errorPipe
|
||
|
|
||
|
let inputPipe = Pipe()
|
||
|
task.standardInput = inputPipe
|
||
|
inputPipe.fileHandleForWriting.write("y\n".data(using: String.Encoding.utf8)!)
|
||
|
|
||
|
task.launch()
|
||
|
task.waitUntilExit()
|
||
|
|
||
|
let readHandle = outputPipe.fileHandleForReading
|
||
|
let outputData = readHandle.readDataToEndOfFile()
|
||
|
|
||
|
guard task.terminationStatus == 0 else {
|
||
|
let errorHandle = errorPipe.fileHandleForReading
|
||
|
let errorData = errorHandle.readDataToEndOfFile()
|
||
|
|
||
|
let outputString = String(data: outputData, encoding: String.Encoding.utf8)!
|
||
|
let errorString = String(data: errorData, encoding: String.Encoding.utf8)!
|
||
|
|
||
|
NSLog("Failed to create and mount DMG: \(dmgURL.path)\n\n\toutput: \(outputString)\n\nerror: \(errorString)");
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
let outputPlist = try! PropertyListSerialization.propertyList(from: outputData,
|
||
|
options: [],
|
||
|
format: nil)
|
||
|
as! [String: Any]
|
||
|
|
||
|
let entities = outputPlist["system-entities"] as! [[String:AnyObject]]
|
||
|
let mountPoint: URL
|
||
|
|
||
|
switch fileSystem {
|
||
|
case .HFS:
|
||
|
let hfsEntry = entities.filter{ $0["content-hint"] as! String == "Apple_HFS" }.first!
|
||
|
let mountPointPath = hfsEntry["mount-point"] as! String
|
||
|
mountPoint = URL(fileURLWithPath: mountPointPath)
|
||
|
break;
|
||
|
|
||
|
case .APFS:
|
||
|
let mountPointEntry = entities.filter{ $0.contains { (k, v) in k == "mount-point" } }.first!
|
||
|
let mountPointPath = mountPointEntry["mount-point"] as! String
|
||
|
mountPoint = URL(fileURLWithPath: mountPointPath)
|
||
|
|
||
|
// Need to copy the folder's contents in, since -srcfolder doesn't work. Reportedly fixed in 10.13
|
||
|
let folderContents = try! FileManager.default.contentsOfDirectory(at: source, includingPropertiesForKeys: nil, options: FileManager.DirectoryEnumerationOptions(rawValue: 0))
|
||
|
for sourceItemURL in folderContents {
|
||
|
let sourceItemPathRelativeToSource = sourceItemURL.path.replacingOccurrences(of: source.path, with: "")
|
||
|
let destinationURL = mountPoint.appendingPathComponent(sourceItemPathRelativeToSource)
|
||
|
try! FileManager.default.copyItem(at: sourceItemURL, to: destinationURL)
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
return mountPoint
|
||
|
}
|
||
|
|
||
|
|
||
|
public func unmountDMG(URL mountPoint: URL) {
|
||
|
let task = Process()
|
||
|
task.launchPath = "/usr/bin/hdiutil"
|
||
|
task.arguments = ["detach", mountPoint.path]
|
||
|
|
||
|
task.launch()
|
||
|
task.waitUntilExit()
|
||
|
|
||
|
if task.terminationStatus != 0 {
|
||
|
NSLog("Failed to unmount DMG: \(mountPoint)");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|