sulogin: use bb_error_msg instead of bb_info_msg; better message
[oweals/busybox.git] / coreutils / du.c
index 7a6662d1e02fd21f0558fb2aed346b4767feca30..1889c16bb13c0861bd82b6e46b428610a1245128 100644 (file)
 //usage:#define du_trivial_usage
 //usage:       "[-aHLdclsx" IF_FEATURE_HUMAN_READABLE("hm") "k] [FILE]..."
 //usage:#define du_full_usage "\n\n"
-//usage:       "Summarize disk space used for each FILE and/or directory.\n"
-//usage:       "Disk space is printed in units of "
-//usage:       IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K("1024")
-//usage:       IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K("512")
-//usage:       " bytes.\n"
-//usage:     "\nOptions:"
+//usage:       "Summarize disk space used for each FILE and/or directory\n"
 //usage:     "\n       -a      Show file sizes too"
 //usage:     "\n       -L      Follow all symlinks"
 //usage:     "\n       -H      Follow symlinks on command line"
 //usage:     "\n       -s      Display only a total for each argument"
 //usage:     "\n       -x      Skip directories on different filesystems"
 //usage:       IF_FEATURE_HUMAN_READABLE(
-//usage:     "\n       -h      Sizes in human readable format (e.g., 1K 243M 2G )"
+//usage:     "\n       -h      Sizes in human readable format (e.g., 1K 243M 2G)"
 //usage:     "\n       -m      Sizes in megabytes"
 //usage:       )
-//usage:     "\n       -k      Sizes in kilobytes"
-//usage:                       IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(" (default)")
+//usage:     "\n       -k      Sizes in kilobytes" IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(" (default)")
+//usage:       IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(
+//usage:     "\n               Default unit is 512 bytes"
+//usage:       )
 //usage:
 //usage:#define du_example_usage
 //usage:       "$ du\n"
@@ -78,7 +75,7 @@ enum {
 
 struct globals {
 #if ENABLE_FEATURE_HUMAN_READABLE
-       unsigned long disp_hr;
+       unsigned long disp_unit;
 #else
        unsigned disp_k;
 #endif
@@ -89,31 +86,45 @@ struct globals {
        dev_t dir_dev;
 } FIX_ALIASING;
 #define G (*(struct globals*)&bb_common_bufsiz1)
+#define INIT_G() do { } while (0)
 
 
-static void print(unsigned long size, const char *filename)
+static void print(unsigned long long size, const char *filename)
 {
        /* TODO - May not want to defer error checking here. */
 #if ENABLE_FEATURE_HUMAN_READABLE
+# if ENABLE_DESKTOP
+       /* ~30 bytes of code for extra comtat:
+        * coreutils' du rounds sizes up:
+        * for example,  1025k file is shown as "2" by du -m.
+        * We round to nearest if human-readable [too hard to fix],
+        * else (fixed scale such as -m), we round up. To that end,
+        * add yet another half of the unit before displaying:
+        */
+       if (G.disp_unit)
+               size += (G.disp_unit-1) / (unsigned)(512 * 2);
+# endif
        printf("%s\t%s\n",
-                       /* size x 512 / G.disp_hr, show one fractional,
-                        * use suffixes if G.disp_hr == 0 */
-                       make_human_readable_str(size, 512, G.disp_hr),
+                       /* size x 512 / G.disp_unit.
+                        * If G.disp_unit == 0, show one fractional
+                        * and use suffixes
+                        */
+                       make_human_readable_str(size, 512, G.disp_unit),
                        filename);
 #else
        if (G.disp_k) {
                size++;
                size >>= 1;
        }
-       printf("%lu\t%s\n", size, filename);
+       printf("%llu\t%s\n", size, filename);
 #endif
 }
 
 /* tiny recursive du */
-static unsigned long du(const char *filename)
+static unsigned long long du(const char *filename)
 {
        struct stat statbuf;
-       unsigned long sum;
+       unsigned long long sum;
 
        if (lstat(filename, &statbuf) != 0) {
                bb_simple_perror_msg(filename);
@@ -190,15 +201,17 @@ static unsigned long du(const char *filename)
 int du_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int du_main(int argc UNUSED_PARAM, char **argv)
 {
-       unsigned long total;
+       unsigned long long total;
        int slink_depth_save;
        unsigned opt;
 
+       INIT_G();
+
 #if ENABLE_FEATURE_HUMAN_READABLE
-       IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 1024;)
-       IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 512;)
+       IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_unit = 1024;)
+       IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_unit = 512;)
        if (getenv("POSIXLY_CORRECT"))  /* TODO - a new libbb function? */
-               G.disp_hr = 512;
+               G.disp_unit = 512;
 #else
        IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 1;)
        /* IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */
@@ -216,13 +229,13 @@ int du_main(int argc UNUSED_PARAM, char **argv)
        opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth);
        argv += optind;
        if (opt & OPT_h_for_humans) {
-               G.disp_hr = 0;
+               G.disp_unit = 0;
        }
        if (opt & OPT_m_mbytes) {
-               G.disp_hr = 1024*1024;
+               G.disp_unit = 1024*1024;
        }
        if (opt & OPT_k_kbytes) {
-               G.disp_hr = 1024;
+               G.disp_unit = 1024;
        }
 #else
        opt_complementary = "H-L:L-H:s-d:d-s:d+";