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