Re: NSURL getResourceValue: for NSURLVolumeMaximumFileSizeKey returns nil
Re: NSURL getResourceValue: for NSURLVolumeMaximumFileSizeKey returns nil
- Subject: Re: NSURL getResourceValue: for NSURLVolumeMaximumFileSizeKey returns nil
- From: Scott Talbert <email@hidden>
- Date: Fri, 31 Mar 2017 20:10:28 -0400
- Importance: Normal
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 <email@hidden> 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 (email@hidden)
>> Help/Unsubscribe/Update your Subscription:
>>
>> This email sent to email@hidden
>
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Filesystem-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden