A user of my app reported that when my app copies files from a QNAP NAS to a folder on their Mac, they get the error "Result too large". When copying the same files from the Desktop, it works.
I asked them to reproduce the issue with the sample code below and they confirmed that it reproduces. They contacted QNAP for support who in turn contacted me saying that they are not sure they can do anything about it, and asking if Apple can help.
Both the app user and QNAP are willing to help, but at this point I'm also unsure how to proceed. Can someone at Apple say anything about this? Is this something QNAP should solve, or is this a bug in macOS?
P.S.: I've had users in the past who reported the same issue with other brands, mostly Synology.
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.runModal()
let source = openPanel.urls[0]
openPanel.canChooseFiles = false
openPanel.runModal()
let destination = openPanel.urls[0]
do {
try copyFile(from: source, to: destination.appendingPathComponent(source.lastPathComponent, isDirectory: false))
} catch {
NSAlert(error: error).runModal()
}
NSApp.terminate(nil)
}
private func copyFile(from source: URL, to destination: URL) throws {
if try source.resourceValues(forKeys: [.isDirectoryKey]).isDirectory == true {
try FileManager.default.createDirectory(at: destination, withIntermediateDirectories: false)
for source in try FileManager.default.contentsOfDirectory(at: source, includingPropertiesForKeys: nil) {
try copyFile(from: source, to: destination.appendingPathComponent(source.lastPathComponent, isDirectory: false))
}
} else {
try copyRegularFile(from: source, to: destination)
}
}
private func copyRegularFile(from source: URL, to destination: URL) throws {
let state = copyfile_state_alloc()
defer {
copyfile_state_free(state)
}
var bsize = UInt32(16_777_216)
if copyfile_state_set(state, UInt32(COPYFILE_STATE_BSIZE), &bsize) != 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
} else if copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CB), unsafeBitCast(copyfileCallback, to: UnsafeRawPointer.self)) != 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
} else if copyfile(source.path, destination.path, state, copyfile_flags_t(COPYFILE_DATA | COPYFILE_SECURITY | COPYFILE_NOFOLLOW | COPYFILE_EXCL | COPYFILE_XATTR)) != 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
}
}
private let copyfileCallback: copyfile_callback_t = { what, stage, state, src, dst, ctx in
if what == COPYFILE_COPY_DATA {
if stage == COPYFILE_ERR {
return COPYFILE_QUIT
}
}
return COPYFILE_CONTINUE
}
}