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
32
33
34
35
36
37
38
39#define FOR_du
40#include "toys.h"
41
42GLOBALS(
43 long d;
44
45 unsigned long depth, total;
46 dev_t st_dev;
47 void *inodes;
48)
49
50typedef struct node_size {
51 struct dirtree *node;
52 long size;
53} node_size;
54
55
56static void print(long long size, struct dirtree *node)
57{
58 char *name = "total";
59
60 if (TT.depth > TT.d) return;
61
62 if (FLAG(h)) {
63 human_readable(toybuf, size, 0);
64 printf("%s", toybuf);
65 } else {
66 int bits = 10;
67
68 if (FLAG(K)) bits = 9;
69 else if (FLAG(m)) bits = 20;
70
71 if (FLAG(b) && bits == 10 && !FLAG(k)) printf("%llu", size);
72 else printf("%llu", (size>>bits)+!!(size&((1<<bits)-1)));
73 }
74 if (node) name = dirtree_path(node, NULL);
75 xprintf("\t%s\n", name);
76 if (node) free(name);
77}
78
79
80
81static int seen_inode(void **list, struct stat *st)
82{
83 if (!st) llist_traverse(st, free);
84
85
86
87
88
89 else if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
90 struct inode_list {
91 struct inode_list *next;
92 struct dev_ino di;
93 } *new;
94
95 for (new = *list; new; new = new->next)
96 if(same_dev_ino(st, &new->di)) return 1;
97
98 new = xzalloc(sizeof(*new));
99 new->di.ino = st->st_ino;
100 new->di.dev = st->st_dev;
101 new->next = *list;
102 *list = new;
103 }
104
105 return 0;
106}
107
108
109static int do_du(struct dirtree *node)
110{
111 unsigned long blocks;
112
113 if (!node->parent) TT.st_dev = node->st.st_dev;
114 else if (!dirtree_notdotdot(node)) return 0;
115
116
117 if (FLAG(x) && (TT.st_dev != node->st.st_dev))
118 return 0;
119
120
121 if (FLAG(L)) {
122 struct dirtree *try = node;
123
124 while ((try = try->parent)) if (same_file(&node->st, &try->st)) return 0;
125 }
126
127
128 if (!FLAG(l) && !node->again)
129 if (seen_inode(&TT.inodes, &node->st)) return 0;
130
131
132 if (S_ISDIR(node->st.st_mode)) {
133 if (!node->again) {
134 TT.depth++;
135 return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!FLAG(L));
136 } else TT.depth--;
137 }
138
139
140
141 blocks = FLAG(b) ? node->st.st_size : node->st.st_blocks;
142 blocks += (unsigned long)node->extra;
143 node->extra = blocks;
144 if (node->parent)
145 node->parent->extra = (unsigned long)node->parent->extra+blocks;
146 else TT.total += node->extra;
147
148 if (FLAG(a) || !node->parent || (S_ISDIR(node->st.st_mode) && !FLAG(s))) {
149 blocks = node->extra;
150 print(FLAG(b) ? blocks : blocks*512LL, node);
151 }
152
153 return 0;
154}
155
156void du_main(void)
157{
158 char *noargs[] = {".", 0}, **args;
159
160
161 for (args = toys.optc ? toys.optargs : noargs; *args; args++)
162 dirtree_flagread(*args, DIRTREE_SYMFOLLOW*!!(toys.optflags&(FLAG_H|FLAG_L)),
163 do_du);
164 if (FLAG(c)) print(FLAG(b) ? TT.total : TT.total*512, 0);
165
166 if (CFG_TOYBOX_FREE) seen_inode(TT.inodes, 0);
167}
168