ubase

suckless linux base utils
git clone git://git.suckless.org/ubase
Log | Files | Refs | README | LICENSE

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 }