1*cf5a6c84SAndroid Build Coastguard Worker /* df.c - report free disk space.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2006 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * See http://opengroup.org/onlinepubs/9699919799/utilities/df.html
6*cf5a6c84SAndroid Build Coastguard Worker
7*cf5a6c84SAndroid Build Coastguard Worker USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_BIN))
8*cf5a6c84SAndroid Build Coastguard Worker
9*cf5a6c84SAndroid Build Coastguard Worker config DF
10*cf5a6c84SAndroid Build Coastguard Worker bool "df"
11*cf5a6c84SAndroid Build Coastguard Worker default y
12*cf5a6c84SAndroid Build Coastguard Worker help
13*cf5a6c84SAndroid Build Coastguard Worker usage: df [-aHhikP] [-t TYPE] [FILE...]
14*cf5a6c84SAndroid Build Coastguard Worker
15*cf5a6c84SAndroid Build Coastguard Worker The "disk free" command shows total/used/available disk space for
16*cf5a6c84SAndroid Build Coastguard Worker each filesystem listed on the command line, or all currently mounted
17*cf5a6c84SAndroid Build Coastguard Worker filesystems.
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker -a Show all (including /proc and friends)
20*cf5a6c84SAndroid Build Coastguard Worker -H Human readable (k=1000)
21*cf5a6c84SAndroid Build Coastguard Worker -h Human readable (K=1024)
22*cf5a6c84SAndroid Build Coastguard Worker -i Show inodes instead of blocks
23*cf5a6c84SAndroid Build Coastguard Worker -k Sets units back to 1024 bytes (the default without -P)
24*cf5a6c84SAndroid Build Coastguard Worker -P The SUSv3 "Pedantic" option (512 byte blocks)
25*cf5a6c84SAndroid Build Coastguard Worker -t TYPE Display only filesystems of this type
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker Pedantic provides a slightly less useful output format dictated by POSIX,
28*cf5a6c84SAndroid Build Coastguard Worker and sets the units to 512 bytes instead of the default 1024 bytes.
29*cf5a6c84SAndroid Build Coastguard Worker */
30*cf5a6c84SAndroid Build Coastguard Worker
31*cf5a6c84SAndroid Build Coastguard Worker #define FOR_df
32*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
33*cf5a6c84SAndroid Build Coastguard Worker
GLOBALS(struct arg_list * t;int units,width[6];)34*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
35*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *t;
36*cf5a6c84SAndroid Build Coastguard Worker
37*cf5a6c84SAndroid Build Coastguard Worker int units, width[6];
38*cf5a6c84SAndroid Build Coastguard Worker )
39*cf5a6c84SAndroid Build Coastguard Worker
40*cf5a6c84SAndroid Build Coastguard Worker static void measure_columns(char *s[])
41*cf5a6c84SAndroid Build Coastguard Worker {
42*cf5a6c84SAndroid Build Coastguard Worker int i;
43*cf5a6c84SAndroid Build Coastguard Worker
44*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<5; i++) TT.width[i] = maxof(TT.width[i], strlen(s[i]));
45*cf5a6c84SAndroid Build Coastguard Worker }
46*cf5a6c84SAndroid Build Coastguard Worker
print_columns(char ** dsuapm)47*cf5a6c84SAndroid Build Coastguard Worker static void print_columns(char **dsuapm)
48*cf5a6c84SAndroid Build Coastguard Worker {
49*cf5a6c84SAndroid Build Coastguard Worker int i;
50*cf5a6c84SAndroid Build Coastguard Worker
51*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<6; i++) printf(!i ? "%-*s" : " %*s", TT.width[i], dsuapm[i]);
52*cf5a6c84SAndroid Build Coastguard Worker xputc('\n');
53*cf5a6c84SAndroid Build Coastguard Worker }
54*cf5a6c84SAndroid Build Coastguard Worker
print_header()55*cf5a6c84SAndroid Build Coastguard Worker static void print_header()
56*cf5a6c84SAndroid Build Coastguard Worker {
57*cf5a6c84SAndroid Build Coastguard Worker char *dsuapm[] = {"Filesystem", "Size", "Used", "Avail", "Use%","Mounted on"};
58*cf5a6c84SAndroid Build Coastguard Worker
59*cf5a6c84SAndroid Build Coastguard Worker // The filesystem column is always at least this wide.
60*cf5a6c84SAndroid Build Coastguard Worker TT.width[0] = maxof(TT.width[0], 14+(FLAG(H)||FLAG(h)));
61*cf5a6c84SAndroid Build Coastguard Worker
62*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(i)) memcpy(dsuapm+1, (char *[]){"Inodes", "IUsed", "IFree", "IUse%"},
63*cf5a6c84SAndroid Build Coastguard Worker sizeof(char *)*4);
64*cf5a6c84SAndroid Build Coastguard Worker else {
65*cf5a6c84SAndroid Build Coastguard Worker if (!(FLAG(H)||FLAG(h))) {
66*cf5a6c84SAndroid Build Coastguard Worker dsuapm[1] = TT.units == 512 ? "512-blocks" :
67*cf5a6c84SAndroid Build Coastguard Worker FLAG(P) ? "1024-blocks" : "1K-blocks";
68*cf5a6c84SAndroid Build Coastguard Worker dsuapm[3] = "Available";
69*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(P)) dsuapm[4] = "Capacity";
70*cf5a6c84SAndroid Build Coastguard Worker }
71*cf5a6c84SAndroid Build Coastguard Worker }
72*cf5a6c84SAndroid Build Coastguard Worker
73*cf5a6c84SAndroid Build Coastguard Worker measure_columns(dsuapm);
74*cf5a6c84SAndroid Build Coastguard Worker TT.width[5] = -1;
75*cf5a6c84SAndroid Build Coastguard Worker print_columns(dsuapm);
76*cf5a6c84SAndroid Build Coastguard Worker }
77*cf5a6c84SAndroid Build Coastguard Worker
show_mt(struct mtab_list * mt,int measuring)78*cf5a6c84SAndroid Build Coastguard Worker static void show_mt(struct mtab_list *mt, int measuring)
79*cf5a6c84SAndroid Build Coastguard Worker {
80*cf5a6c84SAndroid Build Coastguard Worker unsigned long long suap[4], block = 1, ll;
81*cf5a6c84SAndroid Build Coastguard Worker char *dsuapm[6]; // device, size, used, avail, percent, mount
82*cf5a6c84SAndroid Build Coastguard Worker int i;
83*cf5a6c84SAndroid Build Coastguard Worker
84*cf5a6c84SAndroid Build Coastguard Worker // If we don't have -a, skip overmounted and synthetic filesystems.
85*cf5a6c84SAndroid Build Coastguard Worker if (!mt || (!FLAG(a) && (!mt->stat.st_dev || !mt->statvfs.f_blocks))) return;
86*cf5a6c84SAndroid Build Coastguard Worker
87*cf5a6c84SAndroid Build Coastguard Worker // If we have -t, skip other filesystem types
88*cf5a6c84SAndroid Build Coastguard Worker if (TT.t) {
89*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *al;
90*cf5a6c84SAndroid Build Coastguard Worker
91*cf5a6c84SAndroid Build Coastguard Worker for (al = TT.t; al; al = al->next) if (!strcmp(mt->type, al->arg)) break;
92*cf5a6c84SAndroid Build Coastguard Worker
93*cf5a6c84SAndroid Build Coastguard Worker if (!al) return;
94*cf5a6c84SAndroid Build Coastguard Worker }
95*cf5a6c84SAndroid Build Coastguard Worker
96*cf5a6c84SAndroid Build Coastguard Worker // Prepare filesystem display fields
97*cf5a6c84SAndroid Build Coastguard Worker *dsuapm = *mt->device == '/' ? xabspath(mt->device, 0) : 0;
98*cf5a6c84SAndroid Build Coastguard Worker if (!*dsuapm) *dsuapm = mt->device;
99*cf5a6c84SAndroid Build Coastguard Worker if (!mt->stat.st_dev) for (i = 1; i<5; i++) dsuapm[i] = "-";
100*cf5a6c84SAndroid Build Coastguard Worker else {
101*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(i)) {
102*cf5a6c84SAndroid Build Coastguard Worker suap[0] = mt->statvfs.f_files;
103*cf5a6c84SAndroid Build Coastguard Worker suap[1] = mt->statvfs.f_files - mt->statvfs.f_ffree;
104*cf5a6c84SAndroid Build Coastguard Worker suap[2] = geteuid() ? mt->statvfs.f_favail : mt->statvfs.f_ffree;
105*cf5a6c84SAndroid Build Coastguard Worker } else {
106*cf5a6c84SAndroid Build Coastguard Worker block = maxof(mt->statvfs.f_frsize, 1);
107*cf5a6c84SAndroid Build Coastguard Worker suap[0] = mt->statvfs.f_blocks;
108*cf5a6c84SAndroid Build Coastguard Worker suap[1] = mt->statvfs.f_blocks - mt->statvfs.f_bfree;
109*cf5a6c84SAndroid Build Coastguard Worker suap[2] = geteuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree;
110*cf5a6c84SAndroid Build Coastguard Worker }
111*cf5a6c84SAndroid Build Coastguard Worker
112*cf5a6c84SAndroid Build Coastguard Worker // Scale and convert to strings
113*cf5a6c84SAndroid Build Coastguard Worker dsuapm[1] = toybuf;
114*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<3; i++) {
115*cf5a6c84SAndroid Build Coastguard Worker suap[i] = (block*suap[i])/TT.units;
116*cf5a6c84SAndroid Build Coastguard Worker
117*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(H)||FLAG(h))
118*cf5a6c84SAndroid Build Coastguard Worker human_readable(dsuapm[i+1], suap[i], HR_1000*FLAG(H));
119*cf5a6c84SAndroid Build Coastguard Worker else sprintf(dsuapm[i+1], "%llu", suap[i]);
120*cf5a6c84SAndroid Build Coastguard Worker dsuapm[i+2] = strchr(dsuapm[i+1], 0)+1;
121*cf5a6c84SAndroid Build Coastguard Worker }
122*cf5a6c84SAndroid Build Coastguard Worker
123*cf5a6c84SAndroid Build Coastguard Worker // percent
124*cf5a6c84SAndroid Build Coastguard Worker if ((suap[3] = ll = suap[1]+suap[2])) {
125*cf5a6c84SAndroid Build Coastguard Worker suap[3] = (block = suap[1]*100)/ll;
126*cf5a6c84SAndroid Build Coastguard Worker if (block != suap[3]*ll) suap[3]++;
127*cf5a6c84SAndroid Build Coastguard Worker }
128*cf5a6c84SAndroid Build Coastguard Worker sprintf(dsuapm[4], "%llu%%", suap[3]);
129*cf5a6c84SAndroid Build Coastguard Worker }
130*cf5a6c84SAndroid Build Coastguard Worker dsuapm[5] = mt->dir;
131*cf5a6c84SAndroid Build Coastguard Worker
132*cf5a6c84SAndroid Build Coastguard Worker if (measuring) measure_columns(dsuapm);
133*cf5a6c84SAndroid Build Coastguard Worker else print_columns(dsuapm);
134*cf5a6c84SAndroid Build Coastguard Worker
135*cf5a6c84SAndroid Build Coastguard Worker if (*dsuapm != mt->device) free(*dsuapm);
136*cf5a6c84SAndroid Build Coastguard Worker }
137*cf5a6c84SAndroid Build Coastguard Worker
df_main(void)138*cf5a6c84SAndroid Build Coastguard Worker void df_main(void)
139*cf5a6c84SAndroid Build Coastguard Worker {
140*cf5a6c84SAndroid Build Coastguard Worker struct mtab_list *mt, *mtstart, *mtend, *mt2, *mt3;
141*cf5a6c84SAndroid Build Coastguard Worker int measuring;
142*cf5a6c84SAndroid Build Coastguard Worker char **next;
143*cf5a6c84SAndroid Build Coastguard Worker
144*cf5a6c84SAndroid Build Coastguard Worker // Units are 512 bytes if you select "pedantic" without "kilobytes".
145*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(H)||FLAG(h)||FLAG(i)) TT.units = 1;
146*cf5a6c84SAndroid Build Coastguard Worker else TT.units = FLAG(P) && !FLAG(k) ? 512 : 1024;
147*cf5a6c84SAndroid Build Coastguard Worker
148*cf5a6c84SAndroid Build Coastguard Worker if (!(mtstart = xgetmountlist(0))) return;
149*cf5a6c84SAndroid Build Coastguard Worker mtend = dlist_terminate(mtstart);
150*cf5a6c84SAndroid Build Coastguard Worker
151*cf5a6c84SAndroid Build Coastguard Worker // If we have a list of filesystems on the command line, loop through them.
152*cf5a6c84SAndroid Build Coastguard Worker if (*toys.optargs) {
153*cf5a6c84SAndroid Build Coastguard Worker // Measure the names then output the table.
154*cf5a6c84SAndroid Build Coastguard Worker for (measuring = 1;;) {
155*cf5a6c84SAndroid Build Coastguard Worker for (next = toys.optargs; *next; next++) {
156*cf5a6c84SAndroid Build Coastguard Worker struct stat st;
157*cf5a6c84SAndroid Build Coastguard Worker
158*cf5a6c84SAndroid Build Coastguard Worker // Stat it (complain if we can't).
159*cf5a6c84SAndroid Build Coastguard Worker if (stat(*next, &st)) {
160*cf5a6c84SAndroid Build Coastguard Worker if (!measuring) perror_msg("'%s'", *next);
161*cf5a6c84SAndroid Build Coastguard Worker } else {
162*cf5a6c84SAndroid Build Coastguard Worker // Find and display this filesystem. Use _last_ hit in case of
163*cf5a6c84SAndroid Build Coastguard Worker // overmounts (which is first hit in the reversed list).
164*cf5a6c84SAndroid Build Coastguard Worker for (mt = mtend, mt2 = 0; mt; mt = mt->prev) {
165*cf5a6c84SAndroid Build Coastguard Worker if (!mt2 && st.st_dev == mt->stat.st_dev) mt2 = mt;
166*cf5a6c84SAndroid Build Coastguard Worker if (st.st_rdev && (st.st_rdev == mt->stat.st_dev)) break;
167*cf5a6c84SAndroid Build Coastguard Worker }
168*cf5a6c84SAndroid Build Coastguard Worker show_mt(mt ? : mt2, measuring);
169*cf5a6c84SAndroid Build Coastguard Worker }
170*cf5a6c84SAndroid Build Coastguard Worker }
171*cf5a6c84SAndroid Build Coastguard Worker if (!measuring--) break;
172*cf5a6c84SAndroid Build Coastguard Worker print_header();
173*cf5a6c84SAndroid Build Coastguard Worker }
174*cf5a6c84SAndroid Build Coastguard Worker } else {
175*cf5a6c84SAndroid Build Coastguard Worker // Loop through mount list to filter out overmounts.
176*cf5a6c84SAndroid Build Coastguard Worker for (mt = mtend; mt; mt = mt->prev) {
177*cf5a6c84SAndroid Build Coastguard Worker for (mt3 = mt, mt2 = mt->prev; mt2; mt2 = mt2->prev) {
178*cf5a6c84SAndroid Build Coastguard Worker if (mt->stat.st_dev == mt2->stat.st_dev) {
179*cf5a6c84SAndroid Build Coastguard Worker // For --bind mounts, show earliest mount
180*cf5a6c84SAndroid Build Coastguard Worker if (!strcmp(mt->device, mt2->device)) {
181*cf5a6c84SAndroid Build Coastguard Worker mt3->stat.st_dev = 0;
182*cf5a6c84SAndroid Build Coastguard Worker mt3 = mt2;
183*cf5a6c84SAndroid Build Coastguard Worker } else mt2->stat.st_dev = 0;
184*cf5a6c84SAndroid Build Coastguard Worker }
185*cf5a6c84SAndroid Build Coastguard Worker }
186*cf5a6c84SAndroid Build Coastguard Worker }
187*cf5a6c84SAndroid Build Coastguard Worker
188*cf5a6c84SAndroid Build Coastguard Worker // Measure the names then output the table (in filesystem creation order).
189*cf5a6c84SAndroid Build Coastguard Worker for (measuring = 1;;) {
190*cf5a6c84SAndroid Build Coastguard Worker for (mt = mtstart; mt; mt = mt->next) show_mt(mt, measuring);
191*cf5a6c84SAndroid Build Coastguard Worker if (!measuring--) break;
192*cf5a6c84SAndroid Build Coastguard Worker print_header();
193*cf5a6c84SAndroid Build Coastguard Worker }
194*cf5a6c84SAndroid Build Coastguard Worker }
195*cf5a6c84SAndroid Build Coastguard Worker
196*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) llist_traverse(mtstart, free);
197*cf5a6c84SAndroid Build Coastguard Worker }
198