Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/du.c
Parent Directory | Revision Log
Revision 816 -
(hide annotations)
(download)
Fri Apr 24 18:33:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 5758 byte(s)
Fri Apr 24 18:33:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 5758 byte(s)
-updated to busybox-1.13.4
1 | niro | 532 | /* 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 | niro | 816 | #include "libbb.h" |
27 | niro | 532 | |
28 | niro | 816 | struct globals { |
29 | niro | 532 | #if ENABLE_FEATURE_HUMAN_READABLE |
30 | niro | 816 | unsigned long disp_hr; |
31 | niro | 532 | #else |
32 | niro | 816 | unsigned disp_k; |
33 | niro | 532 | #endif |
34 | |||
35 | niro | 816 | int max_print_depth; |
36 | nlink_t count_hardlinks; | ||
37 | niro | 532 | |
38 | niro | 816 | 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 | niro | 532 | |
47 | |||
48 | niro | 816 | static void print(unsigned long size, const char *filename) |
49 | niro | 532 | { |
50 | /* TODO - May not want to defer error checking here. */ | ||
51 | #if ENABLE_FEATURE_HUMAN_READABLE | ||
52 | niro | 816 | printf("%s\t%s\n", make_human_readable_str(size, 512, G.disp_hr), |
53 | niro | 532 | filename); |
54 | #else | ||
55 | niro | 816 | if (G.disp_k) { |
56 | niro | 532 | size++; |
57 | size >>= 1; | ||
58 | } | ||
59 | printf("%ld\t%s\n", size, filename); | ||
60 | #endif | ||
61 | } | ||
62 | |||
63 | /* tiny recursive du */ | ||
64 | niro | 816 | static unsigned long du(const char *filename) |
65 | niro | 532 | { |
66 | struct stat statbuf; | ||
67 | niro | 816 | unsigned long sum; |
68 | niro | 532 | |
69 | if (lstat(filename, &statbuf) != 0) { | ||
70 | niro | 816 | bb_simple_perror_msg(filename); |
71 | G.status = EXIT_FAILURE; | ||
72 | niro | 532 | return 0; |
73 | } | ||
74 | |||
75 | niro | 816 | 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 | niro | 532 | return 0; |
80 | } | ||
81 | } | ||
82 | |||
83 | sum = statbuf.st_blocks; | ||
84 | |||
85 | if (S_ISLNK(statbuf.st_mode)) { | ||
86 | niro | 816 | if (G.slink_depth > G.du_depth) { /* -H or -L */ |
87 | niro | 532 | if (stat(filename, &statbuf) != 0) { |
88 | niro | 816 | bb_simple_perror_msg(filename); |
89 | G.status = EXIT_FAILURE; | ||
90 | niro | 532 | return 0; |
91 | } | ||
92 | sum = statbuf.st_blocks; | ||
93 | niro | 816 | if (G.slink_depth == 1) { |
94 | G.slink_depth = INT_MAX; /* Convert -H to -L. */ | ||
95 | niro | 532 | } |
96 | } | ||
97 | } | ||
98 | |||
99 | niro | 816 | if (statbuf.st_nlink > G.count_hardlinks) { |
100 | niro | 532 | /* Add files/directories with links only once */ |
101 | niro | 816 | if (is_in_ino_dev_hashtable(&statbuf)) { |
102 | niro | 532 | 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 | niro | 816 | G.status = EXIT_FAILURE; |
115 | niro | 532 | 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 | niro | 816 | ++G.du_depth; |
129 | niro | 532 | sum += du(newfile); |
130 | niro | 816 | --G.du_depth; |
131 | niro | 532 | free(newfile); |
132 | } | ||
133 | closedir(dir); | ||
134 | niro | 816 | } else if (G.du_depth > G.print_files) { |
135 | niro | 532 | return sum; |
136 | } | ||
137 | niro | 816 | if (G.du_depth <= G.max_print_depth) { |
138 | niro | 532 | print(sum, filename); |
139 | } | ||
140 | return sum; | ||
141 | } | ||
142 | |||
143 | niro | 816 | int du_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
144 | int du_main(int argc UNUSED_PARAM, char **argv) | ||
145 | niro | 532 | { |
146 | niro | 816 | unsigned long total; |
147 | niro | 532 | int slink_depth_save; |
148 | niro | 816 | bool print_final_total; |
149 | niro | 532 | unsigned opt; |
150 | |||
151 | #if ENABLE_FEATURE_HUMAN_READABLE | ||
152 | niro | 816 | 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 | niro | 532 | #else |
157 | niro | 816 | 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 | niro | 532 | #endif |
160 | niro | 816 | G.max_print_depth = INT_MAX; |
161 | G.count_hardlinks = 1; | ||
162 | niro | 532 | |
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 | niro | 816 | 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 | niro | 532 | if (opt & (1 << 9)) { |
174 | /* -h opt */ | ||
175 | niro | 816 | G.disp_hr = 0; |
176 | niro | 532 | } |
177 | if (opt & (1 << 10)) { | ||
178 | /* -m opt */ | ||
179 | niro | 816 | G.disp_hr = 1024*1024; |
180 | niro | 532 | } |
181 | if (opt & (1 << 2)) { | ||
182 | /* -k opt */ | ||
183 | niro | 816 | G.disp_hr = 1024; |
184 | niro | 532 | } |
185 | #else | ||
186 | niro | 816 | 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 | niro | 532 | #if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K |
190 | if (opt & (1 << 2)) { | ||
191 | /* -k opt */ | ||
192 | niro | 816 | G.disp_k = 1; |
193 | niro | 532 | } |
194 | #endif | ||
195 | #endif | ||
196 | if (opt & (1 << 0)) { | ||
197 | /* -a opt */ | ||
198 | niro | 816 | G.print_files = INT_MAX; |
199 | niro | 532 | } |
200 | if (opt & (1 << 1)) { | ||
201 | /* -H opt */ | ||
202 | niro | 816 | G.slink_depth = 1; |
203 | niro | 532 | } |
204 | if (opt & (1 << 3)) { | ||
205 | /* -L opt */ | ||
206 | niro | 816 | G.slink_depth = INT_MAX; |
207 | niro | 532 | } |
208 | if (opt & (1 << 4)) { | ||
209 | /* -s opt */ | ||
210 | niro | 816 | G.max_print_depth = 0; |
211 | niro | 532 | } |
212 | niro | 816 | G.one_file_system = opt & (1 << 5); /* -x opt */ |
213 | niro | 532 | if (opt & (1 << 7)) { |
214 | /* -l opt */ | ||
215 | niro | 816 | G.count_hardlinks = MAXINT(nlink_t); |
216 | niro | 532 | } |
217 | print_final_total = opt & (1 << 8); /* -c opt */ | ||
218 | |||
219 | /* go through remaining args (if any) */ | ||
220 | niro | 816 | if (!*argv) { |
221 | *--argv = (char*)"."; | ||
222 | if (G.slink_depth == 1) { | ||
223 | G.slink_depth = 0; | ||
224 | niro | 532 | } |
225 | } | ||
226 | |||
227 | niro | 816 | slink_depth_save = G.slink_depth; |
228 | niro | 532 | total = 0; |
229 | do { | ||
230 | total += du(*argv); | ||
231 | niro | 816 | G.slink_depth = slink_depth_save; |
232 | niro | 532 | } while (*++argv); |
233 | |||
234 | niro | 816 | if (ENABLE_FEATURE_CLEAN_UP) |
235 | reset_ino_dev_hashtable(); | ||
236 | if (print_final_total) | ||
237 | niro | 532 | print(total, "total"); |
238 | |||
239 | niro | 816 | fflush_stdout_and_exit(G.status); |
240 | niro | 532 | } |