Update LoopbackFS-Swift for macFUSE 5
This commit is contained in:
parent
b0fd1fed0d
commit
5878beace5
|
|
@ -1,5 +1,5 @@
|
|||
Copyright 2017 KF Interactive GmbH
|
||||
Copyright 2018-2023 Benjamin Fleischer
|
||||
Copyright 2018-2025 Benjamin Fleischer
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
|
|
|||
|
|
@ -233,6 +233,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CODE_SIGN_FLAGS = "--timestamp";
|
||||
|
|
@ -287,6 +288,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CODE_SIGN_FLAGS = "--timestamp";
|
||||
SDKROOT = macosx;
|
||||
|
|
@ -312,7 +314,6 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "io.macfuse.demo.loopbackfs-swift";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -338,7 +339,6 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "io.macfuse.demo.loopbackfs-swift";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
|
|||
|
|
@ -4,16 +4,15 @@
|
|||
//
|
||||
// Created by Gunnar Herzog on 27/01/2017.
|
||||
// Copyright © 2017 KF Interactive GmbH. All rights reserved.
|
||||
// Copyright © 2019-2023 Benjamin Fleischer. All rights reserved.
|
||||
// Copyright © 2019-2025 Benjamin Fleischer. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
let loopbackMountPath = "/Volumes/loop"
|
||||
|
||||
@NSApplicationMain
|
||||
@main
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
@IBOutlet weak var window: NSWindow!
|
||||
|
||||
private var notificationObservers: [NSObjectProtocol] = []
|
||||
|
|
@ -24,7 +23,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
|
||||
private var userFileSystem: GMUserFileSystem?
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
let panel = NSOpenPanel()
|
||||
panel.canChooseFiles = false
|
||||
panel.canChooseDirectories = true
|
||||
|
|
@ -45,10 +44,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
}
|
||||
|
||||
userFileSystem = GMUserFileSystem(delegate: self.loopFileSystem, isThreadSafe: false)
|
||||
|
||||
|
||||
// Do not use the 'native_xattr' mount-time option unless the underlying
|
||||
// file system supports native extended attributes. Typically, the user
|
||||
// would be mounting an HFS+ directory through LoopbackFS, so we do want
|
||||
// would be mounting an APFS directory through LoopbackFS, so we do want
|
||||
// this option in that case.
|
||||
userFileSystem!.mount(atPath: loopbackMountPath, withOptions: options)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,22 +4,21 @@
|
|||
//
|
||||
// Created by Gunnar Herzog on 27/01/2017.
|
||||
// Copyright © 2017 KF Interactive GmbH. All rights reserved.
|
||||
// Copyright © 2019-2020 Benjamin Fleischer. All rights reserved.
|
||||
// Copyright © 2019-2025 Benjamin Fleischer. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
final class LoopbackFS: NSObject {
|
||||
public final class LoopbackFS: NSObject {
|
||||
private let rootPath: String
|
||||
|
||||
let rootPath: String
|
||||
|
||||
init(rootPath: String) {
|
||||
public init(rootPath: String) {
|
||||
self.rootPath = rootPath
|
||||
}
|
||||
|
||||
// MARK: - Moving an Item
|
||||
|
||||
override func moveItem(atPath source: String!, toPath destination: String!, options: GMUserFileSystemMoveOption) throws {
|
||||
public override func moveItem(atPath source: String, toPath destination: String, options: GMUserFileSystemMoveOption) throws {
|
||||
let sourcePath = (rootPath.appending(source) as NSString).utf8String!
|
||||
let destinationPath = (rootPath.appending(destination) as NSString).utf8String!
|
||||
|
||||
|
|
@ -47,7 +46,7 @@ final class LoopbackFS: NSObject {
|
|||
|
||||
// MARK: - Removing an Item
|
||||
|
||||
override func removeDirectory(atPath path: String!) throws {
|
||||
public override func removeDirectory(atPath path: String) throws {
|
||||
// We need to special-case directories here and use the bsd API since
|
||||
// NSFileManager will happily do a recursive remove :-(
|
||||
|
||||
|
|
@ -59,7 +58,7 @@ final class LoopbackFS: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
override func removeItem(atPath path: String!) throws {
|
||||
public override func removeItem(atPath path: String) throws {
|
||||
let originalPath = rootPath.appending(path)
|
||||
|
||||
return try FileManager.default.removeItem(atPath: originalPath)
|
||||
|
|
@ -67,15 +66,13 @@ final class LoopbackFS: NSObject {
|
|||
|
||||
// MARK: - Creating an Item
|
||||
|
||||
override func createDirectory(atPath path: String!, attributes: [AnyHashable : Any]! = [:]) throws {
|
||||
guard let attributes = attributes as? [String: Any] else { throw NSError(posixErrorCode: EPERM) }
|
||||
|
||||
public override func createDirectory(atPath path: String, attributes: [FileAttributeKey : Any] = [:]) throws {
|
||||
let originalPath = rootPath.appending(path)
|
||||
|
||||
try FileManager.default.createDirectory(atPath: originalPath, withIntermediateDirectories: false, attributes: convertToOptionalFileAttributeKeyDictionary(attributes))
|
||||
try FileManager.default.createDirectory(atPath: originalPath, withIntermediateDirectories: false, attributes: attributes)
|
||||
}
|
||||
|
||||
override func createFile(atPath path: String!, attributes: [AnyHashable : Any]! = [:], flags: Int32, userData: AutoreleasingUnsafeMutablePointer<AnyObject?>!) throws {
|
||||
public override func createFile(atPath path: String, attributes: [FileAttributeKey : Any], flags: Int32, userData: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
|
||||
|
||||
guard let mode = attributes[FileAttributeKey.posixPermissions] as? mode_t else {
|
||||
throw NSError(posixErrorCode: EPERM)
|
||||
|
|
@ -94,7 +91,7 @@ final class LoopbackFS: NSObject {
|
|||
|
||||
// MARK: - Linking an Item
|
||||
|
||||
override func linkItem(atPath path: String!, toPath otherPath: String!) throws {
|
||||
public override func linkItem(atPath path: String, toPath otherPath: String) throws {
|
||||
let originalPath = (rootPath.appending(path) as NSString).utf8String!
|
||||
let originalOtherPath = (rootPath.appending(otherPath) as NSString).utf8String!
|
||||
|
||||
|
|
@ -107,19 +104,19 @@ final class LoopbackFS: NSObject {
|
|||
|
||||
// MARK: - Symbolic Links
|
||||
|
||||
override func createSymbolicLink(atPath path: String!, withDestinationPath otherPath: String!) throws {
|
||||
public override func createSymbolicLink(atPath path: String, withDestinationPath otherPath: String) throws {
|
||||
let sourcePath = rootPath.appending(path)
|
||||
try FileManager.default.createSymbolicLink(atPath: sourcePath, withDestinationPath: otherPath)
|
||||
}
|
||||
|
||||
override func destinationOfSymbolicLink(atPath path: String!) throws -> String {
|
||||
public override func destinationOfSymbolicLink(atPath path: String) throws -> String {
|
||||
let sourcePath = rootPath.appending(path)
|
||||
return try FileManager.default.destinationOfSymbolicLink(atPath: sourcePath)
|
||||
}
|
||||
|
||||
// MARK: - File Contents
|
||||
|
||||
override func openFile(atPath path: String!, mode: Int32, userData: AutoreleasingUnsafeMutablePointer<AnyObject?>!) throws {
|
||||
public override func openFile(atPath path: String, mode: Int32, userData: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
|
||||
let originalPath = (rootPath.appending(path) as NSString).utf8String!
|
||||
|
||||
let fileDescriptor = open(originalPath, mode)
|
||||
|
|
@ -131,7 +128,7 @@ final class LoopbackFS: NSObject {
|
|||
userData.pointee = NSNumber(value: fileDescriptor)
|
||||
}
|
||||
|
||||
override func releaseFile(atPath path: String!, userData: Any!) {
|
||||
public override func releaseFile(atPath path: String, userData: Any!) {
|
||||
guard let num = userData as? NSNumber else {
|
||||
return
|
||||
}
|
||||
|
|
@ -140,7 +137,7 @@ final class LoopbackFS: NSObject {
|
|||
close(fileDescriptor)
|
||||
}
|
||||
|
||||
override func readFile(atPath path: String!, userData: Any!, buffer: UnsafeMutablePointer<Int8>!, size: Int, offset: off_t, error: NSErrorPointer) -> Int32 {
|
||||
public override func readFile(atPath path: String, userData: Any?, buffer: UnsafeMutablePointer<Int8>, size: Int, offset: off_t, error: NSErrorPointer) -> Int32 {
|
||||
guard let num = userData as? NSNumber else {
|
||||
error?.pointee = NSError(posixErrorCode: EBADF)
|
||||
return -1
|
||||
|
|
@ -156,7 +153,7 @@ final class LoopbackFS: NSObject {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override func writeFile(atPath path: String!, userData: Any!, buffer: UnsafePointer<Int8>!, size: Int, offset: off_t, error: NSErrorPointer) -> Int32 {
|
||||
public override func writeFile(atPath path: String, userData: Any?, buffer: UnsafePointer<Int8>, size: Int, offset: off_t, error: NSErrorPointer) -> Int32 {
|
||||
guard let num = userData as? NSNumber else {
|
||||
error?.pointee = NSError(posixErrorCode: EBADF)
|
||||
return -1
|
||||
|
|
@ -171,7 +168,7 @@ final class LoopbackFS: NSObject {
|
|||
return Int32(returnValue)
|
||||
}
|
||||
|
||||
override func preallocateFile(atPath path: String!, userData: Any!, options: Int32, offset: off_t, length: off_t) throws {
|
||||
public override func preallocateFile(atPath path: String, userData: Any!, options: Int32, offset: off_t, length: off_t) throws {
|
||||
guard let num = userData as? NSNumber else {
|
||||
throw NSError(posixErrorCode: EBADF)
|
||||
}
|
||||
|
|
@ -197,7 +194,7 @@ final class LoopbackFS: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
public override func exchangeDataOfItem(atPath path1: String!, withItemAtPath path2: String!) throws {
|
||||
public override func exchangeDataOfItem(atPath path1: String, withItemAtPath path2: String) throws {
|
||||
let sourcePath = (rootPath.appending(path1) as NSString).utf8String!
|
||||
let destinationPath = (rootPath.appending(path2) as NSString).utf8String!
|
||||
|
||||
|
|
@ -209,19 +206,30 @@ final class LoopbackFS: NSObject {
|
|||
|
||||
// MARK: - Directory Contents
|
||||
|
||||
override func contentsOfDirectory(atPath path: String!) throws -> [Any] {
|
||||
public override func contentsOfDirectory(atPath path: String, includingAttributesForKeys keys: [FileAttributeKey]) throws -> [GMDirectoryEntry] {
|
||||
let originalPath = rootPath.appending(path)
|
||||
return try FileManager.default.contentsOfDirectory(atPath: originalPath)
|
||||
let contents = try FileManager.default.contentsOfDirectory(atPath: originalPath)
|
||||
|
||||
var entries = [GMDirectoryEntry]()
|
||||
for name in contents {
|
||||
do {
|
||||
let attributes = try FileManager.default.attributesOfItem(atPath: originalPath.appending("/\(name)"))
|
||||
entries.append(GMDirectoryEntry(name: name, attributes: attributes))
|
||||
} catch {
|
||||
// Skip entry
|
||||
}
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
// MARK: - Getting and Setting Attributes
|
||||
|
||||
override func attributesOfItem(atPath path: String!, userData: Any!) throws -> [AnyHashable : Any] {
|
||||
public override func attributesOfItem(atPath path: String, userData: Any?) throws -> [FileAttributeKey : Any] {
|
||||
let originalPath = rootPath.appending(path)
|
||||
return try FileManager.default.attributesOfItem(atPath: originalPath)
|
||||
}
|
||||
|
||||
override func attributesOfFileSystem(forPath path: String!) throws -> [AnyHashable : Any] {
|
||||
public override func attributesOfFileSystem(forPath path: String) throws -> [FileAttributeKey : Any] {
|
||||
let originalPath = rootPath.appending(path)
|
||||
|
||||
var attributes = try FileManager.default.attributesOfFileSystem(forPath: originalPath)
|
||||
|
|
@ -242,20 +250,18 @@ final class LoopbackFS: NSObject {
|
|||
return attributes
|
||||
}
|
||||
|
||||
override func setAttributes(_ attributes: [AnyHashable : Any]!, ofItemAtPath path: String!, userData: Any!) throws {
|
||||
guard let attribs = attributes as? [FileAttributeKey: Any] else { throw NSError(posixErrorCode: EINVAL) }
|
||||
|
||||
public override func setAttributes(_ attributes: [FileAttributeKey : Any], ofItemAtPath path: String, userData: Any?) throws {
|
||||
let originalPath = rootPath.appending(path)
|
||||
|
||||
if let pathPointer = (originalPath as NSString).utf8String {
|
||||
if let offset = attributes[FileAttributeKey.size.rawValue] as? Int64 {
|
||||
if let offset = attributes[FileAttributeKey.size] as? Int64 {
|
||||
let ret = truncate(pathPointer, offset)
|
||||
if ret < 0 {
|
||||
throw NSError(posixErrorCode: errno)
|
||||
}
|
||||
}
|
||||
|
||||
if let flags = attributes[kGMUserFileSystemFileFlagsKey] as? Int32 {
|
||||
if let flags = attributes[FileAttributeKey(rawValue: kGMUserFileSystemFileFlagsKey)] as? Int32 {
|
||||
let rc = chflags(pathPointer, UInt32(flags))
|
||||
if rc < 0 {
|
||||
throw NSError(posixErrorCode: errno)
|
||||
|
|
@ -263,20 +269,16 @@ final class LoopbackFS: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
try FileManager.default.setAttributes(attribs, ofItemAtPath: originalPath)
|
||||
try FileManager.default.setAttributes(attributes, ofItemAtPath: originalPath)
|
||||
}
|
||||
|
||||
override func setAttributes(_ attributes: [AnyHashable : Any]!, ofFileSystemAtPath path: String!) throws {
|
||||
public override func setAttributes(_ attributes: [FileAttributeKey : Any], ofFileSystemAtPath path: String) throws {
|
||||
// Needed for kGMUserFileSystemVolumeSupportsSetVolumeNameKey
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Extended Attributes
|
||||
|
||||
public override func extendedAttributesOfItem(atPath path: Any!) throws -> [Any] {
|
||||
guard let path = path as? String else {
|
||||
throw NSError(posixErrorCode: ENODEV)
|
||||
}
|
||||
|
||||
public override func extendedAttributesOfItem(atPath path: String) throws -> [String] {
|
||||
let originalUrl = URL(fileURLWithPath: rootPath.appending(path))
|
||||
|
||||
return try originalUrl.withUnsafeFileSystemRepresentation { fileSystemPath -> [String] in
|
||||
|
|
@ -301,7 +303,7 @@ final class LoopbackFS: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
public override func value(ofExtendedAttribute name: String!, ofItemAtPath path: String!, position: off_t) throws -> Data {
|
||||
public override func value(ofExtendedAttribute name: String, ofItemAtPath path: String, position: off_t) throws -> Data {
|
||||
let originalUrl = URL(fileURLWithPath: rootPath.appending(path))
|
||||
|
||||
return try originalUrl.withUnsafeFileSystemRepresentation { fileSystemPath -> Data in
|
||||
|
|
@ -327,7 +329,7 @@ final class LoopbackFS: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
public override func setExtendedAttribute(_ name: String!, ofItemAtPath path: String!, value: Data!, position: off_t, options: Int32) throws {
|
||||
public override func setExtendedAttribute(_ name: String, ofItemAtPath path: String, value: Data, position: off_t, options: Int32) throws {
|
||||
let originalUrl = URL(fileURLWithPath: rootPath.appending(path))
|
||||
|
||||
try originalUrl.withUnsafeFileSystemRepresentation { fileSystemPath in
|
||||
|
|
@ -344,7 +346,7 @@ final class LoopbackFS: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
public override func removeExtendedAttribute(_ name: String!, ofItemAtPath path: String!) throws {
|
||||
public override func removeExtendedAttribute(_ name: String, ofItemAtPath path: String) throws {
|
||||
let originalUrl = URL(fileURLWithPath: rootPath.appending(path))
|
||||
|
||||
try originalUrl.withUnsafeFileSystemRepresentation { fileSystemPath in
|
||||
|
|
@ -353,9 +355,3 @@ final class LoopbackFS: NSObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function inserted by Swift 4.2 migrator.
|
||||
fileprivate func convertToOptionalFileAttributeKeyDictionary(_ input: [String: Any]?) -> [FileAttributeKey: Any]? {
|
||||
guard let input = input else { return nil }
|
||||
return Dictionary(uniqueKeysWithValues: input.map { key, value in (FileAttributeKey(rawValue: key), value)})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue