Contents of /trunk/mkinitrd-magellan/busybox/coreutils/du.c
Parent Directory | Revision Log
Revision 816 -
(show annotations)
(download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 5 months ago) by niro
File MIME type: text/plain
File size: 5758 byte(s)
Fri Apr 24 18:33:46 2009 UTC (15 years, 5 months ago) by niro
File MIME type: text/plain
File size: 5758 byte(s)
-updated to busybox-1.13.4
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Mini du implementation for busybox |
4 | * |
5 | * Copyright (C) 1999,2000,2001 by Lineo, inc. and John Beppu |
6 | * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> |
7 | * Copyright (C) 2002 Edward Betts <edward@debian.org> |
8 | * |
9 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
10 | */ |
11 | |
12 | /* BB_AUDIT SUSv3 compliant (unless default blocksize set to 1k) */ |
13 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/du.html */ |
14 | |
15 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) |
16 | * |
17 | * Mostly rewritten for SUSv3 compliance and to fix bugs/defects. |
18 | * 1) Added support for SUSv3 -a, -H, -L, gnu -c, and (busybox) -d options. |
19 | * The -d option allows setting of max depth (similar to gnu --max-depth). |
20 | * 2) Fixed incorrect size calculations for links and directories, especially |
21 | * when errors occurred. Calculates sizes should now match gnu du output. |
22 | * 3) Added error checking of output. |
23 | * 4) Fixed busybox bug #1284 involving long overflow with human_readable. |
24 | */ |
25 | |
26 | #include "libbb.h" |
27 | |
28 | struct globals { |
29 | #if ENABLE_FEATURE_HUMAN_READABLE |
30 | unsigned long disp_hr; |
31 | #else |
32 | unsigned disp_k; |
33 | #endif |
34 | |
35 | int max_print_depth; |
36 | nlink_t count_hardlinks; |
37 | |
38 | bool status; |
39 | bool one_file_system; |
40 | int print_files; |
41 | int slink_depth; |
42 | int du_depth; |
43 | dev_t dir_dev; |
44 | }; |
45 | #define G (*(struct globals*)&bb_common_bufsiz1) |
46 | |
47 | |
48 | static void print(unsigned long size, const char *filename) |
49 | { |
50 | /* TODO - May not want to defer error checking here. */ |
51 | #if ENABLE_FEATURE_HUMAN_READABLE |
52 | printf("%s\t%s\n", make_human_readable_str(size, 512, G.disp_hr), |
53 | filename); |
54 | #else |
55 | if (G.disp_k) { |
56 | size++; |
57 | size >>= 1; |
58 | } |
59 | printf("%ld\t%s\n", size, filename); |
60 | #endif |
61 | } |
62 | |
63 | /* tiny recursive du */ |
64 | static unsigned long du(const char *filename) |
65 | { |
66 | struct stat statbuf; |
67 | unsigned long sum; |
68 | |
69 | if (lstat(filename, &statbuf) != 0) { |
70 | bb_simple_perror_msg(filename); |
71 | G.status = EXIT_FAILURE; |
72 | return 0; |
73 | } |
74 | |
75 | if (G.one_file_system) { |
76 | if (G.du_depth == 0) { |
77 | G.dir_dev = statbuf.st_dev; |
78 | } else if (G.dir_dev != statbuf.st_dev) { |
79 | return 0; |
80 | } |
81 | } |
82 | |
83 | sum = statbuf.st_blocks; |
84 | |
85 | if (S_ISLNK(statbuf.st_mode)) { |
86 | if (G.slink_depth > G.du_depth) { /* -H or -L */ |
87 | if (stat(filename, &statbuf) != 0) { |
88 | bb_simple_perror_msg(filename); |
89 | G.status = EXIT_FAILURE; |
90 | return 0; |
91 | } |
92 | sum = statbuf.st_blocks; |
93 | if (G.slink_depth == 1) { |
94 | G.slink_depth = INT_MAX; /* Convert -H to -L. */ |
95 | } |
96 | } |
97 | } |
98 | |
99 | if (statbuf.st_nlink > G.count_hardlinks) { |
100 | /* Add files/directories with links only once */ |
101 | if (is_in_ino_dev_hashtable(&statbuf)) { |
102 | return 0; |
103 | } |
104 | add_to_ino_dev_hashtable(&statbuf, NULL); |
105 | } |
106 | |
107 | if (S_ISDIR(statbuf.st_mode)) { |
108 | DIR *dir; |
109 | struct dirent *entry; |
110 | char *newfile; |
111 | |
112 | dir = warn_opendir(filename); |
113 | if (!dir) { |
114 | G.status = EXIT_FAILURE; |
115 | return sum; |
116 | } |
117 | |
118 | newfile = last_char_is(filename, '/'); |
119 | if (newfile) |
120 | *newfile = '\0'; |
121 | |
122 | while ((entry = readdir(dir))) { |
123 | char *name = entry->d_name; |
124 | |
125 | newfile = concat_subpath_file(filename, name); |
126 | if (newfile == NULL) |
127 | continue; |
128 | ++G.du_depth; |
129 | sum += du(newfile); |
130 | --G.du_depth; |
131 | free(newfile); |
132 | } |
133 | closedir(dir); |
134 | } else if (G.du_depth > G.print_files) { |
135 | return sum; |
136 | } |
137 | if (G.du_depth <= G.max_print_depth) { |
138 | print(sum, filename); |
139 | } |
140 | return sum; |
141 | } |
142 | |
143 | int du_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
144 | int du_main(int argc UNUSED_PARAM, char **argv) |
145 | { |
146 | unsigned long total; |
147 | int slink_depth_save; |
148 | bool print_final_total; |
149 | unsigned opt; |
150 | |
151 | #if ENABLE_FEATURE_HUMAN_READABLE |
152 | USE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 1024;) |
153 | SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 512;) |
154 | if (getenv("POSIXLY_CORRECT")) /* TODO - a new libbb function? */ |
155 | G.disp_hr = 512; |
156 | #else |
157 | USE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 1;) |
158 | /* SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */ |
159 | #endif |
160 | G.max_print_depth = INT_MAX; |
161 | G.count_hardlinks = 1; |
162 | |
163 | /* Note: SUSv3 specifies that -a and -s options cannot be used together |
164 | * in strictly conforming applications. However, it also says that some |
165 | * du implementations may produce output when -a and -s are used together. |
166 | * gnu du exits with an error code in this case. We choose to simply |
167 | * ignore -a. This is consistent with -s being equivalent to -d 0. |
168 | */ |
169 | #if ENABLE_FEATURE_HUMAN_READABLE |
170 | 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); |
172 | argv += optind; |
173 | if (opt & (1 << 9)) { |
174 | /* -h opt */ |
175 | G.disp_hr = 0; |
176 | } |
177 | if (opt & (1 << 10)) { |
178 | /* -m opt */ |
179 | G.disp_hr = 1024*1024; |
180 | } |
181 | if (opt & (1 << 2)) { |
182 | /* -k opt */ |
183 | G.disp_hr = 1024; |
184 | } |
185 | #else |
186 | opt_complementary = "H-L:L-H:s-d:d-s:d+"; |
187 | opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth); |
188 | argv += optind; |
189 | #if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K |
190 | if (opt & (1 << 2)) { |
191 | /* -k opt */ |
192 | G.disp_k = 1; |
193 | } |
194 | #endif |
195 | #endif |
196 | if (opt & (1 << 0)) { |
197 | /* -a opt */ |
198 | G.print_files = INT_MAX; |
199 | } |
200 | if (opt & (1 << 1)) { |
201 | /* -H opt */ |
202 | G.slink_depth = 1; |
203 | } |
204 | if (opt & (1 << 3)) { |
205 | /* -L opt */ |
206 | G.slink_depth = INT_MAX; |
207 | } |
208 | if (opt & (1 << 4)) { |
209 | /* -s opt */ |
210 | G.max_print_depth = 0; |
211 | } |
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 | |
219 | /* go through remaining args (if any) */ |
220 | if (!*argv) { |
221 | *--argv = (char*)"."; |
222 | if (G.slink_depth == 1) { |
223 | G.slink_depth = 0; |
224 | } |
225 | } |
226 | |
227 | slink_depth_save = G.slink_depth; |
228 | total = 0; |
229 | do { |
230 | total += du(*argv); |
231 | G.slink_depth = slink_depth_save; |
232 | } while (*++argv); |
233 | |
234 | if (ENABLE_FEATURE_CLEAN_UP) |
235 | reset_ino_dev_hashtable(); |
236 | if (print_final_total) |
237 | print(total, "total"); |
238 | |
239 | fflush_stdout_and_exit(G.status); |
240 | } |