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