Commit | Line | Data |
---|---|---|
36e2e948 TL |
1 | /* |
2 | * Disk usage by user | |
3 | */ | |
4 | ||
5 | char *dargv[] = { | |
6 | "/dev/rrp3", | |
7 | 0 | |
8 | }; | |
9 | ||
10 | #include <stdio.h> | |
11 | #include <ctype.h> | |
12 | #include <pwd.h> | |
13 | #include <sys/param.h> | |
14 | #include <sys/ino.h> | |
15 | #include <sys/inode.h> | |
16 | #include <sys/filsys.h> | |
17 | ||
18 | #define ITABSZ 256 | |
19 | #define ISIZ (BSIZE/sizeof(struct dinode)) | |
20 | #define NUID 300 | |
21 | struct filsys sblock; | |
22 | struct dinode itab[ITABSZ]; | |
23 | struct du | |
24 | { | |
25 | long blocks; | |
26 | long nfiles; | |
27 | int uid; | |
28 | char *name; | |
29 | } du[NUID]; | |
30 | #define TSIZE 500 | |
31 | int sizes[TSIZE]; | |
32 | long overflow; | |
33 | ||
34 | int nflg; | |
35 | int fflg; | |
36 | int cflg; | |
37 | ||
38 | int fi; | |
39 | unsigned ino; | |
40 | unsigned nfiles; | |
41 | ||
42 | struct passwd *getpwent(); | |
43 | char *malloc(); | |
44 | char *copy(); | |
45 | ||
46 | main(argc, argv) | |
47 | char **argv; | |
48 | { | |
49 | register int n; | |
50 | register struct passwd *lp; | |
51 | register char **p; | |
52 | ||
53 | for(n=0; n<NUID; n++) | |
54 | du[n].uid = n; | |
55 | while((lp=getpwent()) != 0) { | |
56 | n = lp->pw_uid; | |
57 | if (n>NUID) | |
58 | continue; | |
59 | if(du[n].name) | |
60 | continue; | |
61 | du[n].name = copy(lp->pw_name); | |
62 | } | |
63 | if (argc == 1) { | |
64 | for (p = dargv; *p;) { | |
65 | check(*p++); | |
66 | report(); | |
67 | } | |
68 | return(0); | |
69 | } | |
70 | while (--argc) { | |
71 | argv++; | |
72 | if (argv[0][0]=='-') { | |
73 | if (argv[0][1]=='n') | |
74 | nflg++; | |
75 | else if (argv[0][1]=='f') | |
76 | fflg++; | |
77 | else if (argv[0][1]=='c') | |
78 | cflg++; | |
79 | } else { | |
80 | check(*argv); | |
81 | report(); | |
82 | } | |
83 | } | |
84 | return(0); | |
85 | } | |
86 | ||
87 | check(file) | |
88 | char *file; | |
89 | { | |
90 | register unsigned i, j; | |
91 | register c; | |
92 | ||
93 | fi = open(file, 0); | |
94 | if (fi < 0) { | |
95 | printf("cannot open %s\n", file); | |
96 | return; | |
97 | } | |
98 | printf("%s:\n", file); | |
99 | sync(); | |
100 | bread(1, (char *)&sblock, sizeof sblock); | |
101 | nfiles = (sblock.s_isize-2)*(BSIZE/sizeof(struct dinode)); | |
102 | ino = 0; | |
103 | if (nflg) { | |
104 | if (isdigit(c = getchar())) | |
105 | ungetc(c, stdin); | |
106 | else while (c!='\n' && c != EOF) | |
107 | c = getchar(); | |
108 | } | |
109 | for(i=2; ino<nfiles; i += ITABSZ/ISIZ) { | |
110 | bread(i, (char *)itab, sizeof itab); | |
111 | for (j=0; j<ITABSZ && ino<nfiles; j++) { | |
112 | ino++; | |
113 | acct(&itab[j]); | |
114 | } | |
115 | } | |
116 | } | |
117 | ||
118 | acct(ip) | |
119 | register struct dinode *ip; | |
120 | { | |
121 | register n; | |
122 | register char *np; | |
123 | static fino; | |
124 | ||
125 | if ((ip->di_mode&IFMT) == 0) | |
126 | return; | |
127 | if (cflg) { | |
128 | if ((ip->di_mode&IFMT)!=IFDIR && (ip->di_mode&IFMT)!=IFREG) | |
129 | return; | |
130 | n = (ip->di_size+BSIZE-1)/BSIZE; | |
131 | if (n >= TSIZE) { | |
132 | overflow += n; | |
133 | n = TSIZE-1; | |
134 | } | |
135 | sizes[n]++; | |
136 | return; | |
137 | } | |
138 | if (ip->di_uid >= NUID) | |
139 | return; | |
140 | du[ip->di_uid].blocks += (ip->di_size+BSIZE-1)/BSIZE; | |
141 | du[ip->di_uid].nfiles++; | |
142 | if (nflg) { | |
143 | tryagain: | |
144 | if (fino==0) | |
145 | if (scanf("%d", &fino)<=0) | |
146 | return; | |
147 | if (fino > ino) | |
148 | return; | |
149 | if (fino<ino) { | |
150 | while ((n=getchar())!='\n' && n!=EOF) | |
151 | ; | |
152 | fino = 0; | |
153 | goto tryagain; | |
154 | } | |
155 | if (np = du[ip->di_uid].name) | |
156 | printf("%.7s ", np); | |
157 | else | |
158 | printf("%d ", ip->di_uid); | |
159 | while ((n = getchar())==' ' || n=='\t') | |
160 | ; | |
161 | putchar(n); | |
162 | while (n!=EOF && n!='\n') { | |
163 | n = getchar(); | |
164 | putchar(n); | |
165 | } | |
166 | fino = 0; | |
167 | } | |
168 | } | |
169 | ||
170 | bread(bno, buf, cnt) | |
171 | unsigned bno; | |
172 | char *buf; | |
173 | { | |
174 | ||
175 | lseek(fi, (long)bno*BSIZE, 0); | |
176 | if (read(fi, buf, cnt) != cnt) { | |
177 | printf("read error %u\n", bno); | |
178 | exit(1); | |
179 | } | |
180 | } | |
181 | ||
182 | qcmp(p1, p2) | |
183 | register struct du *p1, *p2; | |
184 | { | |
185 | if (p1->blocks > p2->blocks) | |
186 | return(-1); | |
187 | if (p1->blocks < p2->blocks) | |
188 | return(1); | |
189 | return(strcmp(p1->name, p2->name)); | |
190 | } | |
191 | ||
192 | report() | |
193 | { | |
194 | register i; | |
195 | ||
196 | if (nflg) | |
197 | return; | |
198 | if (cflg) { | |
199 | long t = 0; | |
200 | for (i=0; i<TSIZE-1; i++) | |
201 | if (sizes[i]) { | |
202 | t += i*sizes[i]; | |
203 | printf("%d %d %D\n", i, sizes[i], t); | |
204 | } | |
205 | printf("%d %d %D\n", TSIZE-1, sizes[TSIZE-1], overflow+t); | |
206 | return; | |
207 | } | |
208 | qsort(du, NUID, sizeof(du[0]), qcmp); | |
209 | for (i=0; i<NUID; i++) { | |
210 | if (du[i].blocks==0) | |
211 | return; | |
212 | printf("%5D\t", du[i].blocks); | |
213 | if (fflg) | |
214 | printf("%5D\t", du[i].nfiles); | |
215 | if (du[i].name) | |
216 | printf("%s\n", du[i].name); | |
217 | else | |
218 | printf("#%d\n", du[i].uid); | |
219 | } | |
220 | } | |
221 | ||
222 | char * | |
223 | copy(s) | |
224 | char *s; | |
225 | { | |
226 | register char *p; | |
227 | register n; | |
228 | ||
229 | for(n=0; s[n]; n++) | |
230 | ; | |
231 | p = malloc((unsigned)n+1); | |
232 | for(n=0; p[n] = s[n]; n++) | |
233 | ; | |
234 | return(p); | |
235 | } |