aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-11-11 21:15:56 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-11-11 21:15:56 +0000
commit618a3027edbfd42e52bfd7680cd24affe7a29b4c (patch)
tree5493504ca370c90464e3b6550d11b6d51c05c4fc
parent3b35fbb6323adadf7108e1d32fc4d93b4d89e9c4 (diff)
downloadbusybox-w32-618a3027edbfd42e52bfd7680cd24affe7a29b4c.tar.gz
busybox-w32-618a3027edbfd42e52bfd7680cd24affe7a29b4c.tar.bz2
busybox-w32-618a3027edbfd42e52bfd7680cd24affe7a29b4c.zip
du: fix "du /dir /dir" case
reset_ino_dev_hashtable - 84 +84 du 388 376 -12 du_main 327 301 -26 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 84/-38) Total: 46 bytes
-rw-r--r--coreutils/du.c82
-rw-r--r--libbb/inode_hash.c2
2 files changed, 36 insertions, 48 deletions
diff --git a/coreutils/du.c b/coreutils/du.c
index efc9bb9fa..16c773243 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -25,19 +25,28 @@
25 25
26#include "libbb.h" 26#include "libbb.h"
27 27
28enum {
29 OPT_a_files_too = (1 << 0),
30 OPT_H_follow_links = (1 << 1),
31 OPT_k_kbytes = (1 << 2),
32 OPT_L_follow_links = (1 << 3),
33 OPT_s_total_norecurse = (1 << 4),
34 OPT_x_one_FS = (1 << 5),
35 OPT_d_maxdepth = (1 << 6),
36 OPT_l_hardlinks = (1 << 7),
37 OPT_c_total = (1 << 8),
38 OPT_h_for_humans = (1 << 9),
39 OPT_m_mbytes = (1 << 10),
40};
41
28struct globals { 42struct globals {
29#if ENABLE_FEATURE_HUMAN_READABLE 43#if ENABLE_FEATURE_HUMAN_READABLE
30 unsigned long disp_hr; 44 unsigned long disp_hr;
31#else 45#else
32 unsigned disp_k; 46 unsigned disp_k;
33#endif 47#endif
34
35 int max_print_depth; 48 int max_print_depth;
36 nlink_t count_hardlinks;
37
38 bool status; 49 bool status;
39 bool one_file_system;
40 int print_files;
41 int slink_depth; 50 int slink_depth;
42 int du_depth; 51 int du_depth;
43 dev_t dir_dev; 52 dev_t dir_dev;
@@ -72,7 +81,7 @@ static unsigned long du(const char *filename)
72 return 0; 81 return 0;
73 } 82 }
74 83
75 if (G.one_file_system) { 84 if (option_mask32 & OPT_x_one_FS) {
76 if (G.du_depth == 0) { 85 if (G.du_depth == 0) {
77 G.dir_dev = statbuf.st_dev; 86 G.dir_dev = statbuf.st_dev;
78 } else if (G.dir_dev != statbuf.st_dev) { 87 } else if (G.dir_dev != statbuf.st_dev) {
@@ -83,7 +92,7 @@ static unsigned long du(const char *filename)
83 sum = statbuf.st_blocks; 92 sum = statbuf.st_blocks;
84 93
85 if (S_ISLNK(statbuf.st_mode)) { 94 if (S_ISLNK(statbuf.st_mode)) {
86 if (G.slink_depth > G.du_depth) { /* -H or -L */ 95 if (G.slink_depth > G.du_depth) { /* -H or -L */
87 if (stat(filename, &statbuf) != 0) { 96 if (stat(filename, &statbuf) != 0) {
88 bb_simple_perror_msg(filename); 97 bb_simple_perror_msg(filename);
89 G.status = EXIT_FAILURE; 98 G.status = EXIT_FAILURE;
@@ -91,12 +100,15 @@ static unsigned long du(const char *filename)
91 } 100 }
92 sum = statbuf.st_blocks; 101 sum = statbuf.st_blocks;
93 if (G.slink_depth == 1) { 102 if (G.slink_depth == 1) {
94 G.slink_depth = INT_MAX; /* Convert -H to -L. */ 103 /* Convert -H to -L */
104 G.slink_depth = INT_MAX;
95 } 105 }
96 } 106 }
97 } 107 }
98 108
99 if (statbuf.st_nlink > G.count_hardlinks) { 109 if (!(option_mask32 & OPT_l_hardlinks)
110 && statbuf.st_nlink > 1
111 ) {
100 /* Add files/directories with links only once */ 112 /* Add files/directories with links only once */
101 if (is_in_ino_dev_hashtable(&statbuf)) { 113 if (is_in_ino_dev_hashtable(&statbuf)) {
102 return 0; 114 return 0;
@@ -115,14 +127,8 @@ static unsigned long du(const char *filename)
115 return sum; 127 return sum;
116 } 128 }
117 129
118 newfile = last_char_is(filename, '/');
119 if (newfile)
120 *newfile = '\0';
121
122 while ((entry = readdir(dir))) { 130 while ((entry = readdir(dir))) {
123 char *name = entry->d_name; 131 newfile = concat_subpath_file(filename, entry->d_name);
124
125 newfile = concat_subpath_file(filename, name);
126 if (newfile == NULL) 132 if (newfile == NULL)
127 continue; 133 continue;
128 ++G.du_depth; 134 ++G.du_depth;
@@ -131,8 +137,9 @@ static unsigned long du(const char *filename)
131 free(newfile); 137 free(newfile);
132 } 138 }
133 closedir(dir); 139 closedir(dir);
134 } else if (G.du_depth > G.print_files) { 140 } else {
135 return sum; 141 if (!(option_mask32 & OPT_a_files_too) && G.du_depth != 0)
142 return sum;
136 } 143 }
137 if (G.du_depth <= G.max_print_depth) { 144 if (G.du_depth <= G.max_print_depth) {
138 print(sum, filename); 145 print(sum, filename);
@@ -145,7 +152,6 @@ int du_main(int argc UNUSED_PARAM, char **argv)
145{ 152{
146 unsigned long total; 153 unsigned long total;
147 int slink_depth_save; 154 int slink_depth_save;
148 bool print_final_total;
149 unsigned opt; 155 unsigned opt;
150 156
151#if ENABLE_FEATURE_HUMAN_READABLE 157#if ENABLE_FEATURE_HUMAN_READABLE
@@ -158,7 +164,6 @@ int du_main(int argc UNUSED_PARAM, char **argv)
158 /* SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */ 164 /* SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */
159#endif 165#endif
160 G.max_print_depth = INT_MAX; 166 G.max_print_depth = INT_MAX;
161 G.count_hardlinks = 1;
162 167
163 /* Note: SUSv3 specifies that -a and -s options cannot be used together 168 /* Note: SUSv3 specifies that -a and -s options cannot be used together
164 * in strictly conforming applications. However, it also says that some 169 * in strictly conforming applications. However, it also says that some
@@ -170,16 +175,13 @@ int du_main(int argc UNUSED_PARAM, char **argv)
170 opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s:d+"; 175 opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s:d+";
171 opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth); 176 opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth);
172 argv += optind; 177 argv += optind;
173 if (opt & (1 << 9)) { 178 if (opt & OPT_h_for_humans) {
174 /* -h opt */
175 G.disp_hr = 0; 179 G.disp_hr = 0;
176 } 180 }
177 if (opt & (1 << 10)) { 181 if (opt & OPT_m_mbytes) {
178 /* -m opt */
179 G.disp_hr = 1024*1024; 182 G.disp_hr = 1024*1024;
180 } 183 }
181 if (opt & (1 << 2)) { 184 if (opt & OPT_k_kbytes) {
182 /* -k opt */
183 G.disp_hr = 1024; 185 G.disp_hr = 1024;
184 } 186 }
185#else 187#else
@@ -187,34 +189,20 @@ int du_main(int argc UNUSED_PARAM, char **argv)
187 opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth); 189 opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth);
188 argv += optind; 190 argv += optind;
189#if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K 191#if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
190 if (opt & (1 << 2)) { 192 if (opt & OPT_k_kbytes) {
191 /* -k opt */
192 G.disp_k = 1; 193 G.disp_k = 1;
193 } 194 }
194#endif 195#endif
195#endif 196#endif
196 if (opt & (1 << 0)) { 197 if (opt & OPT_H_follow_links) {
197 /* -a opt */
198 G.print_files = INT_MAX;
199 }
200 if (opt & (1 << 1)) {
201 /* -H opt */
202 G.slink_depth = 1; 198 G.slink_depth = 1;
203 } 199 }
204 if (opt & (1 << 3)) { 200 if (opt & OPT_L_follow_links) {
205 /* -L opt */
206 G.slink_depth = INT_MAX; 201 G.slink_depth = INT_MAX;
207 } 202 }
208 if (opt & (1 << 4)) { 203 if (opt & OPT_s_total_norecurse) {
209 /* -s opt */
210 G.max_print_depth = 0; 204 G.max_print_depth = 0;
211 } 205 }
212 G.one_file_system = opt & (1 << 5); /* -x opt */
213 if (opt & (1 << 7)) {
214 /* -l opt */
215 G.count_hardlinks = MAXINT(nlink_t);
216 }
217 print_final_total = opt & (1 << 8); /* -c opt */
218 206
219 /* go through remaining args (if any) */ 207 /* go through remaining args (if any) */
220 if (!*argv) { 208 if (!*argv) {
@@ -228,12 +216,12 @@ int du_main(int argc UNUSED_PARAM, char **argv)
228 total = 0; 216 total = 0;
229 do { 217 do {
230 total += du(*argv); 218 total += du(*argv);
219 /* otherwise du /dir /dir won't show /dir twice: */
220 reset_ino_dev_hashtable();
231 G.slink_depth = slink_depth_save; 221 G.slink_depth = slink_depth_save;
232 } while (*++argv); 222 } while (*++argv);
233 223
234 if (ENABLE_FEATURE_CLEAN_UP) 224 if (opt & OPT_c_total)
235 reset_ino_dev_hashtable();
236 if (print_final_total)
237 print(total, "total"); 225 print(total, "total");
238 226
239 fflush_stdout_and_exit(G.status); 227 fflush_stdout_and_exit(G.status);
diff --git a/libbb/inode_hash.c b/libbb/inode_hash.c
index 4469671dd..b32bd26bf 100644
--- a/libbb/inode_hash.c
+++ b/libbb/inode_hash.c
@@ -67,7 +67,7 @@ void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *
67 ino_dev_hashtable[i] = bucket; 67 ino_dev_hashtable[i] = bucket;
68} 68}
69 69
70#if ENABLE_FEATURE_CLEAN_UP 70#if ENABLE_DU || ENABLE_FEATURE_CLEAN_UP
71/* Clear statbuf hash table */ 71/* Clear statbuf hash table */
72void FAST_FUNC reset_ino_dev_hashtable(void) 72void FAST_FUNC reset_ino_dev_hashtable(void)
73{ 73{