xref: /original-bsd/usr.bin/du/du.c (revision 6386612b)
1 #ifndef lint
2 static char *sccsid = "@(#)du.c	4.11 (Berkeley) 07/01/83";
3 #endif
4 
5 #include <stdio.h>
6 #include <sys/param.h>
7 #include <sys/stat.h>
8 #include <sys/dir.h>
9 
10 char	path[BUFSIZ], name[BUFSIZ];
11 int	aflg;
12 int	sflg;
13 char	*dot = ".";
14 
15 #define ML	1000
16 struct {
17 	int	dev;
18 	ino_t	ino;
19 } ml[ML];
20 int	mlx;
21 
22 long	descend();
23 char	*index(), *rindex(), *strcpy(), *sprintf();
24 
25 #define	kb(n)	(howmany(dbtob(n), 1024))
26 
27 main(argc, argv)
28 	int argc;
29 	char **argv;
30 {
31 	long blocks = 0;
32 	register char *np;
33 	int pid;
34 
35 	argc--, argv++;
36 again:
37 	if (argc && !strcmp(*argv, "-s")) {
38 		sflg++;
39 		argc--, argv++;
40 		goto again;
41 	}
42 	if (argc && !strcmp(*argv, "-a")) {
43 		aflg++;
44 		argc--, argv++;
45 		goto again;
46 	}
47 	if (argc == 0) {
48 		argv = &dot;
49 		argc = 1;
50 	}
51 	do {
52 		if (argc > 1) {
53 			pid = fork();
54 			if (pid == -1) {
55 				fprintf(stderr, "No more processes.\n");
56 				exit(1);
57 			}
58 			if (pid != 0)
59 				wait((int *)0);
60 		}
61 		if (argc == 1 || pid == 0) {
62 			(void) strcpy(path, *argv);
63 			(void) strcpy(name, *argv);
64 			if (np = rindex(name, '/')) {
65 				*np++ = '\0';
66 				if (chdir(*name ? name : "/") < 0) {
67 					perror(*name ? name : "/");
68 					exit(1);
69 				}
70 			} else
71 				np = path;
72 			blocks = descend(path, *np ? np : ".");
73 			if (sflg)
74 				printf("%ld\t%s\n", kb(blocks), path);
75 			if (argc > 1)
76 				exit(1);
77 		}
78 		argc--, argv++;
79 	} while (argc > 0);
80 	exit(0);
81 }
82 
83 DIR	*dirp = NULL;
84 
85 long
86 descend(base, name)
87 	char *base, *name;
88 {
89 	char *ebase0, *ebase;
90 	struct stat stb;
91 	int i;
92 	long blocks = 0;
93 	long curoff = NULL;
94 	register struct direct *dp;
95 
96 	ebase0 = ebase = index(base, 0);
97 	if (ebase > base && ebase[-1] == '/')
98 		ebase--;
99 	if (lstat(name, &stb) < 0) {
100 		perror(base);
101 		*ebase0 = 0;
102 		return (0);
103 	}
104 	if (stb.st_nlink > 1 && (stb.st_mode&S_IFMT) != S_IFDIR) {
105 		for (i = 0; i <= mlx; i++)
106 			if (ml[i].ino == stb.st_ino && ml[i].dev == stb.st_dev)
107 				return (0);
108 		if (mlx < ML) {
109 			ml[mlx].dev = stb.st_dev;
110 			ml[mlx].ino = stb.st_ino;
111 			mlx++;
112 		}
113 	}
114 	blocks = stb.st_blocks;
115 	if ((stb.st_mode&S_IFMT) != S_IFDIR) {
116 		if (aflg)
117 			printf("%ld\t%s\n", kb(blocks), base);
118 		return (blocks);
119 	}
120 	if (dirp != NULL)
121 		closedir(dirp);
122 	dirp = opendir(name);
123 	if (dirp == NULL) {
124 		perror(base);
125 		*ebase0 = 0;
126 		return (0);
127 	}
128 	if (chdir(name) < 0) {
129 		perror(base);
130 		*ebase0 = 0;
131 		closedir(dirp);
132 		dirp = NULL;
133 		return (0);
134 	}
135 	while (dp = readdir(dirp)) {
136 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
137 			continue;
138 		(void) sprintf(ebase, "/%s", dp->d_name);
139 		curoff = telldir(dirp);
140 		blocks += descend(base, ebase+1);
141 		*ebase = 0;
142 		if (dirp == NULL) {
143 			dirp = opendir(".");
144 			if (dirp == NULL) {
145 				perror(".");
146 				return (0);
147 			}
148 			seekdir(dirp, curoff);
149 		}
150 	}
151 	closedir(dirp);
152 	dirp = NULL;
153 	if (sflg == 0)
154 		printf("%ld\t%s\n", kb(blocks), base);
155 	if (chdir("..") < 0) {
156 		(void) sprintf(index(base, 0), "/..");
157 		perror(base);
158 		exit(1);
159 	}
160 	*ebase0 = 0;
161 	return (blocks);
162 }
163