Magellan Linux

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

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