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