Magellan Linux

Contents of /trunk/mkinitrd-magellan/busybox/coreutils/du.c

Parent Directory Parent Directory | Revision Log 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)
-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 }