Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
A variety of methods to calculate the free space on a Mac volume
/*
* freesize.m
* Description: Multiple ways to calculate the free space on a volume
* Author: Chad Armstrong
* Date: 6 - 10 May 2017
* To compile: gcc -framework Foundation freesize.m -o freesize
*/
#import <Foundation/Foundation.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
// Use param.h and mount.h for statfs
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/statvfs.h>
#include <string.h>
#include <stdlib.h>
// Use unistd.h and attr.h for getattrlist
#include <unistd.h>
#include <sys/attr.h>
// Buffer structure for getattrlist()
typedef struct {
uint32_t length; // Contains overall length, in bytes, of this structure
off_t vol_size;
off_t space_free;
off_t space_available;
} vol_attr;
#pragma mark Prototypes
void fileManagerCalculation();
void cocoaFreeSpaceCalculation();
void getattrlistCalculation();
void statfsCalculation();
void statvfsCalculation();
#pragma mark -
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// NSFileManager ------------------
fileManagerCalculation();
// NSURL ------------------
cocoaFreeSpaceCalculation();
// getattrlist ------------------
getattrlistCalculation();
// statfs ------------------
statfsCalculation();
// statvfs ------------------
statvfsCalculation();
[pool drain];
return 0;
}
// Check folder size using Cocoa's NSFileManager
void fileManagerCalculation()
{
NSError *error = nil;
NSFileManager *fm = [NSFileManager defaultManager];
NSDictionary *attr = [fm attributesOfFileSystemForPath:@"/" error:&error];
NSLog(@"Attr: %@", attr);
double totalsizeGb = [[attr objectForKey:NSFileSystemSize] doubleValue] / 1000000000;
NSLog(@"File system size in GB %.2f",totalsizeGb);
double freeSizeBytes = [[attr objectForKey:NSFileSystemFreeSize] doubleValue];
double freesizeGb = [[attr objectForKey:NSFileSystemFreeSize] doubleValue] / 1000000000;
NSLog(@"Free size in GB %.2f (%.0f)", freesizeGb, freeSizeBytes);
}
void cocoaFreeSpaceCalculation()
{
NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeNameKey, NSURLVolumeTotalCapacityKey, NSURLVolumeAvailableCapacityKey, nil];
NSArray *urls = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:keys options:NSVolumeEnumerationSkipHiddenVolumes];
for (NSURL *url in urls) {
NSNumber *availableSpace = nil;
NSError *error = nil;
NSDictionary *resources = [url resourceValuesForKeys: keys error: &error];
NSLog(@"NSURL resources: %@", resources);
if ([url getResourceValue: &availableSpace forKey: NSURLVolumeAvailableCapacityKey error: &error] == YES) {
NSString *formattedAvailableSpace = [NSByteCountFormatter stringFromByteCount: [availableSpace longLongValue] countStyle: NSByteCountFormatterCountStyleFile];
NSLog(@"availableSpace: %@ formattedAvailableSpace: %@", availableSpace, formattedAvailableSpace);
}
}
}
/* Example response:
Volume size: 16229794380578291739
Free space: 15103894473735667713
Avail size: 1
*/
/* References:
* https://books.google.com/books?id=K8vUkpOXhN4C&pg=PA1575&lpg=PA1575&dq=getattrlist+example&source=bl&ots=OLqjSSTpUy&sig=9XXq2hoXoRC_y61OhuRKwkyZjNM&hl=en&sa=X&ved=0ahUKEwjo0YTh9OHTAhUlzoMKHYvPAvAQ6AEITjAG#v=onepage&q=getattrlist%20example&f=false
* https://cboard.cprogramming.com/linux-programming/114785-mac-os-x-10-4-getattrlist-know-file-system-type.html
* https://github.com/yarshure/AdvancedMacOSX/blob/master/amosxp3-sample-code-update/12-files-part-2/permtype-getattrlist.m
* https://github.com/yarshure/AdvancedMacOSX/blob/master/amosxp3-sample-code-update/12-files-part-2/permtype.m
* https://alastairs-place.net/blog/2012/06/20/file-ownership-and-acls/
*/
void getattrlistCalculation()
{
struct attrlist attr; // = { 0 };
vol_attr volAttr;
// Must clear out the structure first, otherwise we'll get undefined results
memset(&attr, 0, sizeof (attr));
memset(&volAttr, 0, sizeof(volAttr));
attr.bitmapcount = ATTR_BIT_MAP_COUNT; /* number of attr. bit sets in list */
attr.reserved = 0; /* (to maintain 4-byte alignment) */
attr.commonattr = 0; /* common attribute group */
attr.volattr = ATTR_VOL_INFO | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | ATTR_VOL_SPACEAVAIL; /* volume attribute group */
attr.dirattr = 0; /* directory attribute group */
attr.fileattr = 0; /* file attribute group */
attr.forkattr = 0; /* fork attribute group */
if (getattrlist("/", &attr, &volAttr, sizeof(volAttr), FSOPT_NOFOLLOW) < 0) {
perror("getattrlist");
}
if (volAttr.length > sizeof(volAttr)) {
// Need to use a bigger buffer in this case
printf("Error: volAttr's buffer is larger than it's allocated size\n");
}
// Note: None of this data seems correct. The vol_attr structure may not be lining up properly with the data.
printf("\ngetattrlist ------------------\n");
printf("\tVolume size: %llu\n", volAttr.vol_size);
printf("\tFree space: %llu\n", volAttr.space_free);
printf("\tAvail size: %llu\n", volAttr.space_available);
}
void statfsCalculation()
{
struct statfs vfs;
if (statfs("/", & vfs) != 0) {
fprintf(stderr, "%s: statfs failed: %s\n",
"/", strerror(errno));
exit(0);
}
printf("\nstatfs ------------------\n");
printf("mounted on %s:\n","/");
printf("\tf_bsize: %u\n", vfs.f_bsize);
printf("\tf_blocks: %llu\n", vfs.f_blocks);
printf("\tf_bfree: %llu\n", vfs.f_bfree);
printf("\tf_bavail: %llu\n", vfs.f_bavail);
printf("\tf_files: %llu\n", vfs.f_files);
printf("\tf_ffree: %llu\n", vfs.f_ffree);
long long Total_Space = vfs.f_blocks;
Total_Space *= vfs.f_bsize; // vfs.f_frsize;
Total_Space /= 1024;
long long Avail_Space = vfs.f_bavail; // vfs.f_bfree;
Avail_Space *= vfs.f_bsize; // vfs.f_frsize;
Avail_Space /= 1024;
long long Free_Space = vfs.f_bfree;
Free_Space *= vfs.f_bsize; // vfs.f_frsize;
Free_Space /= 1024;
printf("\nTotal Space: \t\t%lld KB \nAvailable Space: \t%lld KB \nFree Space: \t\t%lld KB\n", Total_Space, Avail_Space, Free_Space);
double freespacePercentage = 100.0 * (double) (vfs.f_blocks - vfs.f_bfree) / (double) (vfs.f_blocks - vfs.f_bfree + vfs.f_bavail);
printf("\nCapacity filled: %.0f%% \n", freespacePercentage);
}
void statvfsCalculation()
{
struct statvfs stat;
if (statvfs("/", &stat) == 0) {
printf("\nstatvfs ------------------\n");
printf("\tf_bsize: %lu\n", stat.f_bsize); // 1048576 = 2^20, instead of 4096
printf("\tf_frsize: %lu\n", stat.f_frsize); // corresponds to f_bsize member of struct statfs
printf("\tf_bfree: %u\n", stat.f_bfree);
printf("\tf_bavail: %u\n", stat.f_bavail);
long availableFreeSpace = stat.f_frsize * stat.f_bavail;
printf("availableFreeSpace: %lu\n", availableFreeSpace);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment