new copyright notice
[unix-history] / usr / src / usr.bin / du / du.c
CommitLineData
20ff9060
KB
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 *
f15db449 8 * %sccs.include.redist.c%
20ff9060
KB
9 */
10
fbdb528f 11#ifndef lint
20ff9060
KB
12char copyright[] =
13"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
14 All rights reserved.\n";
15#endif /* not lint */
16
17#ifndef lint
f15db449 18static char sccsid[] = "@(#)du.c 5.6 (Berkeley) %G%";
20ff9060 19#endif /* not lint */
fbdb528f 20
ca4a89e1
BJ
21#include <sys/param.h>
22#include <sys/stat.h>
20ff9060 23#include <dirent.h>
38dde0cd 24#include <string.h>
20ff9060 25#include <stdio.h>
fbdb528f 26
20ff9060
KB
27typedef struct _ID {
28 dev_t dev;
29 ino_t inode;
30} ID;
e29a75fd 31
20ff9060
KB
32ID *files;
33dev_t device;
3f900164 34int crossmounts, kvalue, listdirs, listfiles, maxfiles, numfiles;
20ff9060 35char path[MAXPATHLEN + 1];
905d30b9 36
ca4a89e1 37main(argc, argv)
e29a75fd
BJ
38 int argc;
39 char **argv;
ca4a89e1 40{
20ff9060 41 extern int optind, errno;
17372837 42 int ch;
20ff9060 43 char *malloc(), top[MAXPATHLEN + 1];
ca4a89e1 44
20ff9060 45 listdirs = crossmounts = 1;
3f900164 46 while ((ch = getopt(argc, argv, "aksx")) != EOF)
20ff9060
KB
47 switch(ch) {
48 case 'a':
49 listfiles = 1;
50 break;
3f900164
KB
51 case 'k':
52 kvalue = 1;
53 break;
20ff9060
KB
54 case 's':
55 listfiles = listdirs = 0;
56 break;
57 case 'x':
58 crossmounts = 0;
59 break;
60 case '?':
61 default:
3f900164
KB
62 (void)fprintf(stderr,
63 "usage: du [-aksx] [name ...]\n");
20ff9060 64 exit(1);
dd610901 65 }
20ff9060
KB
66 argv += optind;
67
68 files = (ID *)malloc((u_int)(sizeof(ID) * (maxfiles = 128)));
69
70 if (!*argv)
71 du(".");
72 else {
73 if (argv[1])
74 (void)getwd(top);
17372837 75 for (;;) {
20ff9060 76 du(*argv);
17372837
KB
77 if (!*++argv)
78 break;
79 if (chdir(top)) {
20ff9060
KB
80 (void)fprintf(stderr, "du: %s: %s\n",
81 top, strerror(errno));
dd610901 82 exit(1);
20ff9060 83 }
dd610901 84 }
20ff9060 85 }
ca4a89e1
BJ
86 exit(0);
87}
88
20ff9060 89struct stat info;
e29a75fd 90
20ff9060
KB
91du(arg)
92 register char *arg;
ca4a89e1 93{
20ff9060
KB
94 extern int errno;
95 u_long total, descend();
ca4a89e1 96
20ff9060 97 if (lstat(arg, &info)) {
ee63d32b 98 (void)fprintf(stderr, "du: %s: %s\n", arg, strerror(errno));
20ff9060 99 return;
ca4a89e1 100 }
20ff9060 101 if ((info.st_mode&S_IFMT) != S_IFDIR) {
3f900164
KB
102 (void)printf("%ld\t%s\n", kvalue ?
103 howmany(info.st_blocks, 2) : info.st_blocks, arg);
20ff9060 104 return;
fbdb528f 105 }
20ff9060
KB
106 device = info.st_dev;
107 (void)strcpy(path, arg);
108 total = descend(path);
109 if (!listfiles && !listdirs)
3f900164
KB
110 (void)printf("%lu\t%s\n",
111 kvalue ? howmany(total, 2) : total, path);
20ff9060
KB
112}
113
114u_long
115descend(endp)
116 register char *endp;
117{
118 extern int errno;
119 register DIR *dir;
120 register ID *fp;
121 register struct dirent *dp;
122 u_long total;
123 char *realloc();
124
125 if (info.st_nlink > 1) {
126 for (fp = files + numfiles - 1; fp >= files; --fp)
127 if (info.st_ino == fp->inode &&
128 info.st_dev == fp->dev)
129 return(0L);
130 if (numfiles == maxfiles)
131 files = (ID *)realloc((char *)files,
132 (u_int)(sizeof(ID) * (maxfiles += 128)));
133 files[numfiles].inode = info.st_ino;
134 files[numfiles].dev = info.st_dev;
135 ++numfiles;
a1a73cfc 136 }
20ff9060
KB
137 total = info.st_blocks;
138 if ((info.st_mode&S_IFMT) == S_IFDIR) {
139 if (info.st_dev != device && !crossmounts)
140 return(0L);
141 if (chdir(endp) || !(dir = opendir("."))) {
3f900164
KB
142 (void)fprintf(stderr, "du: %s: %s\n",
143 path, strerror(errno));
20ff9060
KB
144 return(total);
145 }
146 for (; *endp; ++endp);
147 if (endp[-1] != '/')
148 *endp++ = '/';
149 while (dp = readdir(dir)) {
150 if (dp->d_name[0] == '.' && (!dp->d_name[1] ||
151 dp->d_name[1] == '.' && !dp->d_name[2]))
152 continue;
153 bcopy(dp->d_name, endp, dp->d_namlen + 1);
154 if (lstat(dp->d_name, &info)) {
155 (void)fprintf(stderr, "du: %s: %s\n", path,
156 strerror(errno));
157 continue;
a1a73cfc 158 }
20ff9060 159 total += descend(endp);
ca4a89e1 160 }
20ff9060
KB
161 closedir(dir);
162 if (chdir("..")) {
3f900164 163 (void)fprintf(stderr, "du: ..: %s\n", strerror(errno));
20ff9060
KB
164 exit(1);
165 }
166 *--endp = '\0';
167 if (listdirs)
3f900164
KB
168 (void)printf("%lu\t%s\n",
169 kvalue ? howmany(total, 2) : total, path);
ca4a89e1 170 }
20ff9060 171 else if (listfiles)
3f900164
KB
172 (void)printf("%lu\t%s\n",
173 kvalue ? howmany(total, 2) : total, path);
20ff9060 174 return(total);
ca4a89e1 175}