Commit | Line | Data |
---|---|---|
ca4a89e1 BJ |
1 | static char *sccsid = "@(#)du.c 4.1 (Berkeley) %G%"; |
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 | ||
9 | struct stat Statb; | |
10 | char path[256], name[256]; | |
11 | int Aflag = 0, | |
12 | Sflag = 0, | |
13 | Noarg = 0; | |
14 | struct { | |
15 | int dev, | |
16 | ino; | |
17 | } ml[ML]; | |
18 | long descend(); | |
19 | char *rindex(); | |
20 | char *strcpy(); | |
21 | ||
22 | main(argc, argv) | |
23 | char **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 | ||
60 | long | |
61 | descend(np, fname) | |
62 | char *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); | |
159 | ret: | |
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 | } |