I would like to figure out the available free space on a USB flash drive in a C program in Linux. I have earlier used system("df -h /dev/sda1")
to figure it out but using system command in a Linux C application is causing some timing issues. Hence need to know how to determine available free space using any other kind of system call/library function.
1 Answers
For a mounted USB flash drive, you can do this via statvfs(3) function, where you need to provide path to the mountpoint, and you basically have a small version of df
(which also btw only operates on mounted filesystems):
$ cat fs_usage.c
#include <stdio.h>
#include <sys/statvfs.h>
int main(int argc, char **argv){
struct statvfs fs_usage;
statvfs(argv[1],&fs_usage);
printf("%s:%f bytes available, %f bytes used\n",argv[1],
fs_usage.f_frsize*(double)fs_usage.f_bavail,
fs_usage.f_frsize * (double)(fs_usage.f_blocks - fs_usage.f_bfree));
return 0;
}
$ gcc fs_usage.c -o fs_usage
$ df -B 1 /mnt/ubuntu
Filesystem 1B-blocks Used Available Use% Mounted on
/dev/sdb1 118013599744 105134329856 6860865536 94% /mnt/ubuntu
$ ./fs_usage /mnt/ubuntu/
/mnt/ubuntu/:6860865536.000000 bytes available, 105134329856.000000 bytes used
Note also that statvfs()
takes const char *path
as one of the parameters, and that can be pathname of any file within the filesystem, e.g. /dev/sda7
will return usage of /dev
filesystem ( because it is in fact one of virtual filesystems ), and not the sda7
partition of a device.
Note that I am using f_frsize
here, which is equivalent to f_bsize
, however in some filesystems fragment size may be smaller than block size. See https://unix.stackexchange.com/a/463370/85039 for details
If your C library (usually glibc but on an embedded platform might be something else) implements statvfs(3) in a way that's too slow for you, then you should probably use the underlying statfs(2) or fstatfs(2) system calls directly instead.

- 15,462

- 16,527
-
1statvfs(3) is not a system call; it's a library function implemented on top of the statfs(2) (without v) system call. – Feb 07 '19 at 04:24
-
When I ran the above code, I see some precision loss as compared to the values reported by df command. For instance, df reports available space as 21M and the above code reports available space as 20M. How do we get very accurate values for available space (till . precision) – OpenSourceEnthusiast Feb 07 '19 at 04:49
-
2maybe you should mention that statvfs it will work on any file contained in the fs, not just the mount point --
statvfs("/dev/sda7", &vfs)
will return info about the devtmpfs file system, not about the filesystem contained in/dev/sda7
. – Feb 07 '19 at 04:49 -
1@OpenSourceEnthusiast Did you run
df
with-B 1
or without ? By default GNUdf
defaults to blocks of 1024 bytes, but with-B 1
block size is set to 1 byte. – Sergiy Kolodyazhnyy Feb 07 '19 at 05:03 -
1@OpenSourceEnthusiast
printf("%llu\n", (uint64_t)vfs.f_bavail * vfs.f_frsize)
will get you the value down to the last byte; it's up to you to round it as you see fit (using 2^20 or 10^6 for M, etc). – Feb 07 '19 at 05:05 -
-
@OpenSourceEnthusiast
df -h
will give you human readable numbers, which means it will round the numbers. If you do intend on using C, rounding will have to be done by yourself (dividing by 1024 on each iteration). I've done that in Python for one of my apps, so if you want I can provide a link to that as well. – Sergiy Kolodyazhnyy Feb 07 '19 at 06:08 -
@OpenSourceEnthusiast https://github.com/SergKolo/udisks-indicator Line 489,
def get_human_readable()
– Sergiy Kolodyazhnyy Feb 07 '19 at 06:48 -
@SergiyKolodyazhnyy this code seems to be computationally intensive too. It seems to be taking ~200 msecs to execute on my target.. which is more than what df -h was taking on my target board. Looks like statvfs is a library call which takes quite some time to complete. Is there a better/lighter version of this code? – OpenSourceEnthusiast Feb 07 '19 at 09:59
-
@OpenSourceEnthusiast you're not telling what board and what version of linux you're using. Have you read the NOTES from the statvfs(3) manpage? It should be pretty obvious what you should do next. – Feb 07 '19 at 10:14
-
Not sure what you mean by "it should be pretty obvious what you should do next". My linux application is running on beagle bone black. – OpenSourceEnthusiast Feb 07 '19 at 10:24
-
1If your C library (usually
glibc
but on an embedded platform might be something else) implementsstatvfs(3)
in a way that's too slow for you, then you should probably use the underlyingstatfs(2)
orfstatfs(2)
system calls directly instead. – telcoM Feb 07 '19 at 10:50
system
call. They are asking what libraries exist, e.g. can they ask the kernel. However this may be off topic, as it is a programming question. – ctrl-alt-delor Feb 07 '19 at 11:47