How big is the file you are attempting to copy? Your hunch is probably correct. I think the Finder stops at 3.999... GB if the file system doesn't report NSURLVolumeMaximumFileSizeKey.
- Jim > On Apr 10, 2017, at 7:07 AM, Scott Talbert <s...@techie.net> wrote: > > Still trying to sort this out, but not having any luck. > > The real problem I'm trying to solve is this error message from Finder: > > The item "<filename>" can't be copied because it is too large for the > volume's format > > Do you know under what conditions Finder will produce this error message? My > hunch has been that it is related to the NSURL result, but strangely, we only > see this Finder error consistently on one specific machine. > > On Wed, 5 Apr 2017, Jim Luther wrote: > >> No. Immutable properties and capabilities like NSURLVolumeMaximumFileSizeKey >> are cached by coreservicesd on macos. The URL methods only remove cached >> values from the URL object. >> >>> On Apr 5, 2017, at 6:29 AM, Scott Talbert <s...@techie.net> wrote: >>> >>> Do -[NSURL removeCachedResourceValueForKey:] and -[NSURL >>> removeAllCachedResourceValues] clear the cached information in this case? >>> It doesn't seem that they do. >>> >>> Scott >>> >>> On Mon, 3 Apr 2017, Scott Talbert wrote: >>> >>>> It sure sounds that way. However, I haven't been able to spot a problem >>>> in the FUSE kext thus far. It seems to be setting >>>> VOL_CAP_FMT_2TB_FILESIZE when it should be. >>>> >>>> On Mon, 3 Apr 2017, Jim Luther wrote: >>>> >>>>> >>>>> On Apr 3, 2017, at 8:56 AM, Scott Talbert <s...@techie.net> >>>>> wrote: >>>>> It's getting a value from the getattrlist path. >>>>> The fact that the data is cached at mount time is an interesting >>>>> clue. It suggest that perhaps there may be some window just shortly >>>>> after mount that the incorrect data is getting reported and cached. >>>>> It's a FUSE filesystem. However, some of the more commonly-used FUSE >>>>> filesystems (e.g., sshfs) seem to behave the same way. >>>>> That sounds like a bug in FUSE. Once a file system is mounted, the kernel >>>>> sends out a VQ_MOUNT kernel event and that's what causes the >>>>> kNotifyVFSMount BSD notification to be sent. At that time, file systems >>>>> must be ready to respond to requests correctly. If they don't, they have a >>>>> bug. >>>>> - Jim >>>>> >>>>> On Sat, 1 Apr 2017, Jim Luther wrote: >>>>> >>>>> Scott, if you walk through that code, do you see >>>>> which path it's getting a value from -- pathconf or >>>>> getattrlist? >>>>> >>>>> The code in our frameworks that gets that value >>>>> runs when a file system is first mounted. We have >>>>> code listening for kNotifyVFSMount BSD >>>>> notifications. When a notification comes in, we >>>>> look to see what new volume(s) are available, and >>>>> then collect and cache the volume's immutable >>>>> properties (like this capability). >>>>> >>>>> Knowing more about the file system (what file >>>>> system type, how it's connected, etc) where you are >>>>> seeing the problem might help diagnose things. >>>>> >>>>> - Jim >>>>> >>>>> On Mar 31, 2017, at 5:10 PM, Scott >>>>> Talbert <s...@techie.net> wrote: >>>>> >>>>> Thanks for the information. >>>>> Unfortunately, that leaves me even >>>>> more >>>>> confused as, using that code, I get the >>>>> correct answer: >>>>> >>>>> #include <sys/attr.h> >>>>> #include <sys/param.h> >>>>> #include <sys/mount.h> >>>>> #import <Foundation/Foundation.h> >>>>> >>>>> int getMaxFileSize(const char *path, >>>>> int64_t *maxFileSize) >>>>> { >>>>> int result; >>>>> struct statfs statfsBuf; >>>>> >>>>> // get the file system's mount point >>>>> path for the input path >>>>> result = statfs(path, &statfsBuf); >>>>> if ( result == 0 ) { >>>>> long fileSizeBits = >>>>> pathconf(statfsBuf.f_mntonname, >>>>> _PC_FILESIZEBITS); >>>>> if (fileSizeBits == -1) { >>>>> // if _PC_FILESIZEBITS isn't >>>>> supported, check for >>>>> VOL_CAP_FMT_2TB_FILESIZE >>>>> bool >>>>> fileSystemSupports2TBFileSize = false; >>>>> >>>>> // get the supported >>>>> capabilities >>>>> struct attrlist attrList; >>>>> struct volCapabilitiesBuf { >>>>> u_int32_t length; >>>>> vol_capabilities_attr_t >>>>> capabilities; >>>>> } __attribute__((aligned(4), >>>>> packed)); >>>>> struct volCapabilitiesBuf >>>>> volCaps; >>>>> >>>>> memset(&attrList, 0, >>>>> sizeof(attrList)); >>>>> attrList.bitmapcount = >>>>> ATTR_BIT_MAP_COUNT; >>>>> attrList.volattr = >>>>> ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES; >>>>> result = >>>>> getattrlist(statfsBuf.f_mntonname, >>>>> &attrList, >>>>> &volCaps, sizeof(volCaps), 0); >>>>> if ( result == 0 ) { >>>>> fileSystemSupports2TBFileSize >>>>> = >>>>> >>>>> ((volCaps.capabilities.capabilities[VOL_CAPABILITIES_FORMAT] >>>>> & VOL_CAP_FMT_2TB_FILESIZE) && >>>>> (volCaps.capabilities.valid[VOL_CAPABILITIES_FORMAT] >>>>> & >>>>> VOL_CAP_FMT_2TB_FILESIZE)); >>>>> } >>>>> >>>>> if ( >>>>> fileSystemSupports2TBFileSize ) { >>>>> // use >>>>> Supports2TBFileSize >>>>> *maxFileSize = >>>>> LONG_LONG_MAX; >>>>> } >>>>> else { >>>>> // otherwise, we don't >>>>> know >>>>> *maxFileSize = -1LL; >>>>> } >>>>> } >>>>> else if ( fileSizeBits > 64 ) { >>>>> // off_t is signed long long, >>>>> so it cannot be more than >>>>> LONG_LONG_MAX >>>>> *maxFileSize = LONG_LONG_MAX; >>>>> } >>>>> else if ( fileSizeBits < 32 ) { >>>>> // POSIX spec says 'Minimum >>>>> Acceptable Value: 32' for >>>>> FILESIZEBITS >>>>> *maxFileSize = INT_MAX; >>>>> } >>>>> else { >>>>> // 32...64 bits: shift off >>>>> the bits we don't need >>>>> *maxFileSize = >>>>> (int64_t)((u_int64_t)0xffffffffffffffffLL >>>>> >> >>>>> (u_int64_t)(65 - fileSizeBits)); >>>>> } >>>>> } >>>>> return result; >>>>> } >>>>> >>>>> int main() >>>>> { >>>>> const char *mount = >>>>> "/Volumes/Filesystem"; >>>>> >>>>> int64_t maxFileSize; >>>>> int ret1 = getMaxFileSize(mount, >>>>> &maxFileSize); >>>>> NSLog(@"getMaxFileSize %d %lld", ret1, >>>>> maxFileSize); >>>>> >>>>> NSString *path = [NSString >>>>> stringWithUTF8String:mount]; >>>>> NSURL *url = [NSURL >>>>> fileURLWithPath:path]; >>>>> NSNumber *maxfilesize; >>>>> NSError *error; >>>>> BOOL ret = [url >>>>> getResourceValue:&maxfilesize >>>>> forKey:NSURLVolumeMaximumFileSizeKey >>>>> error:&error]; >>>>> NSLog(@"NSURLVolumeMaximumFileSize: %d >>>>> %@ %@", ret, maxfilesize, error); >>>>> >>>>> } >>>>> >>>>> $ ./blahm >>>>> 2017-03-31 20:04:34.358 >>>>> blahm[45735:2028260] getMaxFileSize 0 >>>>> 9223372036854775807 >>>>> 2017-03-31 20:04:34.365 >>>>> blahm[45735:2028260] >>>>> NSURLVolumeMaximumFileSize: 1 >>>>> (null) (null) >>>>> >>>>> As -[NSURL >>>>> getResourceValue:forKey:error:] >>>>> is documented, "If this >>>>> method >>>>> returns YES and the value >>>>> is populated with nil, it >>>>> means that the >>>>> resource property is not >>>>> available for the specified >>>>> resource, and that no >>>>> errors occurred when >>>>> determining that the >>>>> resource property was >>>>> unavailable." So YES and >>>>> nil is a valid response. >>>>> >>>>> The >>>>> NSURLVolumeMaximumFileSizeKey >>>>> property value comes from >>>>> two sources: >>>>> pathconf() with >>>>> _PC_FILESIZEBITS, or from >>>>> getattrlist() from the >>>>> ATTR_VOL_CAPABILITIES >>>>> attribute and the >>>>> VOL_CAP_FMT_2TB_FILESIZE >>>>> capability. >>>>> >>>>> Here's code (not the real >>>>> code but the exact same >>>>> algorithm) that shows >>>>> how the value is >>>>> calculated: >>>>> >>>>> int getMaxFileSize(const >>>>> char *path, int64_t >>>>> *maxFileSize) >>>>> { >>>>> int result; >>>>> struct statfs statfsBuf; >>>>> >>>>> // get the file system's >>>>> mount point path for the >>>>> input path >>>>> result = statfs(path, >>>>> &statfsBuf); >>>>> if ( result == 0 ) { >>>>> long fileSizeBits = >>>>> pathconf(statfsBuf.f_mntonname, >>>>> _PC_FILESIZEBITS); >>>>> if (fileSizeBits == >>>>> -1) { >>>>> // if >>>>> _PC_FILESIZEBITS isn't >>>>> supported, check for >>>>> VOL_CAP_FMT_2TB_FILESIZE >>>>> bool >>>>> fileSystemSupports2TBFileSize >>>>> = false; >>>>> >>>>> // get the >>>>> supported capabilities >>>>> struct attrlist >>>>> attrList; >>>>> struct >>>>> volCapabilitiesBuf { >>>>> u_int32_t >>>>> length; >>>>> vol_capabilities_attr_t >>>>> capabilities; >>>>> } >>>>> __attribute__((aligned(4), >>>>> packed)); >>>>> struct >>>>> volCapabilitiesBuf volCaps; >>>>> >>>>> memset(&attrList, >>>>> 0, sizeof(attrList)); >>>>> attrList.bitmapcount >>>>> = ATTR_BIT_MAP_COUNT; >>>>> attrList.volattr >>>>> = ATTR_VOL_INFO | >>>>> ATTR_VOL_CAPABILITIES; >>>>> result = >>>>> getattrlist(statfsBuf.f_mntonname, >>>>> &attrList, >>>>> &volCaps, sizeof(volCaps), >>>>> 0); >>>>> if ( result == 0 >>>>> ) { >>>>> fileSystemSupports2TBFileSize >>>>> = >>>>> >>>>> ((volCaps.capabilities.capabilities[VOL_CAPABILITIES_FORMAT] >>>>> & VOL_CAP_FMT_2TB_FILESIZE) >>>>> && >>>>> (volCaps.capabilities.valid[VOL_CAPABILITIES_FORMAT] >>>>> & >>>>> VOL_CAP_FMT_2TB_FILESIZE)); >>>>> } >>>>> >>>>> if ( >>>>> fileSystemSupports2TBFileSize >>>>> ) { >>>>> // use >>>>> Supports2TBFileSize >>>>> *maxFileSize >>>>> = LONG_LONG_MAX; >>>>> } >>>>> else { >>>>> // otherwise, >>>>> we don't know >>>>> *maxFileSize >>>>> = -1LL; >>>>> } >>>>> } >>>>> else if ( >>>>> fileSizeBits > 64 ) { >>>>> // off_t is >>>>> signed long long, so it >>>>> cannot be more than >>>>> LONG_LONG_MAX >>>>> *maxFileSize = >>>>> LONG_LONG_MAX; >>>>> } >>>>> else if ( >>>>> fileSizeBits < 32 ) { >>>>> // POSIX spec >>>>> says 'Minimum Acceptable >>>>> Value: 32' for >>>>> FILESIZEBITS >>>>> *maxFileSize = >>>>> INT_MAX; >>>>> } >>>>> else { >>>>> // 32...64 bits: >>>>> shift off the bits we don't >>>>> need >>>>> *maxFileSize = >>>>> (int64_t)((u_int64_t)0xffffffffffffffffLL >>>>> >> >>>>> (u_int64_t)(65 - >>>>> fileSizeBits)); >>>>> } >>>>> } >>>>> return result; >>>>> } >>>>> >>>>> if >>>>> NSURLVolumeMaximumFileSizeKey >>>>> is returning nil with no >>>>> errors, >>>>> maxFileSize is -1LL, and >>>>> the only way maxFileSize >>>>> will be -1LL is if >>>>> pathconf() returned an >>>>> error, and the file system >>>>> is saying >>>>> VOL_CAP_FMT_2TB_FILESIZE is >>>>> not valid and set >>>>> (capabilities). >>>>> >>>>> Hope that helpsâ?¢ >>>>> >>>>> - Jim >>>>> >>>>> On Mar 31, >>>>> 2017, at 2:33 >>>>> PM, Scott >>>>> Talbert >>>>> <s...@techie.net> >>>>> wrote: >>>>> >>>>> Hello, >>>>> >>>>> Can anyone tell >>>>> me why calling >>>>> NSURL >>>>> -getResourceValue:forKey:error: >>>>> with key >>>>> NSURLVolumeMaximumFileSizeKey >>>>> would return a >>>>> nil resource >>>>> value >>>>> for a given >>>>> volume? The >>>>> function >>>>> returns YES and >>>>> error is nil >>>>> also. >>>>> >>>>> I can see from >>>>> running dtruss >>>>> that it in turn >>>>> calls >>>>> getattrlist(). >>>>> If I >>>>> call >>>>> getattrlist() >>>>> myself on the >>>>> same volume, I >>>>> can see the >>>>> bits I would >>>>> think it is >>>>> looking at are >>>>> set correctly - >>>>> VOL_CAP_FMT_2TB_FILESIZE. >>>>> >>>>> Thanks, >>>>> Scott >>>>> >>>>> _______________________________________________ >>>>> Do not post >>>>> admin requests >>>>> to the list. >>>>> They will be >>>>> ignored. >>>>> Filesystem-dev >>>>> mailing list >>>>> (Filesystem-dev@lists.apple.com) >>>>> Help/Unsubscribe/Update >>>>> your >>>>> Subscription: >>>>> https://lists.apple.com/mailman/options/filesystem-dev/luther.j%40apple.co >>>>> m >>>>> >>>>> This email sent >>>>> to >>>>> luthe...@apple.com >> _______________________________________________ Do not post admin requests to the list. They will be ignored. Filesystem-dev mailing list (Filesystem-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/filesystem-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com