This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / usr.bin / du / du.c
CommitLineData
15637ed4
RG
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
38char 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
78ed81a3 44static char sccsid[] = "@(#)du.c 5.17 (Berkeley) 5/20/92";
15637ed4
RG
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
78ed81a3 56void err __P((const char *, ...));
57char *getbsize __P((char *, int *, long *));
58int linkchk __P((FTSENT *));
59void usage __P((void));
60
61int kflag;
62
15637ed4
RG
63main(argc, argv)
64 int argc;
78ed81a3 65 char *argv[];
15637ed4 66{
15637ed4
RG
67 register FTS *fts;
68 register FTSENT *p;
78ed81a3 69 register int listdirs, listfiles;
70 long blocksize;
71 int aflag, ch, ftsoptions, notused, sflag;
15637ed4
RG
72 char **save;
73
74 ftsoptions = FTS_PHYSICAL;
15637ed4 75 save = argv;
78ed81a3 76 aflag = kflag = sflag = 0;
15637ed4
RG
77 while ((ch = getopt(argc, argv, "aksx")) != EOF)
78 switch(ch) {
79 case 'a':
80 aflag = 1;
81 break;
82 case 'k':
78ed81a3 83 kflag = 1;
15637ed4
RG
84 break;
85 case 's':
86 sflag = 1;
87 break;
88 case 'x':
89 ftsoptions |= FTS_XDEV;
90 break;
91 case '?':
92 default:
93 usage();
94 }
95 argv += optind;
96
97 if (aflag) {
98 if (sflag)
99 usage();
100 listdirs = listfiles = 1;
101 } else if (sflag)
102 listdirs = listfiles = 0;
103 else {
104 listfiles = 0;
105 listdirs = 1;
106 }
107
108 if (!*argv) {
109 argv = save;
110 argv[0] = ".";
111 argv[1] = NULL;
112 }
113
78ed81a3 114 (void)getbsize("du", &notused, &blocksize);
115 blocksize /= 512;
116
117 if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
118 err("%s", strerror(errno));
15637ed4
RG
119
120 while (p = fts_read(fts))
121 switch(p->fts_info) {
122 case FTS_D:
123 break;
124 case FTS_DP:
125 p->fts_parent->fts_number +=
78ed81a3 126 p->fts_number += p->fts_statp->st_blocks;
15637ed4
RG
127 /*
128 * If listing each directory, or not listing files
129 * or directories and this is post-order of the
130 * root of a traversal, display the total.
131 */
132 if (listdirs || !listfiles && !p->fts_level)
78ed81a3 133 (void)printf("%ld\t%s\n",
134 howmany(p->fts_number, blocksize),
135 p->fts_path);
15637ed4
RG
136 break;
137 case FTS_DNR:
138 case FTS_ERR:
139 case FTS_NS:
140 (void)fprintf(stderr,
78ed81a3 141 "du: %s: %s\n", p->fts_path, strerror(errno));
15637ed4
RG
142 break;
143 case FTS_SL:
144 if (p->fts_level == FTS_ROOTLEVEL) {
145 (void)fts_set(fts, p, FTS_FOLLOW);
146 break;
147 }
148 /* FALLTHROUGH */
149 default:
78ed81a3 150 if (p->fts_statp->st_nlink > 1 && linkchk(p))
15637ed4
RG
151 break;
152 /*
153 * If listing each file, or a non-directory file was
154 * the root of a traversal, display the total.
155 */
156 if (listfiles || !p->fts_level)
78ed81a3 157 (void)printf("%ld\t%s\n",
158 howmany(p->fts_statp->st_blocks, blocksize),
159 p->fts_path);
160 p->fts_parent->fts_number += p->fts_statp->st_blocks;
15637ed4 161 }
78ed81a3 162 if (errno)
163 err("%s", strerror(errno));
15637ed4
RG
164 exit(0);
165}
166
167typedef struct _ID {
168 dev_t dev;
169 ino_t inode;
170} ID;
171
78ed81a3 172int
15637ed4
RG
173linkchk(p)
174 register FTSENT *p;
175{
176 static ID *files;
177 static int maxfiles, nfiles;
178 register ID *fp, *start;
179 register ino_t ino;
180 register dev_t dev;
181
78ed81a3 182 ino = p->fts_statp->st_ino;
183 dev = p->fts_statp->st_dev;
15637ed4
RG
184 if (start = files)
185 for (fp = start + nfiles - 1; fp >= start; --fp)
186 if (ino == fp->inode && dev == fp->dev)
187 return(1);
188
78ed81a3 189 if (nfiles == maxfiles && (files = realloc((char *)files,
190 (u_int)(sizeof(ID) * (maxfiles += 128)))) == NULL)
191 err("%s", strerror(errno));
15637ed4
RG
192 files[nfiles].inode = ino;
193 files[nfiles].dev = dev;
194 ++nfiles;
195 return(0);
196}
197
78ed81a3 198void
15637ed4
RG
199usage()
200{
78ed81a3 201 (void)fprintf(stderr, "usage: du [-a | -s] [-x] [file ...]\n");
202 exit(1);
203}
204
205#if __STDC__
206#include <stdarg.h>
207#else
208#include <varargs.h>
209#endif
210
211void
212#if __STDC__
213err(const char *fmt, ...)
214#else
215err(fmt, va_alist)
216 char *fmt;
217 va_dcl
218#endif
219{
220 va_list ap;
221#if __STDC__
222 va_start(ap, fmt);
223#else
224 va_start(ap);
225#endif
226 (void)fprintf(stderr, "du: ");
227 (void)vfprintf(stderr, fmt, ap);
228 va_end(ap);
229 (void)fprintf(stderr, "\n");
15637ed4 230 exit(1);
78ed81a3 231 /* NOTREACHED */
15637ed4 232}