Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/du.c
Parent Directory | Revision Log
Revision 532 -
(hide 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 | 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 | #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 | } |