Commit | Line | Data |
---|---|---|
ebdf2361 | 1 | /*- |
7c3ccde2 KB |
2 | * Copyright (c) 1991, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
ebdf2361 KB |
4 | * |
5 | * %sccs.include.proprietary.c% | |
6 | */ | |
7 | ||
8 | #ifndef lint | |
7c3ccde2 KB |
9 | static char copyright[] = |
10 | "@(#) Copyright (c) 1991, 1993\n\ | |
11 | The Regents of the University of California. All rights reserved.\n"; | |
ebdf2361 KB |
12 | #endif /* not lint */ |
13 | ||
b47543fa | 14 | #ifndef lint |
86c1d6e5 | 15 | static char sccsid[] = "@(#)quot.c 8.5 (Berkeley) %G%"; |
ebdf2361 | 16 | #endif /* not lint */ |
6430f2d0 | 17 | |
bea492ce | 18 | #include <sys/param.h> |
249eea8a | 19 | #include <sys/time.h> |
3e6ca7df KM |
20 | #include <sys/stat.h> |
21 | #include <sys/mount.h> | |
1032f6ad KB |
22 | #include <ufs/ufs/dinode.h> |
23 | #include <ufs/ffs/fs.h> | |
249eea8a | 24 | |
8ebbce3e KB |
25 | #include <fcntl.h> |
26 | #include <unistd.h> | |
b712d94e KB |
27 | #include <stdio.h> |
28 | #include <ctype.h> | |
29 | #include <paths.h> | |
bea492ce | 30 | |
f6910205 | 31 | #define ISIZ (MAXBSIZE/sizeof(struct dinode)) |
f6910205 KM |
32 | union { |
33 | struct fs u_sblock; | |
34 | char dummy[SBSIZE]; | |
35 | } sb_un; | |
36 | #define sblock sb_un.u_sblock | |
37 | struct dinode itab[MAXBSIZE/sizeof(struct dinode)]; | |
359e6e11 SL |
38 | |
39 | struct du { | |
40 | struct du *next; | |
bea492ce | 41 | long blocks; |
359e6e11 SL |
42 | long blocks30; |
43 | long blocks60; | |
44 | long blocks90; | |
bea492ce BJ |
45 | long nfiles; |
46 | int uid; | |
359e6e11 SL |
47 | #define NDU 2048 |
48 | } du[NDU]; | |
49 | int ndu; | |
50 | #define DUHASH 8209 /* smallest prime >= 4 * NDU */ | |
51 | #define HASH(u) ((u) % DUHASH) | |
52 | struct du *duhash[DUHASH]; | |
53 | ||
bea492ce BJ |
54 | #define TSIZE 500 |
55 | int sizes[TSIZE]; | |
56 | long overflow; | |
57 | ||
58 | int nflg; | |
59 | int fflg; | |
60 | int cflg; | |
6430f2d0 | 61 | int vflg; |
f6910205 | 62 | int hflg; |
249eea8a | 63 | struct timeval now; |
bea492ce | 64 | |
bea492ce | 65 | unsigned ino; |
bea492ce | 66 | |
74708eda | 67 | char *user_from_uid(); |
bea492ce BJ |
68 | |
69 | main(argc, argv) | |
359e6e11 SL |
70 | int argc; |
71 | char *argv[]; | |
bea492ce | 72 | { |
84cfb8d9 KB |
73 | extern char *optarg; |
74 | extern int optind; | |
75 | int ch; | |
84cfb8d9 KB |
76 | |
77 | while ((ch = getopt(argc, argv, "cfhnv")) != EOF) | |
78 | switch((char)ch) { | |
79 | case 'c': | |
80 | cflg++; break; | |
81 | case 'f': | |
82 | fflg++; break; | |
83 | case 'h': /* undocumented */ | |
84 | hflg++; break; | |
85 | case 'n': | |
86 | nflg++; break; | |
87 | case 'v': /* undocumented */ | |
88 | vflg++; break; | |
89 | case '?': | |
90 | default: | |
91 | fputs("usage: quot [-cfn] [filesystem ...]\n", stderr); | |
92 | exit(1); | |
93 | } | |
94 | argc -= optind; | |
95 | argv += optind; | |
96 | ||
249eea8a | 97 | (void)gettimeofday(&now, NULL); |
e6fecf21 | 98 | setpassent(1); |
84cfb8d9 KB |
99 | if (argc) |
100 | for (; *argv; ++argv) { | |
101 | if (check(*argv, (char *)NULL) == 0) | |
102 | report(); | |
103 | } | |
104 | else | |
359e6e11 | 105 | quotall(); |
84cfb8d9 | 106 | exit(0); |
359e6e11 SL |
107 | } |
108 | ||
84cfb8d9 | 109 | #include <sys/dir.h> |
359e6e11 SL |
110 | #include <fstab.h> |
111 | ||
112 | quotall() | |
113 | { | |
114 | register struct fstab *fs; | |
115 | register char *cp; | |
84cfb8d9 | 116 | char dev[MAXNAMLEN + 10], *rindex(); |
359e6e11 | 117 | |
359e6e11 | 118 | while (fs = getfsent()) { |
baf18142 KM |
119 | if (strcmp(fs->fs_vfstype, "ufs") || |
120 | (strcmp(fs->fs_type, FSTAB_RO) && | |
359e6e11 | 121 | strcmp(fs->fs_type, FSTAB_RW) && |
baf18142 | 122 | strcmp(fs->fs_type, FSTAB_RQ))) |
359e6e11 SL |
123 | continue; |
124 | cp = rindex(fs->fs_spec, '/'); | |
125 | if (cp == 0) | |
126 | continue; | |
a4d097e6 | 127 | (void)snprintf(dev, sizeof(dev), "%sr%s", _PATH_DEV, cp + 1); |
619bf80a | 128 | if (check(dev, fs->fs_file) == 0) |
359e6e11 | 129 | report(); |
bea492ce | 130 | } |
bea492ce BJ |
131 | } |
132 | ||
619bf80a | 133 | check(file, fsdir) |
359e6e11 | 134 | char *file; |
619bf80a | 135 | char *fsdir; |
bea492ce | 136 | { |
359e6e11 SL |
137 | register int i, j, nfiles; |
138 | register struct du **dp; | |
f6910205 | 139 | daddr_t iblk; |
84cfb8d9 | 140 | long dev_bsize; |
359e6e11 | 141 | int c, fd; |
3e6ca7df KM |
142 | struct stat sb; |
143 | struct statfs sfs; | |
144 | #define FNBSZ 128 | |
145 | char filebuf[FNBSZ]; | |
bea492ce | 146 | |
359e6e11 | 147 | /* |
249eea8a KB |
148 | * Initialize tables between checks; because of the qsort done in |
149 | * report() the hash tables must be rebuilt each time. | |
359e6e11 SL |
150 | */ |
151 | for (i = 0; i < TSIZE; i++) | |
152 | sizes[i] = 0; | |
153 | overflow = 0; | |
154 | for (dp = duhash; dp < &duhash[DUHASH]; dp++) | |
155 | *dp = 0; | |
156 | ndu = 0; | |
3e6ca7df KM |
157 | /* |
158 | * Make sure "file" refers to a char special file. | |
159 | * Convert if necessary. Also make sure we have an fsdir. | |
160 | */ | |
161 | if (stat(file, &sb) < 0) { | |
162 | fprintf(stderr, "quot: "); | |
163 | perror(file); | |
164 | return (-1); | |
165 | } | |
166 | /* | |
167 | * User specified "file". | |
168 | * Attempt to come up with the appropriate char special file | |
169 | * and a mount point. | |
170 | */ | |
171 | if (fsdir == NULL) { | |
172 | register struct fstab *fs; | |
173 | int len = strlen(_PATH_DEV); | |
174 | ||
175 | strcpy(filebuf, _PATH_DEV); | |
176 | if (S_ISCHR(sb.st_mode)) { | |
177 | if (strncmp(_PATH_DEV, file, len) == 0 && | |
178 | file[len] == 'r') { | |
179 | strncpy(&filebuf[len], &file[len+1], FNBSZ-6); | |
180 | fs = getfsspec(filebuf); | |
181 | if (fs != NULL) | |
182 | fsdir = fs->fs_file; | |
183 | } | |
184 | } else { | |
185 | if (S_ISBLK(sb.st_mode)) { | |
186 | fs = getfsspec(file); | |
187 | if (fs != NULL) | |
188 | fsdir = fs->fs_file; | |
189 | } else { | |
190 | if (statfs(file, &sfs) == 0) { | |
191 | file = sfs.f_mntfromname; | |
192 | fsdir = sfs.f_mntonname; | |
193 | } | |
194 | } | |
195 | if (strncmp(_PATH_DEV, file, len) == 0) { | |
196 | filebuf[len] = 'r'; | |
197 | strncpy(&filebuf[len+1], &file[len], FNBSZ-7); | |
198 | file = filebuf; | |
199 | } | |
200 | } | |
201 | } | |
359e6e11 SL |
202 | fd = open(file, O_RDONLY); |
203 | if (fd < 0) { | |
204 | fprintf(stderr, "quot: "); | |
205 | perror(file); | |
b47543fa | 206 | return (-1); |
bea492ce | 207 | } |
619bf80a S |
208 | printf("%s", file); |
209 | if (fsdir == NULL) { | |
210 | register struct fstab *fs = getfsspec(file); | |
211 | if (fs != NULL) | |
212 | fsdir = fs->fs_file; | |
213 | } | |
214 | if (fsdir != NULL && *fsdir != '\0') | |
215 | printf(" (%s)", fsdir); | |
216 | printf(":\n"); | |
bea492ce | 217 | sync(); |
249eea8a | 218 | bread(fd, (off_t)SBOFF, (char *)&sblock, SBSIZE); |
a66ab591 | 219 | dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); |
bea492ce BJ |
220 | if (nflg) { |
221 | if (isdigit(c = getchar())) | |
84cfb8d9 | 222 | (void)ungetc(c, stdin); |
359e6e11 | 223 | else while (c != '\n' && c != EOF) |
bea492ce BJ |
224 | c = getchar(); |
225 | } | |
f6910205 KM |
226 | nfiles = sblock.fs_ipg * sblock.fs_ncg; |
227 | for (ino = 0; ino < nfiles; ) { | |
39e484b3 | 228 | iblk = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); |
249eea8a | 229 | bread(fd, (off_t)iblk * dev_bsize, itab, (int)sblock.fs_bsize); |
ed77f19d KM |
230 | for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) { |
231 | if (ino < ROOTINO) | |
f6910205 | 232 | continue; |
8ebbce3e | 233 | qacct(&itab[j]); |
bea492ce BJ |
234 | } |
235 | } | |
359e6e11 | 236 | close(fd); |
619bf80a | 237 | return (0); |
bea492ce BJ |
238 | } |
239 | ||
8ebbce3e | 240 | qacct(ip) |
f6910205 | 241 | register struct dinode *ip; |
bea492ce | 242 | { |
359e6e11 SL |
243 | register struct du *dp; |
244 | struct du **hp; | |
f6910205 | 245 | long blks, frags, size; |
619bf80a | 246 | int n; |
bea492ce BJ |
247 | static fino; |
248 | ||
359e6e11 | 249 | if ((ip->di_mode & IFMT) == 0) |
bea492ce | 250 | return; |
359e6e11 SL |
251 | /* |
252 | * By default, take block count in inode. Otherwise (-h), | |
253 | * take the size field and estimate the blocks allocated. | |
254 | * The latter does not account for holes in files. | |
255 | */ | |
256 | if (!hflg) | |
81ac5aae | 257 | size = ip->di_blocks / 2; |
359e6e11 | 258 | else { |
81ac5aae KM |
259 | blks = lblkno(&sblock, ip->di_size); |
260 | frags = blks * sblock.fs_frag + | |
261 | numfrags(&sblock, dblksize(&sblock, ip, blks)); | |
262 | size = frags * sblock.fs_fsize / 1024; | |
f6910205 | 263 | } |
bea492ce | 264 | if (cflg) { |
359e6e11 | 265 | if ((ip->di_mode&IFMT) != IFDIR && (ip->di_mode&IFMT) != IFREG) |
bea492ce | 266 | return; |
f6910205 KM |
267 | if (size >= TSIZE) { |
268 | overflow += size; | |
269 | size = TSIZE-1; | |
bea492ce | 270 | } |
f6910205 | 271 | sizes[size]++; |
bea492ce BJ |
272 | return; |
273 | } | |
359e6e11 SL |
274 | hp = &duhash[HASH(ip->di_uid)]; |
275 | for (dp = *hp; dp; dp = dp->next) | |
276 | if (dp->uid == ip->di_uid) | |
277 | break; | |
278 | if (dp == 0) { | |
279 | if (ndu >= NDU) | |
280 | return; | |
281 | dp = &du[ndu++]; | |
282 | dp->next = *hp; | |
283 | *hp = dp; | |
284 | dp->uid = ip->di_uid; | |
285 | dp->nfiles = 0; | |
286 | dp->blocks = 0; | |
287 | dp->blocks30 = 0; | |
288 | dp->blocks60 = 0; | |
289 | dp->blocks90 = 0; | |
290 | } | |
291 | dp->blocks += size; | |
6430f2d0 | 292 | #define DAY (60 * 60 * 24) /* seconds per day */ |
86c1d6e5 | 293 | if (now.tv_sec - ip->di_atime > 30 * DAY) |
359e6e11 | 294 | dp->blocks30 += size; |
86c1d6e5 | 295 | if (now.tv_sec - ip->di_atime > 60 * DAY) |
359e6e11 | 296 | dp->blocks60 += size; |
86c1d6e5 | 297 | if (now.tv_sec - ip->di_atime > 90 * DAY) |
359e6e11 SL |
298 | dp->blocks90 += size; |
299 | dp->nfiles++; | |
300 | while (nflg) { | |
301 | register char *np; | |
302 | ||
303 | if (fino == 0) | |
304 | if (scanf("%d", &fino) <= 0) | |
bea492ce BJ |
305 | return; |
306 | if (fino > ino) | |
307 | return; | |
359e6e11 SL |
308 | if (fino < ino) { |
309 | while ((n = getchar()) != '\n' && n != EOF) | |
bea492ce BJ |
310 | ; |
311 | fino = 0; | |
359e6e11 | 312 | continue; |
bea492ce | 313 | } |
74708eda | 314 | if (np = user_from_uid(dp->uid, 1)) |
84cfb8d9 | 315 | printf("%.7s\t", np); |
bea492ce | 316 | else |
84cfb8d9 | 317 | printf("%u\t", ip->di_uid); |
359e6e11 | 318 | while ((n = getchar()) == ' ' || n == '\t') |
bea492ce BJ |
319 | ; |
320 | putchar(n); | |
359e6e11 | 321 | while (n != EOF && n != '\n') { |
bea492ce BJ |
322 | n = getchar(); |
323 | putchar(n); | |
324 | } | |
325 | fino = 0; | |
359e6e11 | 326 | break; |
bea492ce BJ |
327 | } |
328 | } | |
329 | ||
359e6e11 | 330 | bread(fd, bno, buf, cnt) |
249eea8a | 331 | int fd, cnt; |
2f42a3e4 | 332 | off_t bno; |
249eea8a | 333 | void *buf; |
bea492ce | 334 | { |
84cfb8d9 | 335 | (void)lseek(fd, bno, L_SET); |
359e6e11 | 336 | if (read(fd, buf, cnt) != cnt) { |
84cfb8d9 | 337 | fprintf(stderr, "quot: read error at block %ld\n", bno); |
bea492ce BJ |
338 | exit(1); |
339 | } | |
340 | } | |
341 | ||
342 | qcmp(p1, p2) | |
359e6e11 | 343 | register struct du *p1, *p2; |
bea492ce | 344 | { |
359e6e11 SL |
345 | char *s1, *s2; |
346 | ||
bea492ce | 347 | if (p1->blocks > p2->blocks) |
359e6e11 | 348 | return (-1); |
bea492ce | 349 | if (p1->blocks < p2->blocks) |
359e6e11 | 350 | return (1); |
74708eda | 351 | s1 = user_from_uid(p1->uid, 1); |
359e6e11 SL |
352 | if (s1 == 0) |
353 | return (0); | |
74708eda | 354 | s2 = user_from_uid(p2->uid, 1); |
359e6e11 SL |
355 | if (s2 == 0) |
356 | return (0); | |
357 | return (strcmp(s1, s2)); | |
bea492ce BJ |
358 | } |
359 | ||
360 | report() | |
361 | { | |
362 | register i; | |
359e6e11 | 363 | register struct du *dp; |
bea492ce BJ |
364 | |
365 | if (nflg) | |
366 | return; | |
367 | if (cflg) { | |
359e6e11 SL |
368 | register long t = 0; |
369 | ||
370 | for (i = 0; i < TSIZE - 1; i++) | |
bea492ce BJ |
371 | if (sizes[i]) { |
372 | t += i*sizes[i]; | |
84cfb8d9 | 373 | printf("%d\t%d\t%ld\n", i, sizes[i], t); |
bea492ce | 374 | } |
84cfb8d9 | 375 | printf("%d\t%d\t%ld\n", |
359e6e11 | 376 | TSIZE - 1, sizes[TSIZE - 1], overflow + t); |
bea492ce BJ |
377 | return; |
378 | } | |
359e6e11 SL |
379 | qsort(du, ndu, sizeof (du[0]), qcmp); |
380 | for (dp = du; dp < &du[ndu]; dp++) { | |
381 | register char *cp; | |
382 | ||
383 | if (dp->blocks == 0) | |
bea492ce | 384 | return; |
359e6e11 | 385 | printf("%5D\t", dp->blocks); |
bea492ce | 386 | if (fflg) |
359e6e11 | 387 | printf("%5D\t", dp->nfiles); |
74708eda | 388 | if (cp = user_from_uid(dp->uid, 1)) |
359e6e11 | 389 | printf("%-8.8s", cp); |
bea492ce | 390 | else |
359e6e11 | 391 | printf("#%-8d", dp->uid); |
6430f2d0 BJ |
392 | if (vflg) |
393 | printf("\t%5D\t%5D\t%5D", | |
359e6e11 | 394 | dp->blocks30, dp->blocks60, dp->blocks90); |
6430f2d0 | 395 | printf("\n"); |
bea492ce BJ |
396 | } |
397 | } |