Question

I've got an issue with a program that should send me back the free disk space usable by any user.

My goal is to get all the free disk space of every partitions of my hard drive that is usable by anyone who doesn't have sudo rights.

So I tryed this :

int main() {
    struct statvfs diskData;
    statvfs("/", &diskData);
    unsigned long long available = (diskData.f_favail + diskData.f_bavail) * diskData.f_frsize) / (1024 * 1024)
    std::cout << "Free Space : " << available << std::endl;
}

This gives me a total of 2810 ...

However, when I output df -h, I can read that the available space is 25G for sda3 and 30G for sda1

This seems completely inaccurate.

I've been running on the posts on Stackoverflow, mixing solutions I saw, but none is satisfactory. How can I get a correct value in Megabytes of my available free space ?

EDIT : Full statvfs and df / output

statvfs :

Block Size            : 4 096
Fragment Size         : 4 096
Blocks                : 9 612 197
Free Blocks           : 7 009 166
Non Root Free Blocks  : 6 520 885
Inodes                : 2 444 624
Free Inodes Space     : 2 137 054
Non Root Free Inodes  : 2 137 054
File System ID        : 4 224 884 198
Mount Flags           : 4 096
Max Filename Length   : 255

df / :

Filesystem     1K-Blocks      Used           Available      Use%     Mounted on
/dev/sda3      38 448 788     10 412 112     26 083 556     29%      / 
Était-ce utile?

La solution 2

It seems that the right value to use is the fragment size, not the block size (i.e. f_frsize)

Have you tried with

diskData.f_bavail * diskData.f_frsize

instead ?

Autres conseils

This seems like a more accurate measure of the free disk space:

unsigned long long available = (diskData.f_bavail * diskData.f_bsize) / (1024 * 1024);

It matches the output from df quite closely on my system (df shows the sizes in gigs, and probably rounds them).

If you want the output in gigs like df you could use this:

#include <sys/statvfs.h>
#include <stdio.h>

unsigned long rounddiv(unsigned long num, unsigned long divisor) {
    return (num + (divisor/2)) / divisor;
}

int main() {
    struct statvfs diskData;
    statvfs("/home", &diskData);
    unsigned long available = diskData.f_bavail * diskData.f_bsize;
    printf("Free Space : %luG\n", rounddiv(available, 1024*1024*1024));
    return 0;
}

The output from this on my system:
Free Space : 31G

And if I run df -h /home:

Filesystem            Size  Used Avail Use% Mounted on
                      181G  141G   31G  83% /home
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top