Initial import, 0.1 + pk 0.2.4-B1
[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
44static char sccsid[] = "@(#)du.c 5.12 (Berkeley) 6/20/91";
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
56main(argc, argv)
57 int argc;
58 char **argv;
59{
60 extern int optind;
61 register FTS *fts;
62 register FTSENT *p;
63 register int kvalue, listdirs, listfiles;
64 int aflag, ch, ftsoptions, sflag;
65 char **save;
66
67 ftsoptions = FTS_PHYSICAL;
68 kvalue = 0;
69 save = argv;
70 aflag = sflag = 0;
71 while ((ch = getopt(argc, argv, "aksx")) != EOF)
72 switch(ch) {
73 case 'a':
74 aflag = 1;
75 break;
76 case 'k':
77 kvalue = 1;
78 break;
79 case 's':
80 sflag = 1;
81 break;
82 case 'x':
83 ftsoptions |= FTS_XDEV;
84 break;
85 case '?':
86 default:
87 usage();
88 }
89 argv += optind;
90
91 if (aflag) {
92 if (sflag)
93 usage();
94 listdirs = listfiles = 1;
95 } else if (sflag)
96 listdirs = listfiles = 0;
97 else {
98 listfiles = 0;
99 listdirs = 1;
100 }
101
102 if (!*argv) {
103 argv = save;
104 argv[0] = ".";
105 argv[1] = NULL;
106 }
107
108 if (!(fts = fts_open(argv, ftsoptions, (int (*)())NULL))) {
109 (void)fprintf(stderr, "du: %s.\n", strerror(errno));
110 exit(1);
111 }
112
113 while (p = fts_read(fts))
114 switch(p->fts_info) {
115 case FTS_D:
116 break;
117 case FTS_DP:
118 p->fts_parent->fts_number +=
119 p->fts_number += p->fts_statb.st_blocks;
120 /*
121 * If listing each directory, or not listing files
122 * or directories and this is post-order of the
123 * root of a traversal, display the total.
124 */
125 if (listdirs || !listfiles && !p->fts_level)
126 (void)printf("%ld\t%s\n", kvalue ?
127 howmany(p->fts_number, 2) :
128 p->fts_number, p->fts_path);
129 break;
130 case FTS_DNR:
131 case FTS_ERR:
132 case FTS_NS:
133 (void)fprintf(stderr,
134 "du: %s: %s.\n", p->fts_path, strerror(errno));
135 break;
136 case FTS_SL:
137 if (p->fts_level == FTS_ROOTLEVEL) {
138 (void)fts_set(fts, p, FTS_FOLLOW);
139 break;
140 }
141 /* FALLTHROUGH */
142 default:
143 if (p->fts_statb.st_nlink > 1 && linkchk(p))
144 break;
145 /*
146 * If listing each file, or a non-directory file was
147 * the root of a traversal, display the total.
148 */
149 if (listfiles || !p->fts_level)
150 (void)printf("%ld\t%s\n", kvalue ?
151 howmany(p->fts_statb.st_blocks, 2) :
152 p->fts_statb.st_blocks, p->fts_path);
153 p->fts_parent->fts_number += p->fts_statb.st_blocks;
154 }
155 exit(0);
156}
157
158typedef struct _ID {
159 dev_t dev;
160 ino_t inode;
161} ID;
162
163linkchk(p)
164 register FTSENT *p;
165{
166 static ID *files;
167 static int maxfiles, nfiles;
168 register ID *fp, *start;
169 register ino_t ino;
170 register dev_t dev;
171
172 ino = p->fts_statb.st_ino;
173 dev = p->fts_statb.st_dev;
174 if (start = files)
175 for (fp = start + nfiles - 1; fp >= start; --fp)
176 if (ino == fp->inode && dev == fp->dev)
177 return(1);
178
179 if (nfiles == maxfiles && !(files = (ID *)realloc((char *)files,
180 (u_int)(sizeof(ID) * (maxfiles += 128))))) {
181 (void)fprintf(stderr, "du: %s\n", strerror(errno));
182 exit(1);
183 }
184 files[nfiles].inode = ino;
185 files[nfiles].dev = dev;
186 ++nfiles;
187 return(0);
188}
189
190usage()
191{
192 (void)fprintf(stderr, "usage: du [-a | -s] [-kx] [file ...]\n");
193 exit(1);
194}