Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 23  Line 23 
23   * 4) Fixed busybox bug #1284 involving long overflow with human_readable.   * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
24   */   */
25    
26  #include "busybox.h"  #include "libbb.h"
27    
28    enum {
29     OPT_a_files_too    = (1 << 0),
30     OPT_H_follow_links = (1 << 1),
31     OPT_k_kbytes       = (1 << 2),
32     OPT_L_follow_links = (1 << 3),
33     OPT_s_total_norecurse = (1 << 4),
34     OPT_x_one_FS       = (1 << 5),
35     OPT_d_maxdepth     = (1 << 6),
36     OPT_l_hardlinks    = (1 << 7),
37     OPT_c_total        = (1 << 8),
38     OPT_h_for_humans   = (1 << 9),
39     OPT_m_mbytes       = (1 << 10),
40    };
41    
42    struct globals {
43  #if ENABLE_FEATURE_HUMAN_READABLE  #if ENABLE_FEATURE_HUMAN_READABLE
44  # if ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K   unsigned long disp_hr;
 static unsigned long disp_hr = 1024;  
 # else  
 static unsigned long disp_hr = 512;  
 # endif  
 #elif ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K  
 static unsigned disp_k = 1;  
45  #else  #else
46  static unsigned disp_k; /* bss inits to 0 */   unsigned disp_k;
47  #endif  #endif
48     int max_print_depth;
49  static int max_print_depth = INT_MAX;   bool status;
50  static nlink_t count_hardlinks = 1;   int slink_depth;
51     int du_depth;
52  static int status;   dev_t dir_dev;
53  static int print_files;  };
54  static int slink_depth;  #define G (*(struct globals*)&bb_common_bufsiz1)
 static int du_depth;  
 static int one_file_system;  
 static dev_t dir_dev;  
55    
56    
57  static void print(long size, const char * const filename)  static void print(unsigned long size, const char *filename)
58  {  {
59   /* TODO - May not want to defer error checking here. */   /* TODO - May not want to defer error checking here. */
60  #if ENABLE_FEATURE_HUMAN_READABLE  #if ENABLE_FEATURE_HUMAN_READABLE
61   printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr),   printf("%s\t%s\n",
62     /* size x 512 / G.disp_hr, show one fractional,
63     * use suffixes if G.disp_hr == 0 */
64     make_human_readable_str(size, 512, G.disp_hr),
65   filename);   filename);
66  #else  #else
67   if (disp_k) {   if (G.disp_k) {
68   size++;   size++;
69   size >>= 1;   size >>= 1;
70   }   }
71   printf("%ld\t%s\n", size, filename);   printf("%lu\t%s\n", size, filename);
72  #endif  #endif
73  }  }
74    
75  /* tiny recursive du */  /* tiny recursive du */
76  static long du(const char * const filename)  static unsigned long du(const char *filename)
77  {  {
78   struct stat statbuf;   struct stat statbuf;
79   long sum;   unsigned long sum;
80    
81   if (lstat(filename, &statbuf) != 0) {   if (lstat(filename, &statbuf) != 0) {
82   bb_perror_msg("%s", filename);   bb_simple_perror_msg(filename);
83   status = EXIT_FAILURE;   G.status = EXIT_FAILURE;
84   return 0;   return 0;
85   }   }
86    
87   if (one_file_system) {   if (option_mask32 & OPT_x_one_FS) {
88   if (du_depth == 0) {   if (G.du_depth == 0) {
89   dir_dev = statbuf.st_dev;   G.dir_dev = statbuf.st_dev;
90   } else if (dir_dev != statbuf.st_dev) {   } else if (G.dir_dev != statbuf.st_dev) {
91   return 0;   return 0;
92   }   }
93   }   }
# Line 86  static long du(const char * const filena Line 95  static long du(const char * const filena
95   sum = statbuf.st_blocks;   sum = statbuf.st_blocks;
96    
97   if (S_ISLNK(statbuf.st_mode)) {   if (S_ISLNK(statbuf.st_mode)) {
98   if (slink_depth > du_depth) { /* -H or -L */   if (G.slink_depth > G.du_depth) { /* -H or -L */
99   if (stat(filename, &statbuf) != 0) {   if (stat(filename, &statbuf) != 0) {
100   bb_perror_msg("%s", filename);   bb_simple_perror_msg(filename);
101   status = EXIT_FAILURE;   G.status = EXIT_FAILURE;
102   return 0;   return 0;
103   }   }
104   sum = statbuf.st_blocks;   sum = statbuf.st_blocks;
105   if (slink_depth == 1) {   if (G.slink_depth == 1) {
106   slink_depth = INT_MAX; /* Convert -H to -L. */   /* Convert -H to -L */
107     G.slink_depth = INT_MAX;
108   }   }
109   }   }
110   }   }
111    
112   if (statbuf.st_nlink > count_hardlinks) {   if (!(option_mask32 & OPT_l_hardlinks)
113     && statbuf.st_nlink > 1
114     ) {
115   /* Add files/directories with links only once */   /* Add files/directories with links only once */
116   if (is_in_ino_dev_hashtable(&statbuf, NULL)) {   if (is_in_ino_dev_hashtable(&statbuf)) {
117   return 0;   return 0;
118   }   }
119   add_to_ino_dev_hashtable(&statbuf, NULL);   add_to_ino_dev_hashtable(&statbuf, NULL);
# Line 114  static long du(const char * const filena Line 126  static long du(const char * const filena
126    
127   dir = warn_opendir(filename);   dir = warn_opendir(filename);
128   if (!dir) {   if (!dir) {
129   status = EXIT_FAILURE;   G.status = EXIT_FAILURE;
130   return sum;   return sum;
131   }   }
132    
  newfile = last_char_is(filename, '/');  
  if (newfile)  
  *newfile = '\0';  
   
133   while ((entry = readdir(dir))) {   while ((entry = readdir(dir))) {
134   char *name = entry->d_name;   newfile = concat_subpath_file(filename, entry->d_name);
   
  newfile = concat_subpath_file(filename, name);  
135   if (newfile == NULL)   if (newfile == NULL)
136   continue;   continue;
137   ++du_depth;   ++G.du_depth;
138   sum += du(newfile);   sum += du(newfile);
139   --du_depth;   --G.du_depth;
140   free(newfile);   free(newfile);
141   }   }
142   closedir(dir);   closedir(dir);
143   } else if (du_depth > print_files) {   } else {
144   return sum;   if (!(option_mask32 & OPT_a_files_too) && G.du_depth != 0)
145     return sum;
146   }   }
147   if (du_depth <= max_print_depth) {   if (G.du_depth <= G.max_print_depth) {
148   print(sum, filename);   print(sum, filename);
149   }   }
150   return sum;   return sum;
151  }  }
152    
153  int du_main(int argc, char **argv)  int du_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
154    int du_main(int argc UNUSED_PARAM, char **argv)
155  {  {
156   long total;   unsigned long total;
157   int slink_depth_save;   int slink_depth_save;
  int print_final_total;  
  char *smax_print_depth;  
158   unsigned opt;   unsigned opt;
159    
 #if ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K  
  if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */  
160  #if ENABLE_FEATURE_HUMAN_READABLE  #if ENABLE_FEATURE_HUMAN_READABLE
161   disp_hr = 512;   IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 1024;)
162     IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 512;)
163     if (getenv("POSIXLY_CORRECT"))  /* TODO - a new libbb function? */
164     G.disp_hr = 512;
165  #else  #else
166   disp_k = 0;   IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 1;)
167  #endif   /* IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */
  }  
168  #endif  #endif
169     G.max_print_depth = INT_MAX;
170    
171   /* Note: SUSv3 specifies that -a and -s options cannot be used together   /* Note: SUSv3 specifies that -a and -s options cannot be used together
172   * in strictly conforming applications.  However, it also says that some   * in strictly conforming applications.  However, it also says that some
# Line 168  int du_main(int argc, char **argv) Line 175  int du_main(int argc, char **argv)
175   * ignore -a.  This is consistent with -s being equivalent to -d 0.   * ignore -a.  This is consistent with -s being equivalent to -d 0.
176   */   */
177  #if ENABLE_FEATURE_HUMAN_READABLE  #if ENABLE_FEATURE_HUMAN_READABLE
178   opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s";   opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s:d+";
179   opt = getopt32(argc, argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth);   opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth);
180   if (opt & (1 << 9)) {   argv += optind;
181   /* -h opt */   if (opt & OPT_h_for_humans) {
182   disp_hr = 0;   G.disp_hr = 0;
183   }   }
184   if (opt & (1 << 10)) {   if (opt & OPT_m_mbytes) {
185   /* -m opt */   G.disp_hr = 1024*1024;
186   disp_hr = 1024*1024;   }
187   }   if (opt & OPT_k_kbytes) {
188   if (opt & (1 << 2)) {   G.disp_hr = 1024;
  /* -k opt */  
  disp_hr = 1024;  
189   }   }
190  #else  #else
191   opt_complementary = "H-L:L-H:s-d:d-s";   opt_complementary = "H-L:L-H:s-d:d-s:d+";
192   opt = getopt32(argc, argv, "aHkLsx" "d:" "lc", &smax_print_depth);   opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth);
193     argv += optind;
194  #if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K  #if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
195   if (opt & (1 << 2)) {   if (opt & OPT_k_kbytes) {
196   /* -k opt */   G.disp_k = 1;
  disp_k = 1;  
197   }   }
198  #endif  #endif
199  #endif  #endif
200   if (opt & (1 << 0)) {   if (opt & OPT_H_follow_links) {
201   /* -a opt */   G.slink_depth = 1;
202   print_files = INT_MAX;   }
203   }   if (opt & OPT_L_follow_links) {
204   if (opt & (1 << 1)) {   G.slink_depth = INT_MAX;
205   /* -H opt */   }
206   slink_depth = 1;   if (opt & OPT_s_total_norecurse) {
207   }   G.max_print_depth = 0;
  if (opt & (1 << 3)) {  
  /* -L opt */  
  slink_depth = INT_MAX;  
  }  
  if (opt & (1 << 4)) {  
  /* -s opt */  
  max_print_depth = 0;  
  }  
  one_file_system = opt & (1 << 5); /* -x opt */  
  if (opt & (1 << 6)) {  
  /* -d opt */  
  max_print_depth = xatoi_u(smax_print_depth);  
  }  
  if (opt & (1 << 7)) {  
  /* -l opt */  
  count_hardlinks = MAXINT(nlink_t);  
208   }   }
  print_final_total = opt & (1 << 8); /* -c opt */  
209    
210   /* go through remaining args (if any) */   /* go through remaining args (if any) */
211   argv += optind;   if (!*argv) {
212   if (optind >= argc) {   *--argv = (char*)".";
213   *--argv = ".";   if (G.slink_depth == 1) {
214   if (slink_depth == 1) {   G.slink_depth = 0;
  slink_depth = 0;  
215   }   }
216   }   }
217    
218   slink_depth_save = slink_depth;   slink_depth_save = G.slink_depth;
219   total = 0;   total = 0;
220   do {   do {
221   total += du(*argv);   total += du(*argv);
222   slink_depth = slink_depth_save;   /* otherwise du /dir /dir won't show /dir twice: */
223     reset_ino_dev_hashtable();
224     G.slink_depth = slink_depth_save;
225   } while (*++argv);   } while (*++argv);
 #if ENABLE_FEATURE_CLEAN_UP  
  reset_ino_dev_hashtable();  
 #endif  
226    
227   if (print_final_total) {   if (opt & OPT_c_total)
228   print(total, "total");   print(total, "total");
  }  
229    
230   fflush_stdout_and_exit(status);   fflush_stdout_and_exit(G.status);
231  }  }

Legend:
Removed from v.532  
changed lines
  Added in v.984