filecopy fails with errno 34 "Result too large" when copying from NAS

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
    }

}

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.

Clarifying what you mean here, are you saying that the Finder can handle the copy and while your app cannot? Or that your app is doing both copies it works to one destination (the Finder) and fails to another? Or something else?

I'm going to assume the Finder works and your app fails (that's what typically happens) but please correct that if I'm wrong.

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.

Can someone at Apple say anything about this?

I spent some time looking into this and there does appear to be a newly reported issue (r.165759954) that sounds similar to this. In terms of next steps, I have a few suggestions:

  1. What do you "know" about the file? Is it a particular file or all copies from that source? If it's a particular file, what makes it different than the other files? This can be difficult to investigate without direct access to the file system, but the basic answer here is that "something" about that file makes it different and finding that difference generally explains the entire problem. The issue I mentioned about is tied to very large xattr copying (particularly the resource fork), so it shouldn't be happening with most "normal" file content.

  2. Try doing the same copy with cp. If cp works, then that opens up a new investigation path. "cp" is open source and, while the code is somewhat complex, it's straightforward enough that it's reasonably straightforward to compare the two implementations. This then becomes a matter of simply reworking your implementation to match cp's.

  3. If cp fails, that shifts the problem out of your code and onto the file system side. It also means that, assuming that the Finder works fine, the problem is specific to the "copyfile" copy stack (which the Finder doesn't actually use). I'm not sure I'd really "suggest" it, but that also opens up another potential workaround, which would be to retry the failing copy with the Carbon File Manager, as described here. I can't guarantee that will work, but I strongly suspect it will.

Finally, if you haven't already, please file a bug on this and post the bug number back here.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Sorry for the confusion, and you assumed correctly that copying in the Finder works, but I actually meant something else. What I meant was this: 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 the app copies the same files from the Desktop folder, it works. Copying the files with the Finder, regardless their source location, works as well.

From what the user told me, the issue only happens with some files. I actually asked them to narrow the issue down as much as possible and they found a folder with a single file, and copying that folder always causes that error. Interestingly, the destination file is actually created but has a much smaller size than the source: 250 KB instead of 34 MB.

The user also shared that file as a zip archive on Dropbox with me. I ran the ls -l@ command on it to see its extended attributes and their size, the output was:

	com.apple.FinderInfo	      32 
	com.apple.ResourceFork	     286 
	com.apple.quarantine	      57 

Could com.apple.ResourceFork be the culprit? It doesn't seem to be exceedingly large to me, but maybe zipping a file doesn't correctly preserve extended attributes. Should I ask the user to run this command on their Mac?

I also found this Stackoverflow post from 13 years ago which sounds like it could be the same issue, although they were trying to copy the extended attributes with xattr, not with filecopy: https://stackoverflow.com/questions/13533796/copy-mac-com-apple-resourcefork-extended-attribute-causing-argument-list-too-lo

I created FB21805212.

filecopy fails with errno 34 "Result too large" when copying from NAS
 
 
Q