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.

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.com

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

Reply via email to