df.c (2923B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <sys/statvfs.h> 3 4 #include <mntent.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #include "util.h" 10 11 static long blksize = 512; 12 static int aflag = 0; 13 static int hflag = 0; 14 static int kflag = 0; 15 16 #define CALC_POWER(n, power, base, i) do { \ 17 while (n > power) { \ 18 power = power * base; \ 19 i++; \ 20 } \ 21 } while(0) 22 23 static void 24 print_human( 25 const char *fsname, 26 unsigned long long total, 27 unsigned long long used, 28 unsigned long long avail, 29 int capacity, 30 const char *dir) 31 { 32 long base = 1024; 33 unsigned long long power_total = base; 34 unsigned long long power_used = base; 35 unsigned long long power_avail = base; 36 char postfixes[] = {'B', 'K', 'M', 'G', 'T', 'P', 'E'}; 37 int i = 0, j = 0, k = 0; 38 39 total = total * blksize; 40 used = used * blksize; 41 avail = avail * blksize; 42 43 CALC_POWER(total, power_total, base, i); 44 CALC_POWER(used, power_used, base, j); 45 CALC_POWER(avail, power_avail, base, k); 46 47 total = i ? total / (power_total / base) : total; 48 used = j ? used / (power_used / base) : used; 49 avail = k ? avail / (power_avail / base) : avail; 50 printf("%-12s %9llu%c %9llu%c %9llu%c %7d%% %s\n", 51 fsname, total, postfixes[i], used, postfixes[j], 52 avail, postfixes[k], capacity, dir); 53 } 54 55 static int 56 mnt_show(const char *fsname, const char *dir) 57 { 58 struct statvfs s; 59 unsigned long long total, used, avail; 60 int capacity = 0; 61 int bs; 62 63 if (statvfs(dir, &s) < 0) 64 return -1; 65 66 bs = s.f_frsize / blksize; 67 total = s.f_blocks * bs; 68 avail = s.f_bfree * bs; 69 used = total - avail; 70 71 if (used + avail) { 72 capacity = (used * 100) / (used + avail); 73 if (used * 100 != capacity * (used + avail)) 74 capacity++; 75 } 76 77 if (hflag) 78 print_human(fsname, total, used, avail, capacity, dir); 79 else 80 printf("%-12s %9llu %9llu %9llu %7d%% %s\n", 81 fsname, total, used, avail, capacity, dir); 82 83 return 0; 84 } 85 86 static void 87 usage(void) 88 { 89 eprintf("usage: %s [-a]\n", argv0); 90 } 91 92 int 93 main(int argc, char *argv[]) 94 { 95 struct mntent *me = NULL; 96 FILE *fp; 97 int ret = 0; 98 99 ARGBEGIN { 100 case 'a': 101 aflag = 1; 102 break; 103 case 'h': 104 hflag = 1; 105 kflag = 0; 106 break; 107 case 'k': 108 kflag = 1; 109 hflag = 0; 110 blksize = 1024; 111 break; 112 case 's': 113 case 'i': 114 eprintf("not implemented\n"); 115 default: 116 usage(); 117 } ARGEND; 118 119 if (hflag) 120 printf("Filesystem Size Used " 121 "Avail Capacity Mounted on\n"); 122 else 123 printf("Filesystem %ld-blocks Used " 124 "Avail Capacity Mounted on\n", blksize); 125 126 fp = setmntent("/proc/mounts", "r"); 127 if (!fp) 128 eprintf("setmntent %s:", "/proc/mounts"); 129 while ((me = getmntent(fp)) != NULL) { 130 if (aflag == 0) 131 if (strcmp(me->mnt_type, "rootfs") == 0) 132 continue; 133 if (mnt_show(me->mnt_fsname, me->mnt_dir) < 0) 134 ret = 1; 135 } 136 endmntent(fp); 137 138 return ret; 139 }