Do not rely on FileManager's isExecutableFile, check manually for Mach-O executable...
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Thu, 21 Nov 2024 10:28:19 +0000 (18:28 +0800)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Thu, 21 Nov 2024 10:47:32 +0000 (18:47 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
admin/osx/mac-crafter/Sources/Utils/Codesign.swift

index 139a1e802449ceb16de59d1cf9cdaaa554c36222..bb8ded8ffeb6ee833199f12e1c5d1bb2a7cf5dc1 100644 (file)
@@ -32,11 +32,21 @@ func isAppExtension(_ path: String) -> Bool {
     path.hasSuffix(".appex")
 }
 
-func isExecutable(_ path: String) -> Bool {
-    let fm = FileManager.default
-    var isDir: ObjCBool = false
-    let exists = fm.fileExists(atPath: path, isDirectory: &isDir)
-    return fm.isExecutableFile(atPath: path) && !isDir.boolValue && exists
+func isExecutable(_ path: String) throws -> Bool {
+    let outPipe = Pipe()
+    let errPipe = Pipe()
+    let task = Process()
+    task.standardOutput = outPipe
+    task.standardError = errPipe
+
+    let command = "file \"\(path)\""
+    guard run("/bin/zsh", ["-c", command], task: task) == 0 else {
+        throw CodeSigningError.failedToCodeSign("Failed to determine if \(path) is an executable.")
+    }
+
+    let outputData = outPipe.fileHandleForReading.readDataToEndOfFile()
+    let output = String(data: outputData, encoding: .utf8) ?? ""
+    return output.contains("Mach-O 64-bit executable")
 }
 
 func codesign(identity: String, path: String, options: String = defaultCodesignOptions) throws {
@@ -60,11 +70,11 @@ func recursivelyCodesign(
     }
 
     for case let enumeratedItem as String in pathEnumerator {
-        guard isLibrary(enumeratedItem) ||
-              isAppExtension(enumeratedItem) ||
-              isExecutable(enumeratedItem)
-        else { continue }
-        try codesign(identity: identity, path: "\(path)/\(enumeratedItem)")
+        let isExecutableFile = try isExecutable(fm.currentDirectoryPath + "/" + path + "/" + enumeratedItem)
+        guard isLibrary(enumeratedItem) || isAppExtension(enumeratedItem) || isExecutableFile else {
+            continue
+        }
+        try codesign(identity: identity, path: "\(path)/\(enumeratedItem)", options: options)
     }
 }