Skip to content

Commit d2fe787

Browse files
authored
Re-implement children(inPath:recursive) (#123)
On macOS 10.15.4, accessing data structure returned by `scandir` occassionally returns a mysterious `SIGSEGV (Address boundary error)`. Replace it with opendir/readdir/closedir instead to mitigate this problem. Closes #122
1 parent 1c87529 commit d2fe787

File tree

1 file changed

+9
-18
lines changed

1 file changed

+9
-18
lines changed

Sources/Pathos/children.swift

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,19 @@ import Darwin
1717
/// - SeeAlso: To work with `Path` or `PathRepresentable`, use `PathRepresentable.children(recursive:)`.
1818
public func children(inPath path: String, recursive: Bool = false) throws -> [(String, FileType)] {
1919
var result = [(String, FileType)]()
20-
let bufferPointer = UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<dirent>?>?>.allocate(capacity: 0)
21-
#if os(Linux)
22-
let sorting: @convention(c) (UnsafeMutablePointer<UnsafePointer<dirent>?>?, UnsafeMutablePointer<UnsafePointer<dirent>?>?) -> Int32 = { p0, p1 in
23-
return alphasort(p0!, p1!)
20+
guard let streamPtr = opendir(path) else {
21+
throw SystemError(posixErrorCode: errno)
2422
}
2523

26-
let count = Int(scandir(path, bufferPointer, nil, sorting))
27-
#else
28-
let count = Int(scandir(path, bufferPointer, nil, alphasort))
29-
#endif
30-
if count == -1 {
31-
throw SystemError(posixErrorCode: errno)
24+
defer {
25+
closedir(streamPtr)
3226
}
3327

34-
result.reserveCapacity(count)
35-
let buffer = UnsafeBufferPointer(start: bufferPointer.pointee, count: Int(count))
36-
for d in buffer {
37-
guard let entry = d?.pointee,
38-
let name = withUnsafeBytes(of: entry.d_name, {
39-
$0.bindMemory(to: Int8.self).baseAddress.map(String.init(cString:))
40-
}),
28+
while let entryPtr = readdir(streamPtr) {
29+
let entry = entryPtr.pointee
30+
guard let name = withUnsafeBytes(of: entry.d_name, {
31+
$0.bindMemory(to: Int8.self).baseAddress.map(String.init(cString:))
32+
}),
4133
name != ".." && name != "."
4234
else
4335
{
@@ -53,7 +45,6 @@ public func children(inPath path: String, recursive: Bool = false) throws -> [(S
5345
}
5446
}
5547

56-
free(bufferPointer)
5748
return result
5849
}
5950

0 commit comments

Comments
 (0)