xref: /aosp_15_r20/external/toybox/toys/posix/df.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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