'statvfs wrong SD available size returned

I'm trying to monitor the available SD card size in a embedded linux system (petalinux).

After looking for this topic around stackoverflow I learn that a good option is to use the statvfs structure.

So to test it I wrote the next code:

int main()
{
  struct statvfs stat;

  if (statvfs("/run/media/mmcblk1p2", &stat) != 0) {
    // error happens, just quits here
    return -1;
  }
  printf("bsize: %ld\n", stat.f_bsize);
  printf("bavail: %ld\n", stat.f_blocks);
  printf("size in bytes: %ld\n", stat.f_blocks*stat.f_bavail);
  double megas= (((double)(stat.f_blocks*stat.f_bavail)) / (1024*1024));
  printf("size in MB:%.0f \n", megas);

  return 0;
}

And the output is:

bsize: 131072
bavail: 973877
size in bytes: 945460243017
size in MB:901661 

Checking this with the df command I've got:

root@petalinux:~# df
Filesystem           1K-blocks      Used Available Use% Mounted on
devtmpfs                484744         4    484740   0% /dev
tmpfs                  1023712       128   1023584   0% /run
tmpfs                  1023712        88   1023624   0% /var/volatile
/dev/mmcblk1p2       124656256    391168 124265088   0% /run/media/mmcblk1p2
/dev/mmcblk1p1          204607    135889     68719  66% /run/media/mmcblk1p1

root@petalinux:~# df -h
Filesystem                Size      Used Available Use% Mounted on
devtmpfs                473.4M      4.0K    473.4M   0% /dev
tmpfs                   999.7M    128.0K    999.6M   0% /run
tmpfs                   999.7M     88.0K    999.6M   0% /var/volatile
/dev/mmcblk1p2          118.9G    382.0M    118.5G   0% /run/media/mmcblk1p2
/dev/mmcblk1p1          199.8M    132.7M     67.1M  66% /run/media/mmcblk1p1

I would expect for the mmcblk1p2 folder an available space of 124265088 bytes but instead I'm having 945460243017 bytes.

I've already had a look to similar questions but unfortunately non of them helped me to solve this issue.

Does anyone have an idea what I'm doing wrong?

EDIT

As pointed it could be the a block multiplication issue, where I had:

stat.f_blocks*stat.f_bavail

And I changed it to:

 stat.f_frsize*stat.f_bavail

But the result still wrong:

bsize: 131072
bavail: 973877
size in bytes: 127247450112
Size in MB:121353

Now it's showing 127247450112 and it should be 124265088, Any ideas what I've got wrong?

Thanks in advance.



Solution 1:[1]

This:

printf("size in bytes: %ld\n", stat.f_blocks*stat.f_bavail);

is multiplying two block counts, which surely is not what you meant.

Solution 2:[2]

You will most likely get a wrong answer when multiplying an unsigned long type (f_bsize and f_frsize) by an unsigned long long (f_blocks, f_bfree and f_bavail) without first casting the unsigned long as an unsigned long long... Try this:

printf("%llu\n", stat.f_bavail * (unsigned long long)stat.f_frsize);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 unwind
Solution 2 Caleb Carroll