Commit | Line | Data |
---|---|---|
264ab22e DR |
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 | ||
8 | struct stat Statb; | |
9 | char path[256], name[256]; | |
10 | int Aflag = 0, | |
11 | Sflag = 0, | |
12 | Noarg = 0; | |
13 | struct { | |
14 | int dev, | |
15 | ino; | |
16 | } ml[ML]; | |
17 | long descend(); | |
18 | char *rindex(); | |
19 | char *strcpy(); | |
20 | ||
21 | main(argc, argv) | |
22 | char **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 | ||
59 | long | |
60 | descend(np, fname) | |
61 | char *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); | |
155 | ret: | |
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 | } |