BSD 4 release
[unix-history] / usr / src / cmd / du.c
CommitLineData
31cef89c 1static char *sccsid = "@(#)du.c 4.1 (Berkeley) 10/1/80";
771a7289
BJ
2#include <stdio.h>
3#include <sys/param.h>
4#include <sys/stat.h>
5#include <sys/dir.h>
6#define EQ(x,y) (strcmp(x,y)==0)
7#define ML 1000
8
9struct stat Statb;
10char path[256], name[256];
11int Aflag = 0,
12 Sflag = 0,
13 Noarg = 0;
14struct {
15 int dev,
16 ino;
17} ml[ML];
18long descend();
19char *rindex();
20char *strcpy();
21
22main(argc, argv)
23char **argv;
24{
25 register i = 1;
26 long blocks = 0;
27 register char *np;
28
29 if (argc>1) {
30 if(EQ(argv[i], "-s")) {
31 ++i;
32 ++Sflag;
33 } else if(EQ(argv[i], "-a")) {
34 ++i;
35 ++Aflag;
36 }
37 }
38 if(i == argc)
39 ++Noarg;
40
41 do {
42 strcpy(path, Noarg? ".": argv[i]);
43 strcpy(name, path);
44 if(np = rindex(name, '/')) {
45 *np++ = '\0';
46 if(chdir(*name? name: "/") == -1) {
47 fprintf(stderr, "cannot chdir()\n");
48 exit(1);
49 }
50 } else
51 np = path;
52 blocks = descend(path, *np? np: ".");
53 if(Sflag)
54 printf("%ld %s\n", blocks, path);
55 } while(++i < argc);
56
57 exit(0);
58}
59
60long
61descend(np, fname)
62char *np, *fname;
63{
64 int dir = 0, /* open directory */
65 offset,
66 dsize,
67 entries,
68 dirsize;
69
70 struct direct dentry[BUFSIZ / sizeof (struct direct)];
71 register struct direct *dp;
72 register char *c1, *c2;
73 int i;
74 char *endofname;
75 long blocks = 0;
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/*
95 blocks = (Statb.st_size + BSIZE-1) >> BSHIFT;
96*/
97 blocks = (Statb.st_size + 511) >> 9;
98
99 if((Statb.st_mode&S_IFMT)!=S_IFDIR) {
100 if(Aflag)
101 printf("%ld %s\n", blocks, np);
102 return(blocks);
103 }
104
105 for(c1 = np; *c1; ++c1);
106 if(*(c1-1) == '/')
107 --c1;
108 endofname = c1;
109 dirsize = Statb.st_size;
110 if(chdir(fname) == -1)
111 return 0;
112 for(offset=0; offset < dirsize; offset += BUFSIZ) { /* each block */
113 dsize = BUFSIZ<(dirsize-offset)? BUFSIZ: (dirsize-offset);
114 if(!dir) {
115 if((dir=open(".",0))<0) {
116 fprintf(stderr, "--cannot open < %s >\n",
117 np);
118 goto ret;
119 }
120 if(offset) lseek(dir, (long)offset, 0);
121 if(read(dir, (char *)dentry, dsize)<0) {
122 fprintf(stderr, "--cannot read < %s >\n",
123 np);
124 goto ret;
125 }
126 if(dir > 10) {
127 close(dir);
128 dir = 0;
129 }
130 } else
131 if(read(dir, (char *)dentry, dsize)<0) {
132 fprintf(stderr, "--cannot read < %s >\n",
133 np);
134 goto ret;
135 }
136 for(dp=dentry, entries=dsize>>4; entries; --entries, ++dp) {
137 /* each directory entry */
138 if(dp->d_ino==0
139 || EQ(dp->d_name, ".")
140 || EQ(dp->d_name, ".."))
141 continue;
142 c1 = endofname;
143 *c1++ = '/';
144 c2 = dp->d_name;
145 for(i=0; i<DIRSIZ; ++i)
146 if(*c2)
147 *c1++ = *c2++;
148 else
149 break;
150 *c1 = '\0';
151 if(c1 == endofname) /* ?? */
152 return 0L;
153 blocks += descend(np, endofname+1);
154 }
155 }
156 *endofname = '\0';
157 if(!Sflag)
158 printf("%ld %s\n", blocks, np);
159ret:
160 if(dir)
161 close(dir);
162 if(chdir("..") == -1) {
163 *endofname = '\0';
164 fprintf(stderr, "Bad directory <%s>\n", np);
165 while(*--endofname != '/');
166 *endofname = '\0';
167 if(chdir(np) == -1)
168 exit(1);
169 }
170 return(blocks);
171}