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