Contents of /trunk/mkinitrd-magellan/busybox/coreutils/du.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 5678 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 5678 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
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 "busybox.h" |
27 | |
28 | #if ENABLE_FEATURE_HUMAN_READABLE |
29 | # if ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K |
30 | static unsigned long disp_hr = 1024; |
31 | # else |
32 | static unsigned long disp_hr = 512; |
33 | # endif |
34 | #elif ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K |
35 | static unsigned disp_k = 1; |
36 | #else |
37 | static unsigned disp_k; /* bss inits to 0 */ |
38 | #endif |
39 | |
40 | static int max_print_depth = INT_MAX; |
41 | static nlink_t count_hardlinks = 1; |
42 | |
43 | static int status; |
44 | static int print_files; |
45 | static int slink_depth; |
46 | static int du_depth; |
47 | static int one_file_system; |
48 | static dev_t dir_dev; |
49 | |
50 | |
51 | static void print(long size, const char * const filename) |
52 | { |
53 | /* TODO - May not want to defer error checking here. */ |
54 | #if ENABLE_FEATURE_HUMAN_READABLE |
55 | printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr), |
56 | filename); |
57 | #else |
58 | if (disp_k) { |
59 | size++; |
60 | size >>= 1; |
61 | } |
62 | printf("%ld\t%s\n", size, filename); |
63 | #endif |
64 | } |
65 | |
66 | /* tiny recursive du */ |
67 | static long du(const char * const filename) |
68 | { |
69 | struct stat statbuf; |
70 | long sum; |
71 | |
72 | if (lstat(filename, &statbuf) != 0) { |
73 | bb_perror_msg("%s", filename); |
74 | status = EXIT_FAILURE; |
75 | return 0; |
76 | } |
77 | |
78 | if (one_file_system) { |
79 | if (du_depth == 0) { |
80 | dir_dev = statbuf.st_dev; |
81 | } else if (dir_dev != statbuf.st_dev) { |
82 | return 0; |
83 | } |
84 | } |
85 | |
86 | sum = statbuf.st_blocks; |
87 | |
88 | if (S_ISLNK(statbuf.st_mode)) { |
89 | if (slink_depth > du_depth) { /* -H or -L */ |
90 | if (stat(filename, &statbuf) != 0) { |
91 | bb_perror_msg("%s", filename); |
92 | status = EXIT_FAILURE; |
93 | return 0; |
94 | } |
95 | sum = statbuf.st_blocks; |
96 | if (slink_depth == 1) { |
97 | slink_depth = INT_MAX; /* Convert -H to -L. */ |
98 | } |
99 | } |
100 | } |
101 | |
102 | if (statbuf.st_nlink > count_hardlinks) { |
103 | /* Add files/directories with links only once */ |
104 | if (is_in_ino_dev_hashtable(&statbuf, NULL)) { |
105 | return 0; |
106 | } |
107 | add_to_ino_dev_hashtable(&statbuf, NULL); |
108 | } |
109 | |
110 | if (S_ISDIR(statbuf.st_mode)) { |
111 | DIR *dir; |
112 | struct dirent *entry; |
113 | char *newfile; |
114 | |
115 | dir = warn_opendir(filename); |
116 | if (!dir) { |
117 | status = EXIT_FAILURE; |
118 | return sum; |
119 | } |
120 | |
121 | newfile = last_char_is(filename, '/'); |
122 | if (newfile) |
123 | *newfile = '\0'; |
124 | |
125 | while ((entry = readdir(dir))) { |
126 | char *name = entry->d_name; |
127 | |
128 | newfile = concat_subpath_file(filename, name); |
129 | if (newfile == NULL) |
130 | continue; |
131 | ++du_depth; |
132 | sum += du(newfile); |
133 | --du_depth; |
134 | free(newfile); |
135 | } |
136 | closedir(dir); |
137 | } else if (du_depth > print_files) { |
138 | return sum; |
139 | } |
140 | if (du_depth <= max_print_depth) { |
141 | print(sum, filename); |
142 | } |
143 | return sum; |
144 | } |
145 | |
146 | int du_main(int argc, char **argv) |
147 | { |
148 | long total; |
149 | int slink_depth_save; |
150 | int print_final_total; |
151 | char *smax_print_depth; |
152 | unsigned opt; |
153 | |
154 | #if ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K |
155 | if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */ |
156 | #if ENABLE_FEATURE_HUMAN_READABLE |
157 | disp_hr = 512; |
158 | #else |
159 | disp_k = 0; |
160 | #endif |
161 | } |
162 | #endif |
163 | |
164 | /* Note: SUSv3 specifies that -a and -s options cannot be used together |
165 | * in strictly conforming applications. However, it also says that some |
166 | * du implementations may produce output when -a and -s are used together. |
167 | * gnu du exits with an error code in this case. We choose to simply |
168 | * ignore -a. This is consistent with -s being equivalent to -d 0. |
169 | */ |
170 | #if ENABLE_FEATURE_HUMAN_READABLE |
171 | opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s"; |
172 | opt = getopt32(argc, argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth); |
173 | if (opt & (1 << 9)) { |
174 | /* -h opt */ |
175 | disp_hr = 0; |
176 | } |
177 | if (opt & (1 << 10)) { |
178 | /* -m opt */ |
179 | disp_hr = 1024*1024; |
180 | } |
181 | if (opt & (1 << 2)) { |
182 | /* -k opt */ |
183 | disp_hr = 1024; |
184 | } |
185 | #else |
186 | opt_complementary = "H-L:L-H:s-d:d-s"; |
187 | opt = getopt32(argc, argv, "aHkLsx" "d:" "lc", &smax_print_depth); |
188 | #if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K |
189 | if (opt & (1 << 2)) { |
190 | /* -k opt */ |
191 | disp_k = 1; |
192 | } |
193 | #endif |
194 | #endif |
195 | if (opt & (1 << 0)) { |
196 | /* -a opt */ |
197 | print_files = INT_MAX; |
198 | } |
199 | if (opt & (1 << 1)) { |
200 | /* -H opt */ |
201 | slink_depth = 1; |
202 | } |
203 | if (opt & (1 << 3)) { |
204 | /* -L opt */ |
205 | slink_depth = INT_MAX; |
206 | } |
207 | if (opt & (1 << 4)) { |
208 | /* -s opt */ |
209 | max_print_depth = 0; |
210 | } |
211 | one_file_system = opt & (1 << 5); /* -x opt */ |
212 | if (opt & (1 << 6)) { |
213 | /* -d opt */ |
214 | max_print_depth = xatoi_u(smax_print_depth); |
215 | } |
216 | if (opt & (1 << 7)) { |
217 | /* -l opt */ |
218 | count_hardlinks = MAXINT(nlink_t); |
219 | } |
220 | print_final_total = opt & (1 << 8); /* -c opt */ |
221 | |
222 | /* go through remaining args (if any) */ |
223 | argv += optind; |
224 | if (optind >= argc) { |
225 | *--argv = "."; |
226 | if (slink_depth == 1) { |
227 | slink_depth = 0; |
228 | } |
229 | } |
230 | |
231 | slink_depth_save = slink_depth; |
232 | total = 0; |
233 | do { |
234 | total += du(*argv); |
235 | slink_depth = slink_depth_save; |
236 | } while (*++argv); |
237 | #if ENABLE_FEATURE_CLEAN_UP |
238 | reset_ino_dev_hashtable(); |
239 | #endif |
240 | |
241 | if (print_final_total) { |
242 | print(total, "total"); |
243 | } |
244 | |
245 | fflush_stdout_and_exit(status); |
246 | } |