Skip to content

Commit

Permalink
fix: Error code and description in some async methods
Browse files Browse the repository at this point in the history
chore: Use Swift OptionSet instead of C constants
  • Loading branch information
amosavian committed Oct 17, 2024
1 parent 1b64d4b commit 359f03c
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 134 deletions.
2 changes: 1 addition & 1 deletion AMSMB2/AMSMB2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ public class SMB2Manager: NSObject, NSSecureCoding, Codable, NSCopying, CustomRe
with(completionHandler: completionHandler) { context in
do {
try context.unlink(path)
} catch POSIXError.ENOLINK {
} catch POSIXError.ENOLINK, POSIXError.ENETRESET {
// Try to remove file as a symbolic link.
try context.unlink(path, flags: O_SYMLINK)
}
Expand Down
87 changes: 59 additions & 28 deletions AMSMB2/Context.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import SMB2

/// Provides synchronous operation on SMB2
final class SMB2Context: CustomDebugStringConvertible, CustomReflectable, @unchecked Sendable {
var unsafe: UnsafeMutablePointer<smb2_context>?
var unsafeContext: UnsafeMutablePointer<smb2_context>?
private var _context_lock = NSRecursiveLock()
var timeout: TimeInterval

init(timeout: TimeInterval) throws {
let _context = try smb2_init_context().unwrap()
self.unsafe = _context
self.unsafeContext = _context
self.timeout = timeout
}

Expand All @@ -27,7 +27,7 @@ final class SMB2Context: CustomDebugStringConvertible, CustomReflectable, @unche
try? self.disconnect()
}
try? withThreadSafeContext { context in
self.unsafe = nil
self.unsafeContext = nil
smb2_destroy_context(context)
}
}
Expand All @@ -39,7 +39,7 @@ final class SMB2Context: CustomDebugStringConvertible, CustomReflectable, @unche
defer {
_context_lock.unlock()
}
return try handler(unsafe.unwrap())
return try handler(unsafeContext.unwrap())
}

public var debugDescription: String {
Expand All @@ -48,7 +48,7 @@ final class SMB2Context: CustomDebugStringConvertible, CustomReflectable, @unche

public var customMirror: Mirror {
var c: [(label: String?, value: Any)] = []
if unsafe != nil {
if unsafeContext != nil {
c.append((label: "server", value: server!))
c.append((label: "securityMode", value: securityMode))
c.append((label: "authentication", value: authentication))
Expand All @@ -69,7 +69,7 @@ final class SMB2Context: CustomDebugStringConvertible, CustomReflectable, @unche
extension SMB2Context {
var workstation: String {
get {
(unsafe?.pointee.workstation).map(String.init(cString:)) ?? ""
(unsafeContext?.pointee.workstation).map(String.init(cString:)) ?? ""
}
set {
try? withThreadSafeContext { context in
Expand All @@ -80,7 +80,7 @@ extension SMB2Context {

var domain: String {
get {
(unsafe?.pointee.domain).map(String.init(cString:)) ?? ""
(unsafeContext?.pointee.domain).map(String.init(cString:)) ?? ""
}
set {
try? withThreadSafeContext { context in
Expand All @@ -91,7 +91,7 @@ extension SMB2Context {

var user: String {
get {
(unsafe?.pointee.user).map(String.init(cString:)) ?? ""
(unsafeContext?.pointee.user).map(String.init(cString:)) ?? ""
}
set {
try? withThreadSafeContext { context in
Expand All @@ -102,7 +102,7 @@ extension SMB2Context {

var password: String {
get {
(unsafe?.pointee.password).map(String.init(cString:)) ?? ""
(unsafeContext?.pointee.password).map(String.init(cString:)) ?? ""
}
set {
try? withThreadSafeContext { context in
Expand All @@ -113,7 +113,7 @@ extension SMB2Context {

var securityMode: NegotiateSigning {
get {
(unsafe?.pointee.security_mode).flatMap(NegotiateSigning.init(rawValue:)) ?? []
(unsafeContext?.pointee.security_mode).flatMap(NegotiateSigning.init(rawValue:)) ?? []
}
set {
try? withThreadSafeContext { context in
Expand All @@ -124,7 +124,7 @@ extension SMB2Context {

var seal: Bool {
get {
unsafe?.pointee.seal ?? 0 != 0
unsafeContext?.pointee.seal ?? 0 != 0
}
set {
try? withThreadSafeContext { context in
Expand All @@ -135,7 +135,7 @@ extension SMB2Context {

var authentication: Security {
get {
unsafe?.pointee.sec ?? SMB2_SEC_UNDEFINED
unsafeContext?.pointee.sec ?? SMB2_SEC_UNDEFINED
}
set {
try? withThreadSafeContext { context in
Expand All @@ -145,23 +145,23 @@ extension SMB2Context {
}

var clientGuid: UUID? {
guard let guid = try? smb2_get_client_guid(unsafe.unwrap()) else {
guard let guid = try? smb2_get_client_guid(unsafeContext.unwrap()) else {
return nil
}
let uuid = UnsafeRawPointer(guid).assumingMemoryBound(to: uuid_t.self).pointee
return UUID(uuid: uuid)
}

var server: String? {
unsafe?.pointee.server.map(String.init(cString:))
unsafeContext?.pointee.server.map(String.init(cString:))
}

var share: String? {
unsafe?.pointee.share.map(String.init(cString:))
unsafeContext?.pointee.share.map(String.init(cString:))
}

var version: Version {
(unsafe?.pointee.dialect).map { Version(rawValue: UInt32($0)) } ?? .any
(unsafeContext?.pointee.dialect).map { Version(rawValue: UInt32($0)) } ?? .any
}

var isConnected: Bool {
Expand All @@ -170,28 +170,39 @@ extension SMB2Context {

var fileDescriptor: Int32 {
do {
return try smb2_get_fd(unsafe.unwrap())
return try smb2_get_fd(unsafeContext.unwrap())
} catch {
return -1
}
}

var error: String? {
let errorStr = smb2_get_error(unsafe)
return errorStr.map(String.init(cString:))
smb2_get_error(unsafeContext).map(String.init(cString:))
}

var ntError: NTStatus {
.init(rawValue: smb2_get_nterror(unsafeContext))
}

var errno: Int32 {
ntError.posixErrorCode.rawValue
}

var maximumTransactionSize: Int {
(unsafeContext?.pointee.max_transact_size).map(Int.init) ?? 65535
}

func whichEvents() throws -> Int16 {
try Int16(truncatingIfNeeded: smb2_which_events(unsafe.unwrap()))
try Int16(truncatingIfNeeded: smb2_which_events(unsafeContext.unwrap()))
}

func service(revents: Int32) throws {
let result = smb2_service(unsafe, revents)
let result = smb2_service(unsafeContext, revents)
if result < 0 {
unsafe = nil
smb2_destroy_context(unsafe)
smb2_destroy_context(unsafeContext)
unsafeContext = nil
try POSIXError.throwIfError(result, description: error)
}
try POSIXError.throwIfError(result, description: error)
}
}

Expand Down Expand Up @@ -474,15 +485,15 @@ extension SMB2Context {
struct NegotiateSigning: OptionSet {
var rawValue: UInt16

static let enabled = NegotiateSigning(.init(SMB2_NEGOTIATE_SIGNING_ENABLED))
static let required = NegotiateSigning(.init(SMB2_NEGOTIATE_SIGNING_REQUIRED))
static let enabled = NegotiateSigning(rawValue: SMB2_NEGOTIATE_SIGNING_ENABLED)
static let required = NegotiateSigning(rawValue: SMB2_NEGOTIATE_SIGNING_REQUIRED)
}

typealias Version = smb2_negotiate_version
typealias Security = smb2_sec
}

extension smb2_negotiate_version: Swift.Hashable {
extension SMB2.smb2_negotiate_version: Swift.Hashable {
static let any = SMB2_VERSION_ANY
static let v2 = SMB2_VERSION_ANY2
static let v3 = SMB2_VERSION_ANY3
Expand All @@ -501,7 +512,7 @@ extension smb2_negotiate_version: Swift.Hashable {
}
}

extension smb2_sec {
extension SMB2.smb2_sec: Swift.Hashable {
static let undefined = SMB2_SEC_UNDEFINED
static let ntlmSsp = SMB2_SEC_NTLMSSP
static let kerberos5 = SMB2_SEC_KRB5
Expand Down Expand Up @@ -539,3 +550,23 @@ struct ShareProperties: RawRepresentable {
rawValue & SHARE_TYPE_HIDDEN != 0
}
}

struct NTStatus: LocalizedError {
let rawValue: UInt32

init(rawValue: UInt32) {
self.rawValue = rawValue
}

init(rawValue: Int32) {
self.rawValue = .init(bitPattern: rawValue)
}

var errorDescription: String? {
nterror_to_str(rawValue).map(String.init(cString:))
}

var posixErrorCode: POSIXErrorCode {
.init(nterror_to_errno(rawValue))
}
}
27 changes: 15 additions & 12 deletions AMSMB2/Directory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ typealias smb2dir = OpaquePointer

/// - Note: This class is NOT thread-safe.
final class SMB2Directory: Collection {
private var context: SMB2Context
private var handle: smb2dir
private let context: SMB2Context
private let handle: smb2dir

init(_ path: String, on context: SMB2Context) throws {
let (_, handle) = try context.async_await(dataHandler: OpaquePointer.init) {
context, cbPtr -> Int32 in
smb2_opendir_async(context, path, SMB2Context.generic_handler, cbPtr)
// Due to a unexpected free in closedir, async version is not usable.
let handle = try context.withThreadSafeContext { context in
smb2_opendir(context, path)
}

self.context = context
guard let handle = handle, unsafeBitCast(handle, to: UInt.self) & 0xffffff00 != 0 else {
throw POSIXError(context.ntError.posixErrorCode, description: context.error)
}

self.handle = handle
self.context = context
}

deinit {
Expand All @@ -35,11 +38,11 @@ final class SMB2Directory: Collection {
}

func makeIterator() -> AnyIterator<smb2dirent> {
let context = context.unsafe
let context = context.unsafeContext
let handle = handle
smb2_rewinddir(context, handle)
return AnyIterator {
smb2_readdir(context, self.handle)?.pointee
smb2_readdir(context, handle)?.pointee
}
}

Expand All @@ -52,7 +55,7 @@ final class SMB2Directory: Collection {
}

var count: Int {
let context = context.unsafe
let context = context.unsafeContext
let handle = handle
let currentPos = smb2_telldir(context, handle)
defer {
Expand All @@ -68,14 +71,14 @@ final class SMB2Directory: Collection {
}

subscript(_: Int) -> smb2dirent {
let context = context.unsafe
let context = context.unsafeContext
let handle = handle
let currentPos = smb2_telldir(context, handle)
smb2_seekdir(context, handle, 0)
defer {
smb2_seekdir(context, handle, currentPos)
}
return smb2_readdir(context, handle).move()
return smb2_readdir(context, handle).pointee
}

func index(after i: Int) -> Int {
Expand Down
2 changes: 1 addition & 1 deletion AMSMB2/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ extension POSIXError {

init(_ code: POSIXError.Code, description: String?) {
let userInfo: [String: Any] =
description.map { [NSLocalizedFailureReasonErrorKey: $0] } ?? [:]
description.map { [NSLocalizedDescriptionKey: $0] } ?? [:]
self = POSIXError(code, userInfo: userInfo)
}
}
Expand Down
Loading

0 comments on commit 359f03c

Please sign in to comment.