xref: /original-bsd/usr.bin/du/du.c (revision 9c59a687)
1 #ifndef lint
2 static char *sccsid = "@(#)du.c	4.3 (Berkeley) 03/29/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 #define EQ(x,y)	(strcmp(x,y)==0)
12 #define ML	1000
13 
14 struct stat Statb;
15 char	path[256], name[256];
16 int	Aflag = 0,
17 	Sflag = 0,
18 	Noarg = 0;
19 struct {
20 	int	dev,
21 		ino;
22 } ml[ML];
23 long	descend();
24 char	*rindex();
25 char	*strcpy();
26 
27 main(argc, argv)
28 char **argv;
29 {
30 	register	i = 1;
31 	long	blocks = 0;
32 	register char	*np;
33 
34 	if (argc>1) {
35 		if(EQ(argv[i], "-s")) {
36 			++i;
37 			++Sflag;
38 		} else if(EQ(argv[i], "-a")) {
39 			++i;
40 			++Aflag;
41 		}
42 	}
43 	if(i == argc)
44 		++Noarg;
45 
46 	do {
47 		(void) strcpy(path, Noarg? ".": argv[i]);
48 		(void) strcpy(name, path);
49 		if(np = rindex(name, '/')) {
50 			*np++ = '\0';
51 			if(chdir(*name? name: "/") == -1) {
52 				fprintf(stderr, "cannot chdir()\n");
53 				exit(1);
54 			}
55 		} else
56 			np = path;
57 		blocks = descend(path, *np? np: ".");
58 		if(Sflag)
59 			printf("%ld	%s\n", blocks, path);
60 	} while(++i < argc);
61 
62 	exit(0);
63 }
64 
65 DIR *dirp = NULL;
66 long
67 descend(np, fname)
68 char *np, *fname;
69 {
70 	register  struct direct *dp;
71 	register char *c1;
72 	int i;
73 	char *endofname;
74 	long blocks = 0;
75 	long curoff = NULL;
76 
77 	if(stat(fname,&Statb)<0) {
78 		fprintf(stderr, "--bad status < %s >\n", name);
79 		return 0L;
80 	}
81 	if(Statb.st_nlink > 1 && (Statb.st_mode&S_IFMT)!=S_IFDIR) {
82 		static linked = 0;
83 
84 		for(i = 0; i <= linked; ++i) {
85 			if(ml[i].ino==Statb.st_ino && ml[i].dev==Statb.st_dev)
86 				return 0;
87 		}
88 		if (linked < ML) {
89 			ml[linked].dev = Statb.st_dev;
90 			ml[linked].ino = Statb.st_ino;
91 			++linked;
92 		}
93 	}
94 	blocks = howmany(Statb.st_size, 1024);
95 
96 	if((Statb.st_mode&S_IFMT) != S_IFDIR) {
97 		if(Aflag)
98 			printf("%ld	%s\n", blocks, np);
99 		return(blocks);
100 	}
101 
102 	for(c1 = np; *c1; ++c1);
103 	if(*(c1-1) == '/')
104 		--c1;
105 	endofname = c1;
106 	if(chdir(fname) == -1)
107 		return 0;
108 	if (dirp != NULL)
109 		closedir(dirp);
110 	if ((dirp = opendir(".")) == NULL) {
111 		fprintf(stderr, "--cannot open < %s >\n", np);
112 		goto ret;
113 	}
114 	if ((dp = readdir(dirp)) == NULL) {
115 		fprintf(stderr, "--cannot read < %s >\n", np);
116 		closedir(dirp);
117 		dirp = NULL;
118 		goto ret;
119 	}
120 	for ( ; dp != NULL; dp = readdir(dirp)) {
121 		/* each directory entry */
122 		if (EQ(dp->d_name, ".") || EQ(dp->d_name, ".."))
123 			continue;
124 		c1 = endofname;
125 		*c1++ = '/';
126 		(void) strcpy(c1, dp->d_name);
127 		curoff = telldir(dirp);
128 		blocks += descend(np, endofname+1);
129 		if (dirp == NULL) {
130 			/* previous entry was a directory */
131 			dirp = opendir(".");
132 			seekdir(dirp, curoff);
133 		}
134 	}
135 	closedir(dirp);
136 	dirp = NULL;
137 	*endofname = '\0';
138 	if(!Sflag)
139 		printf("%ld	%s\n", blocks, np);
140 ret:
141 	if(chdir("..") == -1) {
142 		*endofname = '\0';
143 		fprintf(stderr, "Bad directory <%s>\n", np);
144 		while(*--endofname != '/');
145 		*endofname = '\0';
146 		if(chdir(np) == -1)
147 			exit(1);
148 	}
149 	return(blocks);
150 }
151