A system which stays up for weeks or months at a time needs to monitor various facets of its operation to alert an operator if something unusual occurs. One of the things which should be monitored is disk space, as a full filesystem tends to expose lots of strange and wonderful failure modes. I suspect such monitoring is commonly implemented by invoking popen("df -k") and parsing the output. An alternative is to use the same calls which df uses: getmntent and statfs.
setmntent and getmntent parse a file listing mounted filesystems, generally /etc/mtab on Linux systems. The getmntent_r variant shown below is a glibc-specific extension which is thread safe, requiring that a block of memory be provided in which to store string parameters like the mount point.
#include <mntent.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/vfs.h> #include <unistd.h> int main(void) { FILE* mtab = setmntent("/etc/mtab", "r"); struct mntent* m; struct mntent mnt; char strings[4096]; while ((m = getmntent_r(mtab, &mnt, strings, sizeof(strings)))) { struct statfs fs; if ((mnt.mnt_dir != NULL) && (statfs(mnt.mnt_dir, &fs) == 0)) { unsigned long long int size = fs.f_blocks * fs.f_bsize; unsigned long long int free = fs.f_bfree * fs.f_bsize; unsigned long long int avail = fs.f_bavail * fs.f_bsize; printf("%s %s size=%lld free=%lld avail=%lld\n", mnt.mnt_fsname, mnt.mnt_dir, size, free, avail); } } endmntent(mtab); }
This code likely fails when there are stacked filesystems, where multiple filesystems are mounted one atop another on the same directory. This is done for union mounts where a read-only filesystem like squashfs has a read-write filesystem mounted atop it as an overlay. statfs will retrieve only the topmost filesystem at that mount point. I don't have a solution for this, if anyone can provide one in the comments I'll add it as an update here.