Skip to content

Commit

Permalink
Android: add better nullability checks for nullability annotations ad…
Browse files Browse the repository at this point in the history
…ded in NDK 26
  • Loading branch information
finagolfin committed Dec 1, 2023
1 parent 9f011c6 commit cd1e20d
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 17 deletions.
6 changes: 6 additions & 0 deletions Sources/Foundation/FileHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,15 @@ open class FileHandle : NSObject {
let data = mmap(nil, mapSize, PROT_READ, MAP_PRIVATE, _fd, 0)
// Swift does not currently expose MAP_FAILURE
if data != UnsafeMutableRawPointer(bitPattern: -1) {
#if os(Android)
return NSData.NSDataReadResult(bytes: data, length: mapSize) { buffer, length in
munmap(buffer, length)
}
#else
return NSData.NSDataReadResult(bytes: data!, length: mapSize) { buffer, length in
munmap(buffer, length)
}
#endif
}
}

Expand Down
34 changes: 24 additions & 10 deletions Sources/Foundation/FileManager+POSIX.swift
Original file line number Diff line number Diff line change
Expand Up @@ -741,32 +741,38 @@ extension FileManager {
if rmdir(fsRep) == 0 {
return
} else if errno == ENOTEMPTY {
#if os(Android)
let ps = UnsafeMutablePointer<UnsafeMutablePointer<Int8>>.allocate(capacity: 2)
ps.initialize(to: UnsafeMutablePointer(mutating: fsRep))
ps.advanced(by: 1).initialize(to: unsafeBitCast(0, to: UnsafeMutablePointer<Int8>.self))
#else
let ps = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: 2)
ps.initialize(to: UnsafeMutablePointer(mutating: fsRep))
ps.advanced(by: 1).initialize(to: nil)
#endif
let stream = fts_open(ps, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil)
ps.deinitialize(count: 2)
ps.deallocate()

if stream != nil {
if let openStream = stream {
defer {
fts_close(stream)
fts_close(openStream)
}

while let current = fts_read(stream)?.pointee {
let itemPath = string(withFileSystemRepresentation: current.fts_path, length: Int(current.fts_pathlen))
while let current = fts_read(openStream)?.pointee, let current_path = current.fts_path {
let itemPath = string(withFileSystemRepresentation: current_path, length: Int(current.fts_pathlen))
guard alreadyConfirmed || shouldRemoveItemAtPath(itemPath, isURL: isURL) else {
continue
}

do {
switch Int32(current.fts_info) {
case FTS_DEFAULT, FTS_F, FTS_NSOK, FTS_SL, FTS_SLNONE:
if unlink(current.fts_path) == -1 {
if unlink(current_path) == -1 {
throw _NSErrorWithErrno(errno, reading: false, path: itemPath)
}
case FTS_DP:
if rmdir(current.fts_path) == -1 {
if rmdir(current_path) == -1 {
throw _NSErrorWithErrno(errno, reading: false, path: itemPath)
}
case FTS_DNR, FTS_ERR, FTS_NS:
Expand Down Expand Up @@ -1085,10 +1091,18 @@ extension FileManager {
do {
guard fm.fileExists(atPath: _url.path) else { throw _NSErrorWithErrno(ENOENT, reading: true, url: url) }
_stream = try FileManager.default._fileSystemRepresentation(withPath: _url.path) { fsRep in
#if os(Android)
let ps = UnsafeMutablePointer<UnsafeMutablePointer<Int8>>.allocate(capacity: 2)
#else
let ps = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: 2)
#endif
defer { ps.deallocate() }
ps.initialize(to: UnsafeMutablePointer(mutating: fsRep))
#if os(Android)
ps.advanced(by: 1).initialize(to: unsafeBitCast(0, to: UnsafeMutablePointer<Int8>.self))
#else
ps.advanced(by: 1).initialize(to: nil)
#endif
return fts_open(ps, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil)
}
if _stream == nil {
Expand Down Expand Up @@ -1135,14 +1149,14 @@ extension FileManager {
}

_current = fts_read(stream)
while let current = _current {
let filename = FileManager.default.string(withFileSystemRepresentation: current.pointee.fts_path, length: Int(current.pointee.fts_pathlen))
while let current = _current, let current_path = current.pointee.fts_path {
let filename = FileManager.default.string(withFileSystemRepresentation: current_path, length: Int(current.pointee.fts_pathlen))

switch Int32(current.pointee.fts_info) {
case FTS_D:
let (showFile, skipDescendants) = match(filename: filename, to: _options, isDir: true)
if skipDescendants {
fts_set(_stream, _current, FTS_SKIP)
fts_set(stream, current, FTS_SKIP)
}
if showFile {
return URL(fileURLWithPath: filename, isDirectory: true)
Expand Down Expand Up @@ -1315,7 +1329,7 @@ extension FileManager {
let finalErrno = originalItemURL.withUnsafeFileSystemRepresentation { (originalFS) -> Int32? in
return newItemURL.withUnsafeFileSystemRepresentation { (newItemFS) -> Int32? in
// This is an atomic operation in many OSes, but is not guaranteed to be atomic by the standard.
if rename(newItemFS, originalFS) == 0 {
if let newFS = newItemFS, let origFS = originalFS, rename(newFS, origFS) == 0 {
return nil
} else {
return errno
Expand Down
8 changes: 4 additions & 4 deletions Sources/Foundation/FileManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -568,13 +568,13 @@ open class FileManager : NSObject {
let attributes = try windowsFileAttributes(atPath: path)
let type = FileAttributeType(attributes: attributes, atPath: path)
#else
if let pwd = getpwuid(s.st_uid), pwd.pointee.pw_name != nil {
let name = String(cString: pwd.pointee.pw_name)
if let pwd = getpwuid(s.st_uid), let pwd_name = pwd.pointee.pw_name {
let name = String(cString: pwd_name)
result[.ownerAccountName] = name
}

if let grd = getgrgid(s.st_gid), grd.pointee.gr_name != nil {
let name = String(cString: grd.pointee.gr_name)
if let grd = getgrgid(s.st_gid), let grd_name = grd.pointee.gr_name {
let name = String(cString: grd_name)
result[.groupOwnerAccountName] = name
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/Foundation/Host.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import WinSDK

// getnameinfo uses size_t for its 4th and 6th arguments.
private func getnameinfo(_ addr: UnsafePointer<sockaddr>?, _ addrlen: socklen_t, _ host: UnsafeMutablePointer<Int8>?, _ hostlen: socklen_t, _ serv: UnsafeMutablePointer<Int8>?, _ servlen: socklen_t, _ flags: Int32) -> Int32 {
return Glibc.getnameinfo(addr, addrlen, host, Int(hostlen), serv, Int(servlen), flags)
guard let saddr = addr else { return -1 }
return Glibc.getnameinfo(saddr, addrlen, host, Int(hostlen), serv, Int(servlen), flags)
}

// getifaddrs and freeifaddrs are not available in Android 6.0 or earlier, so call these functions dynamically.
Expand Down
2 changes: 1 addition & 1 deletion Tests/Foundation/Tests/TestFileHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class TestFileHandle : XCTestCase {
#else
var fds: [Int32] = [-1, -1]
fds.withUnsafeMutableBufferPointer { (pointer) -> Void in
pipe(pointer.baseAddress)
pipe(pointer.baseAddress!)
}

close(fds[1])
Expand Down
2 changes: 1 addition & 1 deletion Tests/Foundation/Tests/TestTimeZone.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class TestTimeZone: XCTestCase {
var lt = tm()
localtime_r(&t, &lt)
let zoneName = NSTimeZone.system.abbreviation() ?? "Invalid Abbreviation"
let expectedName = String(cString: lt.tm_zone, encoding: .ascii) ?? "Invalid Zone"
let expectedName = String(cString: lt.tm_zone!, encoding: .ascii) ?? "Invalid Zone"
XCTAssertEqual(zoneName, expectedName, "expected name \"\(expectedName)\" is not equal to \"\(zoneName)\"")
}
#endif
Expand Down

0 comments on commit cd1e20d

Please sign in to comment.