Skip to content

Commit c2700d2

Browse files
committed
[android] Fix symlink comparison in Android.
The size reported by stat.st_size might not be the size of the contents of the symlink, since it might include metadata. In Android at least the size of a symlink seems to start at 18 bytes, even if the contents are smaller. The commit disables the st_size comparison against the contents comparison for Android, and rewrites a little the function to use Swift constructs like defer and guards.
1 parent c5c35c1 commit c2700d2

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

Foundation/FileManager+POSIX.swift

+15-12
Original file line numberDiff line numberDiff line change
@@ -853,24 +853,27 @@ extension FileManager {
853853
}
854854
}
855855

856-
private func _compareSymlinks(withFileSystemRepresentation file1Rep: UnsafePointer<Int8>, andFileSystemRepresentation file2Rep: UnsafePointer<Int8>, size: Int64) -> Bool {
857-
let bufSize = Int(size)
856+
private func _compareSymlinks(withFileSystemRepresentation file1Rep: UnsafePointer<Int8>, andFileSystemRepresentation file2Rep: UnsafePointer<Int8>, size fileSize: Int64) -> Bool {
857+
let bufSize = Int(fileSize)
858858
let buffer1 = UnsafeMutablePointer<CChar>.allocate(capacity: bufSize)
859+
defer { buffer1.deallocate() }
859860
let buffer2 = UnsafeMutablePointer<CChar>.allocate(capacity: bufSize)
861+
defer { buffer2.deallocate() }
860862

861863
let size1 = readlink(file1Rep, buffer1, bufSize)
864+
guard size1 >= 0 else { return false }
865+
862866
let size2 = readlink(file2Rep, buffer2, bufSize)
867+
guard size2 >= 0 else { return false }
863868

864-
let compare: Bool
865-
if size1 < 0 || size2 < 0 || size1 != size || size1 != size2 {
866-
compare = false
867-
} else {
868-
compare = memcmp(buffer1, buffer2, size1) == 0
869-
}
869+
#if !os(Android)
870+
// In Android the reported size doesn't match the contents.
871+
// Other platforms seems to follow that rule.
872+
guard fileSize == size1 else { return false }
873+
#endif
870874

871-
buffer1.deallocate()
872-
buffer2.deallocate()
873-
return compare
875+
guard size1 == size2 else { return false }
876+
return memcmp(buffer1, buffer2, size1) == 0
874877
}
875878

876879
internal func _lstatFile(atPath path: String, withFileSystemRepresentation fsRep: UnsafePointer<Int8>? = nil) throws -> stat {
@@ -938,7 +941,7 @@ extension FileManager {
938941

939942
/* -contentsEqualAtPath:andPath: does not take into account data stored in the resource fork or filesystem extended attributes.
940943
*/
941-
internal func _contentsEqual(atPath path1: String, andPath path2: String) -> Bool {
944+
internal func _contentsEqual(atPath path1: String, andPath path2: String) -> Bool {
942945
do {
943946
let fsRep1 = try __fileSystemRepresentation(withPath: path1)
944947
defer { fsRep1.deallocate() }

0 commit comments

Comments
 (0)