1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#define FOR_df
32#include "toys.h"
33
34GLOBALS(
35 struct arg_list *t;
36
37 long units;
38 int column_widths[5];
39 int header_shown;
40)
41
42static void measure_column(int col, const char *s)
43{
44 size_t len = strlen(s);
45
46 if (TT.column_widths[col] < len) TT.column_widths[col] = len;
47}
48
49static void measure_numeric_column(int col, long long n)
50{
51 snprintf(toybuf, sizeof(toybuf), "%llu", n);
52 return measure_column(col, toybuf);
53}
54
55static void show_header()
56{
57 TT.header_shown = 1;
58
59
60 if (TT.column_widths[0] < 14) TT.column_widths[0] = 14;
61
62 if ((toys.optflags & (FLAG_H|FLAG_h))) {
63 xprintf((toys.optflags&FLAG_i) ?
64 "%-*sInodes IUsed IFree IUse%% Mounted on\n" :
65 "%-*s Size Used Avail Use%% Mounted on\n",
66 TT.column_widths[0], "Filesystem");
67 } else {
68 const char *item_label, *used_label, *free_label, *use_label;
69
70 if (toys.optflags & FLAG_i) {
71 item_label = "Inodes";
72 used_label = "IUsed";
73 free_label = "IFree";
74 use_label = "IUse%";
75 } else {
76 item_label = TT.units == 512 ? "512-blocks" : "1K-blocks";
77 used_label = "Used";
78 free_label = "Available";
79 use_label = toys.optflags & FLAG_P ? "Capacity" : "Use%";
80 }
81
82 measure_column(1, item_label);
83 measure_column(2, used_label);
84 measure_column(3, free_label);
85 measure_column(4, use_label);
86 xprintf("%-*s %*s %*s %*s %*s Mounted on\n",
87 TT.column_widths[0], "Filesystem",
88 TT.column_widths[1], item_label,
89 TT.column_widths[2], used_label,
90 TT.column_widths[3], free_label,
91 TT.column_widths[4], use_label);
92
93
94 TT.column_widths[4]--;
95 }
96}
97
98static void show_mt(struct mtab_list *mt, int measuring)
99{
100 unsigned long long size, used, avail, percent, block;
101 char *device;
102
103
104 if (!mt) return;
105
106
107 if (TT.t) {
108 struct arg_list *al;
109
110 for (al = TT.t; al; al = al->next)
111 if (!strcmp(mt->type, al->arg)) break;
112
113 if (!al) return;
114 }
115
116
117 if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return;
118
119
120
121 if (toys.optflags & FLAG_i) {
122 size = mt->statvfs.f_files;
123 used = mt->statvfs.f_files - mt->statvfs.f_ffree;
124 avail = getuid() ? mt->statvfs.f_favail : mt->statvfs.f_ffree;
125 } else {
126 block = mt->statvfs.f_bsize ? mt->statvfs.f_bsize : 1;
127 size = (block * mt->statvfs.f_blocks) / TT.units;
128 used = (block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree)) / TT.units;
129 avail= (block*(getuid()?mt->statvfs.f_bavail:mt->statvfs.f_bfree))/TT.units;
130 }
131 if (!(used+avail)) percent = 0;
132 else {
133 percent = (used*100)/(used+avail);
134 if (used*100 != percent*(used+avail)) percent++;
135 }
136
137 device = *mt->device == '/' ? realpath(mt->device, NULL) : NULL;
138 if (!device) device = mt->device;
139
140 if (measuring) {
141 measure_column(0, device);
142 measure_numeric_column(1, size);
143 measure_numeric_column(2, used);
144 measure_numeric_column(3, avail);
145 } else {
146 if (!TT.header_shown) show_header();
147
148 if (toys.optflags & (FLAG_H|FLAG_h)) {
149 char *size_str = toybuf, *used_str = toybuf+64, *avail_str = toybuf+128;
150 int hr_flags = (toys.optflags & FLAG_H) ? HR_1000 : 0;
151 int w = 4 + !!(toys.optflags & FLAG_i);
152
153 human_readable(size_str, size, hr_flags);
154 human_readable(used_str, used, hr_flags);
155 human_readable(avail_str, avail, hr_flags);
156 xprintf("%-*s %*s %*s %*s %*llu%% %s\n",
157 TT.column_widths[0], device,
158 w, size_str, w, used_str, w, avail_str, w-1, percent, mt->dir);
159 } else xprintf("%-*s %*llu %*llu %*llu %*llu%% %s\n",
160 TT.column_widths[0], device,
161 TT.column_widths[1], size,
162 TT.column_widths[2], used,
163 TT.column_widths[3], avail,
164 TT.column_widths[4], percent,
165 mt->dir);
166 }
167
168 if (device != mt->device) free(device);
169}
170
171void df_main(void)
172{
173 struct mtab_list *mt, *mtstart, *mtend;
174 int measuring;
175
176 if (toys.optflags & (FLAG_H|FLAG_h)) {
177 TT.units = 1;
178 } else {
179
180 TT.units = toys.optflags & FLAG_P ? 512 : 1024;
181 }
182
183 if (!(mtstart = xgetmountlist(0))) return;
184 mtend = dlist_terminate(mtstart);
185
186
187 if (*toys.optargs) {
188
189 for (measuring = 1; measuring >= 0; --measuring) {
190 char **next;
191
192 for (next = toys.optargs; *next; next++) {
193 struct stat st;
194
195
196 if (stat(*next, &st)) {
197 perror_msg("'%s'", *next);
198 continue;
199 }
200
201
202
203 for (mt = mtend; mt; mt = mt->prev) {
204 if (st.st_dev == mt->stat.st_dev
205 || (st.st_rdev && (st.st_rdev == mt->stat.st_dev)))
206 {
207 show_mt(mt, measuring);
208 break;
209 }
210 }
211 }
212 }
213 } else {
214
215 for (mt = mtend; mt; mt = mt->prev) {
216 struct mtab_list *mt2, *mt3;
217
218
219 if (!mt->stat.st_dev) continue;
220
221
222 mt3 = mt;
223 for (mt2 = mt->prev; mt2; mt2 = mt2->prev) {
224 if (mt->stat.st_dev == mt2->stat.st_dev) {
225
226 if (!strcmp(mt->device, mt2->device)) {
227 if (!(toys.optflags & FLAG_a)) mt3->stat.st_dev = 0;
228 mt3 = mt2;
229 } else mt2->stat.st_dev = 0;
230 }
231 }
232 }
233
234
235 for (measuring = 1; measuring >= 0; --measuring) {
236
237 for (mt = mtstart; mt; mt = mt->next) {
238 if (mt->stat.st_dev) show_mt(mt, measuring);
239 }
240 }
241 }
242
243 if (CFG_TOYBOX_FREE) llist_traverse(mtstart, free);
244}
245