Print this page
7967 Want apparent size option for du(1)
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: Dan McDonald <danmcd@omniti.com>


   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*

  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  27 /*        All Rights Reserved   */
  28 
  29 #pragma ident   "%Z%%M% %I%     %E% SMI"
  30 
  31 /*
  32  * du -- summarize disk usage
  33  *      du [-dorx] [-a|-s] [-h|-k|-m] [-H|-L] [file...]
  34  */
  35 
  36 #include <sys/types.h>
  37 #include <sys/stat.h>
  38 #include <sys/avl.h>
  39 #include <fcntl.h>
  40 #include <dirent.h>
  41 #include <limits.h>
  42 #include <stdio.h>
  43 #include <stdlib.h>
  44 #include <string.h>
  45 #include <unistd.h>
  46 #include <locale.h>
  47 #include <libcmdutils.h>
  48 
  49 
  50 static int              aflg = 0;
  51 static int              rflg = 0;
  52 static int              sflg = 0;
  53 static int              kflg = 0;
  54 static int              mflg = 0;
  55 static int              oflg = 0;
  56 static int              dflg = 0;
  57 static int              hflg = 0;

  58 static int              Hflg = 0;
  59 static int              Lflg = 0;
  60 static int              cmdarg = 0;     /* Command line argument */
  61 static char             *dot = ".";
  62 static int              level = 0;      /* Level of recursion */
  63 
  64 static char             *base;
  65 static char             *name;
  66 static size_t           base_len = PATH_MAX + 1;    /* # of chars for base */
  67 static size_t           name_len = PATH_MAX + 1;    /* # of chars for name */
  68 
  69 #define NUMBER_WIDTH    64
  70 typedef char            numbuf_t[NUMBER_WIDTH];
  71 
  72 /*
  73  * Output formats.  Solaris uses a tab as separator, XPG4 a space.
  74  */
  75 #ifdef XPG4
  76 #define FORMAT1 "%s %s\n"
  77 #define FORMAT2 "%lld %s\n"
  78 #else
  79 #define FORMAT1 "%s\t%s\n"
  80 #define FORMAT2 "%lld\t%s\n"
  81 #endif
  82 
  83 /*
  84  * convert DEV_BSIZE blocks to K blocks
  85  */
  86 #define DEV_BSIZE       512
  87 #define DEV_KSHIFT      1
  88 #define DEV_MSHIFT      11
  89 #define kb(n)           (((u_longlong_t)(n)) >> DEV_KSHIFT)
  90 #define mb(n)           (((u_longlong_t)(n)) >> DEV_MSHIFT)
  91 
  92 long    wait();
  93 static u_longlong_t     descend(char *curname, int curfd, int *retcode,


 100 int
 101 main(int argc, char **argv)
 102 {
 103         blkcnt_t        blocks = 0;
 104         int             c;
 105         extern int      optind;
 106         char            *np;
 107         pid_t           pid, wpid;
 108         int             status, retcode = 0;
 109         setbuf(stderr, NULL);
 110         (void) setlocale(LC_ALL, "");
 111 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 112 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it weren't */
 113 #endif
 114         (void) textdomain(TEXT_DOMAIN);
 115 
 116 #ifdef XPG4
 117         rflg++;         /* "-r" is not an option but ON always */
 118 #endif
 119 
 120         while ((c = getopt(argc, argv, "adhHkLmorsx")) != EOF)
 121                 switch (c) {
 122 
 123                 case 'a':
 124                         aflg++;
 125                         continue;
 126 
 127                 case 'h':
 128                         hflg++;
 129                         kflg = 0;
 130                         mflg = 0;
 131                         continue;
 132 
 133                 case 'r':
 134                         rflg++;
 135                         continue;
 136 
 137                 case 's':
 138                         sflg++;
 139                         continue;
 140 


 145                         continue;
 146 
 147                 case 'm':
 148                         mflg++;
 149                         hflg = 0;
 150                         kflg = 0;
 151                         continue;
 152 
 153                 case 'o':
 154                         oflg++;
 155                         continue;
 156 
 157                 case 'd':
 158                         dflg++;
 159                         continue;
 160 
 161                 case 'x':
 162                         dflg++;
 163                         continue;
 164 




 165                 case 'H':
 166                         Hflg++;
 167                         /* -H and -L are mutually exclusive */
 168                         Lflg = 0;
 169                         cmdarg++;
 170                         continue;
 171 
 172                 case 'L':
 173                         Lflg++;
 174                         /* -H and -L are mutually exclusive */
 175                         Hflg = 0;
 176                         cmdarg = 0;
 177                         continue;
 178                 case '?':
 179                         (void) fprintf(stderr, gettext(
 180                             "usage: du [-dorx] [-a|-s] [-h|-k|-m] [-H|-L] "
 181                             "[file...]\n"));
 182                         exit(2);
 183                 }
 184         if (optind == argc) {
 185                 argv = &dot;
 186                 argc = 1;
 187                 optind = 0;
 188         }
 189 
 190         /* "-o" and "-s" don't make any sense together. */
 191         if (oflg && sflg)
 192                 oflg = 0;
 193 
 194         if ((base = (char *)calloc(base_len, sizeof (char))) == NULL) {
 195                 perror("du");
 196                 exit(1);
 197         }
 198         if ((name = (char *)calloc(name_len, sizeof (char))) == NULL) {
 199                 perror("du");
 200                 free(base);


 362                 int rc;
 363                 if ((rc = add_tnode(&tree, stb.st_dev, stb.st_ino)) != 1) {
 364                         if (rc == 0) {
 365                                 /*
 366                                  * This hierarchy, or file with multiple
 367                                  * links, has already been visited/reported.
 368                                  */
 369                                 return (0);
 370                         } else {
 371                                 /*
 372                                  * An error occurred while trying to add the
 373                                  * node to the tree.
 374                                  */
 375                                 if (rflg) {
 376                                         perror("du");
 377                                 }
 378                                 exitdu(1);
 379                         }
 380                 }
 381         }
 382         blocks = stb.st_blocks;

 383         /*
 384          * If there are extended attributes on the current file, add their
 385          * block usage onto the block count.  Note: Since pathconf() always
 386          * follows symlinks, only test for extended attributes using pathconf()
 387          * if we are following symlinks or the current file is not a symlink.
 388          */
 389         if (curname && (follow_symlinks ||
 390             ((stb.st_mode & S_IFMT) != S_IFLNK)) &&
 391             pathconf(curname, _PC_XATTR_EXISTS) == 1) {
 392                 if ((fd = attropen(curname, ".", O_RDONLY)) < 0) {
 393                         if (rflg)
 394                                 perror(gettext(
 395                                     "du: can't access extended attributes"));
 396                 }
 397                 else
 398                 {
 399                         tmpflg = sflg;
 400                         sflg = 1;
 401                         blocks += descend(NULL, fd, retcode, device);
 402                         sflg = tmpflg;


 578         while ((number >= scale) && (*uom != 'E')) {
 579                 uom++; /* next unit of measurement */
 580                 save = number;
 581                 number = (number + (scale / 2)) / scale;
 582         }
 583 
 584         /* check if we should output a decimal place after the point */
 585         if (save && ((save / scale) < 10)) {
 586                 /* sprintf() will round for us */
 587                 float fnum = (float)save / scale;
 588                 (void) sprintf(buf, "%4.1f%c", fnum, *uom);
 589         } else {
 590                 (void) sprintf(buf, "%4llu%c", number, *uom);
 591         }
 592         return (buf);
 593 }
 594 
 595 static void
 596 printsize(blkcnt_t blocks, char *path)
 597 {




 598         if (hflg) {
 599                 numbuf_t numbuf;
 600                 unsigned long long scale = 1024L;
 601                 (void) printf(FORMAT1,
 602                     number_to_scaled_string(numbuf, blocks, DEV_BSIZE, scale),
 603                     path);
 604         } else if (kflg) {
 605                 (void) printf(FORMAT2, (long long)kb(blocks), path);
 606         } else if (mflg) {
 607                 (void) printf(FORMAT2, (long long)mb(blocks), path);
 608         } else {
 609                 (void) printf(FORMAT2, (long long)blocks, path);
 610         }
 611 }
 612 
 613 static void
 614 exitdu(int exitcode)
 615 {
 616         free(base);
 617         free(name);
 618         exit(exitcode);
 619 }


   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2017 OmniTI Computer Consulting, Inc.  All rights reserved.
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  28 /*        All Rights Reserved   */
  29 


  30 /*
  31  * du -- summarize disk usage
  32  *      du [-Adorx] [-a|-s] [-h|-k|-m] [-H|-L] [file...]
  33  */
  34 
  35 #include <sys/types.h>
  36 #include <sys/stat.h>
  37 #include <sys/avl.h>
  38 #include <fcntl.h>
  39 #include <dirent.h>
  40 #include <limits.h>
  41 #include <stdio.h>
  42 #include <stdlib.h>
  43 #include <string.h>
  44 #include <unistd.h>
  45 #include <locale.h>
  46 #include <libcmdutils.h>
  47 
  48 
  49 static int              aflg = 0;
  50 static int              rflg = 0;
  51 static int              sflg = 0;
  52 static int              kflg = 0;
  53 static int              mflg = 0;
  54 static int              oflg = 0;
  55 static int              dflg = 0;
  56 static int              hflg = 0;
  57 static int              Aflg = 0;
  58 static int              Hflg = 0;
  59 static int              Lflg = 0;
  60 static int              cmdarg = 0;     /* Command line argument */
  61 static char             *dot = ".";
  62 static int              level = 0;      /* Level of recursion */
  63 
  64 static char             *base;
  65 static char             *name;
  66 static size_t           base_len = PATH_MAX + 1;    /* # of chars for base */
  67 static size_t           name_len = PATH_MAX + 1;    /* # of chars for name */
  68 
  69 #define NUMBER_WIDTH    64
  70 typedef char            numbuf_t[NUMBER_WIDTH];
  71 
  72 /*
  73  * Output formats. illumos uses a tab as separator, XPG4 a space.
  74  */
  75 #ifdef XPG4
  76 #define FORMAT1 "%s %s\n"
  77 #define FORMAT2 "%lld %s\n"
  78 #else
  79 #define FORMAT1 "%s\t%s\n"
  80 #define FORMAT2 "%lld\t%s\n"
  81 #endif
  82 
  83 /*
  84  * convert DEV_BSIZE blocks to K blocks
  85  */
  86 #define DEV_BSIZE       512
  87 #define DEV_KSHIFT      1
  88 #define DEV_MSHIFT      11
  89 #define kb(n)           (((u_longlong_t)(n)) >> DEV_KSHIFT)
  90 #define mb(n)           (((u_longlong_t)(n)) >> DEV_MSHIFT)
  91 
  92 long    wait();
  93 static u_longlong_t     descend(char *curname, int curfd, int *retcode,


 100 int
 101 main(int argc, char **argv)
 102 {
 103         blkcnt_t        blocks = 0;
 104         int             c;
 105         extern int      optind;
 106         char            *np;
 107         pid_t           pid, wpid;
 108         int             status, retcode = 0;
 109         setbuf(stderr, NULL);
 110         (void) setlocale(LC_ALL, "");
 111 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 112 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it weren't */
 113 #endif
 114         (void) textdomain(TEXT_DOMAIN);
 115 
 116 #ifdef XPG4
 117         rflg++;         /* "-r" is not an option but ON always */
 118 #endif
 119 
 120         while ((c = getopt(argc, argv, "aAdhHkLmorsx")) != EOF)
 121                 switch (c) {
 122 
 123                 case 'a':
 124                         aflg++;
 125                         continue;
 126 
 127                 case 'h':
 128                         hflg++;
 129                         kflg = 0;
 130                         mflg = 0;
 131                         continue;
 132 
 133                 case 'r':
 134                         rflg++;
 135                         continue;
 136 
 137                 case 's':
 138                         sflg++;
 139                         continue;
 140 


 145                         continue;
 146 
 147                 case 'm':
 148                         mflg++;
 149                         hflg = 0;
 150                         kflg = 0;
 151                         continue;
 152 
 153                 case 'o':
 154                         oflg++;
 155                         continue;
 156 
 157                 case 'd':
 158                         dflg++;
 159                         continue;
 160 
 161                 case 'x':
 162                         dflg++;
 163                         continue;
 164 
 165                 case 'A':
 166                         Aflg++;
 167                         continue;
 168 
 169                 case 'H':
 170                         Hflg++;
 171                         /* -H and -L are mutually exclusive */
 172                         Lflg = 0;
 173                         cmdarg++;
 174                         continue;
 175 
 176                 case 'L':
 177                         Lflg++;
 178                         /* -H and -L are mutually exclusive */
 179                         Hflg = 0;
 180                         cmdarg = 0;
 181                         continue;
 182                 case '?':
 183                         (void) fprintf(stderr, gettext(
 184                             "usage: du [-Adorx] [-a|-s] [-h|-k|-m] [-H|-L] "
 185                             "[file...]\n"));
 186                         exit(2);
 187                 }
 188         if (optind == argc) {
 189                 argv = &dot;
 190                 argc = 1;
 191                 optind = 0;
 192         }
 193 
 194         /* "-o" and "-s" don't make any sense together. */
 195         if (oflg && sflg)
 196                 oflg = 0;
 197 
 198         if ((base = (char *)calloc(base_len, sizeof (char))) == NULL) {
 199                 perror("du");
 200                 exit(1);
 201         }
 202         if ((name = (char *)calloc(name_len, sizeof (char))) == NULL) {
 203                 perror("du");
 204                 free(base);


 366                 int rc;
 367                 if ((rc = add_tnode(&tree, stb.st_dev, stb.st_ino)) != 1) {
 368                         if (rc == 0) {
 369                                 /*
 370                                  * This hierarchy, or file with multiple
 371                                  * links, has already been visited/reported.
 372                                  */
 373                                 return (0);
 374                         } else {
 375                                 /*
 376                                  * An error occurred while trying to add the
 377                                  * node to the tree.
 378                                  */
 379                                 if (rflg) {
 380                                         perror("du");
 381                                 }
 382                                 exitdu(1);
 383                         }
 384                 }
 385         }
 386         blocks = Aflg ? stb.st_size : stb.st_blocks;
 387 
 388         /*
 389          * If there are extended attributes on the current file, add their
 390          * block usage onto the block count.  Note: Since pathconf() always
 391          * follows symlinks, only test for extended attributes using pathconf()
 392          * if we are following symlinks or the current file is not a symlink.
 393          */
 394         if (curname && (follow_symlinks ||
 395             ((stb.st_mode & S_IFMT) != S_IFLNK)) &&
 396             pathconf(curname, _PC_XATTR_EXISTS) == 1) {
 397                 if ((fd = attropen(curname, ".", O_RDONLY)) < 0) {
 398                         if (rflg)
 399                                 perror(gettext(
 400                                     "du: can't access extended attributes"));
 401                 }
 402                 else
 403                 {
 404                         tmpflg = sflg;
 405                         sflg = 1;
 406                         blocks += descend(NULL, fd, retcode, device);
 407                         sflg = tmpflg;


 583         while ((number >= scale) && (*uom != 'E')) {
 584                 uom++; /* next unit of measurement */
 585                 save = number;
 586                 number = (number + (scale / 2)) / scale;
 587         }
 588 
 589         /* check if we should output a decimal place after the point */
 590         if (save && ((save / scale) < 10)) {
 591                 /* sprintf() will round for us */
 592                 float fnum = (float)save / scale;
 593                 (void) sprintf(buf, "%4.1f%c", fnum, *uom);
 594         } else {
 595                 (void) sprintf(buf, "%4llu%c", number, *uom);
 596         }
 597         return (buf);
 598 }
 599 
 600 static void
 601 printsize(blkcnt_t blocks, char *path)
 602 {
 603         u_longlong_t bsize;
 604 
 605         bsize = Aflg ? 1 : DEV_BSIZE;
 606 
 607         if (hflg) {
 608                 numbuf_t numbuf;
 609                 unsigned long long scale = 1024L;
 610                 (void) printf(FORMAT1,
 611                     number_to_scaled_string(numbuf, blocks, bsize, scale),
 612                     path);
 613         } else if (kflg) {
 614                 (void) printf(FORMAT2, (long long)kb(blocks), path);
 615         } else if (mflg) {
 616                 (void) printf(FORMAT2, (long long)mb(blocks), path);
 617         } else {
 618                 (void) printf(FORMAT2, (long long)blocks, path);
 619         }
 620 }
 621 
 622 static void
 623 exitdu(int exitcode)
 624 {
 625         free(base);
 626         free(name);
 627         exit(exitcode);
 628 }