logo

utils-std

Collection of commonly available Unix tools
commit: 39d8288731b3ee95975229fb36fbe5f41f957eca
parent 722a1008ed5cf8ecb3396d59e57e3c437e4f6a77
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat,  9 Mar 2024 13:49:10 +0100

cmd/df: Add support for -a option

Diffstat:

Mcmd/df.c61++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 50 insertions(+), 11 deletions(-)

diff --git a/cmd/df.c b/cmd/df.c @@ -11,9 +11,10 @@ #include <errno.h> // errno #include <mntent.h> #include <stdbool.h> -#include <stdio.h> // printf -#include <stdlib.h> // abort, exit -#include <string.h> // strerror +#include <stdio.h> // printf +#include <stdlib.h> // abort, exit +#include <string.h> // strerror +#include <sys/stat.h> // stat, dev_t #include <sys/statvfs.h> #include <unistd.h> // getopt @@ -23,20 +24,23 @@ size_t forced_bsize = 0; static void static_escape(char *str) { - for(int i = 0; i < strlen(str); i++) + for(size_t i = 0; i < strlen(str); i++) if(iscntrl(str[i]) || isspace(str[i])) str[i] = '?'; } int main(int argc, char *argv[]) { - bool opt_P = false, opt_h = false; + bool opt_P = false, opt_h = false, opt_a = false; int c = EOF; - while((c = getopt(argc, argv, ":hPk")) != EOF) + while((c = getopt(argc, argv, ":ahPk")) != EOF) { switch(c) { + case 'a': + opt_a = true; + break; case 'P': if(forced_bsize == 0) forced_bsize = 512; @@ -76,6 +80,10 @@ main(int argc, char *argv[]) return 1; } + // FIXME: Fix maximum number of mount entries / devices + dev_t devices[4096]; + size_t devices_found = 0; + while(1) { struct mntent *mntent = getmntent(mounted); @@ -87,22 +95,53 @@ main(int argc, char *argv[]) struct statvfs stats; if(statvfs(mntent->mnt_dir, &stats) != 0) { - fprintf(stderr, "df: Error statvfs(\"%s\", _): %s\n", mntent->mnt_dir, strerror(errno)); + fprintf(stderr, "df: Warning: statvfs(\"%s\", _): %s\n", mntent->mnt_dir, strerror(errno)); static_escape(mntent->mnt_fsname); static_escape(mntent->mnt_dir); - printf("%s - - - - %s\n", mntent->mnt_fsname, mntent->mnt_dir); + + if(opt_a) printf("%s - - - - %s\n", mntent->mnt_fsname, mntent->mnt_dir); continue; } - // Needs to be done after calling statvfs(3) + if(!opt_a) + { + // Skip null filesystems + if(stats.f_blocks == 0) continue; + + struct stat file_stats; + bool dupe = false; + + if(stat(mntent->mnt_dir, &file_stats) != 0) + { + fprintf(stderr, "df: Warning stat(\"%s\", _): %s\n", mntent->mnt_dir, strerror(errno)); + } + else + { + for(size_t i = 0; i < devices_found; i++) + if(devices[i] == file_stats.st_dev) + { + dupe = true; + break; + } + + if(dupe) continue; + + if(devices_found >= 4096) + fprintf(stderr, "df: Warning: Reached maximum amount of devices which can be deduplicated\n"); + + devices[devices_found++] = file_stats.st_dev; + } + } + + // Needs to be done after calling statvfs(3) and stat(3) static_escape(mntent->mnt_fsname); static_escape(mntent->mnt_dir); size_t percent = 0; - size_t total = stats.f_frsize * stats.f_blocks; - size_t free = stats.f_bfree * stats.f_bsize; + size_t total = stats.f_frsize * (stats.f_blocks != 0 ? stats.f_blocks : 1); + size_t free = stats.f_bfree * (stats.f_bsize != 0 ? stats.f_bsize : 1); size_t used = total - free; if(used + free)