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

Reply via email to