3

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.

  • 2
    Either I don't understand what you want, or you left out the most important word in your question. "Hence need to know how to determine available free space using any kind of system call" doesn't make sense since you are already using a system call. – pipe Feb 7 at 10:09
  • 1
    The questioner is asking about system calls, not about the 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 7 at 11:47
  • "using system command in a Linux C application is causing some timing issues". I would suggest that you elaborate on this, because otherwise someone may suggest a solution that causes these same timing issues. – roaima Feb 7 at 11:50
5

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

  • statvfs(3) is not a system call; it's a library function implemented on top of the statfs(2) (without v) system call. – Uncle Billy Feb 7 at 4: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 7 at 4:49
  • 1
    maybe 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. – Uncle Billy Feb 7 at 4:49
  • 1
    @OpenSourceEnthusiast Did you run df with -B 1 or without ? By default GNU df defaults to blocks of 1024 bytes, but with -B 1 block size is set to 1 byte. – Sergiy Kolodyazhnyy Feb 7 at 5: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). – Uncle Billy Feb 7 at 5:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.