home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / du / du.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-20  |  5.5 KB  |  228 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Chris Newcomb.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. char copyright[] =
  39. "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  40.  All rights reserved.\n";
  41. #endif /* not lint */
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@(#)du.c    5.17 (Berkeley) 5/20/92";
  45. #endif /* not lint */
  46.  
  47. #include <sys/param.h>
  48. #include <sys/stat.h>
  49. #include <sys/errno.h>
  50. #include <dirent.h>
  51. #include <stdio.h>
  52. #include <fts.h>
  53. #include <string.h>
  54. #include <stdlib.h>
  55.  
  56. void     err __P((const char *, ...));
  57. char    *getbsize __P((char *, int *, long *));
  58. int     linkchk __P((FTSENT *));
  59. void     usage __P((void));
  60.  
  61. main(argc, argv)
  62.     int argc;
  63.     char *argv[];
  64. {
  65.     register FTS *fts;
  66.     register FTSENT *p;
  67.     register int listdirs, listfiles;
  68.     long blocksize;
  69.     int aflag, ch, ftsoptions, notused, sflag;
  70.     char **save;
  71.  
  72.     ftsoptions = FTS_PHYSICAL;
  73.     save = argv;
  74.     aflag = sflag = 0;
  75.     while ((ch = getopt(argc, argv, "asx")) != EOF)
  76.         switch(ch) {
  77.         case 'a':
  78.             aflag = 1;
  79.             break;
  80.         case 's':
  81.             sflag = 1;
  82.             break;
  83.         case 'x':
  84.             ftsoptions |= FTS_XDEV;
  85.             break;
  86.         case '?':
  87.         default:
  88.             usage();
  89.         }
  90.     argv += optind;
  91.  
  92.     if (aflag) {
  93.         if (sflag)
  94.             usage();
  95.         listdirs = listfiles = 1;
  96.     } else if (sflag)
  97.         listdirs = listfiles = 0;
  98.     else {
  99.         listfiles = 0;
  100.         listdirs = 1;
  101.     }
  102.  
  103.     if (!*argv) {
  104.         argv = save;
  105.         argv[0] = ".";
  106.         argv[1] = NULL;
  107.     }
  108.  
  109.     (void)getbsize("du", ¬used, &blocksize);
  110.     blocksize /= 512;
  111.  
  112.     if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
  113.         err("%s", strerror(errno));
  114.  
  115.     while (p = fts_read(fts))
  116.         switch(p->fts_info) {
  117.         case FTS_D:
  118.             break;
  119.         case FTS_DP:
  120.             p->fts_parent->fts_number += 
  121.                 p->fts_number += p->fts_statp->st_blocks;
  122.             /*
  123.              * If listing each directory, or not listing files
  124.              * or directories and this is post-order of the
  125.              * root of a traversal, display the total.
  126.              */
  127.             if (listdirs || !listfiles && !p->fts_level)
  128.                 (void)printf("%ld\t%s\n",
  129.                     howmany(p->fts_number, blocksize),
  130.                     p->fts_path);
  131.             break;
  132.         case FTS_DNR:
  133.         case FTS_ERR:
  134.         case FTS_NS:
  135.             (void)fprintf(stderr,
  136.                 "du: %s: %s\n", p->fts_path, strerror(errno));
  137.             break;
  138.         case FTS_SL:
  139.             if (p->fts_level == FTS_ROOTLEVEL) {
  140.                 (void)fts_set(fts, p, FTS_FOLLOW);
  141.                 break;
  142.             }
  143.             /* FALLTHROUGH */
  144.         default:
  145.             if (p->fts_statp->st_nlink > 1 && linkchk(p))
  146.                 break;
  147.             /*
  148.              * If listing each file, or a non-directory file was
  149.              * the root of a traversal, display the total.
  150.              */
  151.             if (listfiles || !p->fts_level)
  152.                 (void)printf("%ld\t%s\n",
  153.                     howmany(p->fts_statp->st_blocks, blocksize),
  154.                     p->fts_path);
  155.             p->fts_parent->fts_number += p->fts_statp->st_blocks;
  156.         }
  157.     if (errno)
  158.         err("%s", strerror(errno));
  159.     exit(0);
  160. }
  161.  
  162. typedef struct _ID {
  163.     dev_t    dev;
  164.     ino_t    inode;
  165. } ID;
  166.  
  167. int
  168. linkchk(p)
  169.     register FTSENT *p;
  170. {
  171.     static ID *files;
  172.     static int maxfiles, nfiles;
  173.     register ID *fp, *start;
  174.     register ino_t ino;
  175.     register dev_t dev;
  176.  
  177.     ino = p->fts_statp->st_ino;
  178.     dev = p->fts_statp->st_dev;
  179.     if (start = files)
  180.         for (fp = start + nfiles - 1; fp >= start; --fp)
  181.             if (ino == fp->inode && dev == fp->dev)
  182.                 return(1);
  183.  
  184.     if (nfiles == maxfiles && (files = realloc((char *)files,
  185.         (u_int)(sizeof(ID) * (maxfiles += 128)))) == NULL)
  186.         err("%s", strerror(errno));
  187.     files[nfiles].inode = ino;
  188.     files[nfiles].dev = dev;
  189.     ++nfiles;
  190.     return(0);
  191. }
  192.  
  193. void
  194. usage()
  195. {
  196.     (void)fprintf(stderr, "usage: du [-a | -s] [-x] [file ...]\n");
  197.     exit(1);
  198. }
  199.  
  200. #if __STDC__
  201. #include <stdarg.h>
  202. #else
  203. #include <varargs.h>
  204. #endif
  205.  
  206. void
  207. #if __STDC__
  208. err(const char *fmt, ...)
  209. #else
  210. err(fmt, va_alist)
  211.     char *fmt;
  212.         va_dcl
  213. #endif
  214. {
  215.     va_list ap;
  216. #if __STDC__
  217.     va_start(ap, fmt);
  218. #else
  219.     va_start(ap);
  220. #endif
  221.     (void)fprintf(stderr, "du: ");
  222.     (void)vfprintf(stderr, fmt, ap);
  223.     va_end(ap);
  224.     (void)fprintf(stderr, "\n");
  225.     exit(1);
  226.     /* NOTREACHED */
  227. }
  228.