a simpler way to do it?
[unix-history] / usr / src / usr.sbin / quot / quot.c
CommitLineData
b47543fa
SL
1#ifndef lint
2static char *sccsid = "@(#)quot.c 4.4 (Berkeley) 83/07/01";
3#endif
6430f2d0 4
bea492ce 5/*
6430f2d0 6 * quot
bea492ce
BJ
7 */
8
bea492ce
BJ
9#include <stdio.h>
10#include <ctype.h>
11#include <pwd.h>
12#include <sys/param.h>
bea492ce 13#include <sys/inode.h>
f6910205 14#include <sys/fs.h>
bea492ce 15
f6910205 16#define ISIZ (MAXBSIZE/sizeof(struct dinode))
bea492ce 17#define NUID 1000
f6910205
KM
18union {
19 struct fs u_sblock;
20 char dummy[SBSIZE];
21} sb_un;
22#define sblock sb_un.u_sblock
23struct dinode itab[MAXBSIZE/sizeof(struct dinode)];
bea492ce
BJ
24struct du
25{
26 long blocks;
6430f2d0 27 long blocks30,blocks60,blocks90;
bea492ce
BJ
28 long nfiles;
29 int uid;
30 char *name;
31} du[NUID];
32#define TSIZE 500
33int sizes[TSIZE];
34long overflow;
35
36int nflg;
37int fflg;
38int cflg;
6430f2d0 39int vflg;
f6910205 40int hflg;
6430f2d0 41long now;
bea492ce
BJ
42
43int fi;
44unsigned ino;
45unsigned nfiles;
46
47struct passwd *getpwent();
48char *malloc();
49char *copy();
50
51main(argc, argv)
52char **argv;
53{
54 register int n;
55 register struct passwd *lp;
56 register char **p;
57
6430f2d0 58 now = time(0);
bea492ce
BJ
59 for(n=0; n<NUID; n++)
60 du[n].uid = n;
61 while((lp=getpwent()) != 0) {
62 n = lp->pw_uid;
63 if (n>NUID)
64 continue;
65 if(du[n].name)
66 continue;
67 du[n].name = copy(lp->pw_name);
68 }
69 if (argc == 1) {
6430f2d0
BJ
70 fprintf(stderr, "usage: df device ...\n");
71 exit(1);
bea492ce
BJ
72 }
73 while (--argc) {
74 argv++;
75 if (argv[0][0]=='-') {
76 if (argv[0][1]=='n')
77 nflg++;
78 else if (argv[0][1]=='f')
79 fflg++;
80 else if (argv[0][1]=='c')
81 cflg++;
6430f2d0
BJ
82 else if (argv[0][1]=='v')
83 vflg++;
f6910205
KM
84 else if (argv[0][1]=='h')
85 hflg++;
bea492ce 86 } else {
b47543fa
SL
87 if (check(*argv) == 0)
88 report();
bea492ce
BJ
89 }
90 }
91 return(0);
92}
93
94check(file)
95char *file;
96{
97 register unsigned i, j;
f6910205
KM
98 daddr_t iblk;
99 int c;
bea492ce
BJ
100
101 fi = open(file, 0);
102 if (fi < 0) {
103 printf("cannot open %s\n", file);
b47543fa 104 return (-1);
bea492ce
BJ
105 }
106 printf("%s:\n", file);
107 sync();
f6910205 108 bread(SBLOCK, (char *)&sblock, SBSIZE);
bea492ce
BJ
109 if (nflg) {
110 if (isdigit(c = getchar()))
111 ungetc(c, stdin);
112 else while (c!='\n' && c != EOF)
113 c = getchar();
114 }
f6910205
KM
115 nfiles = sblock.fs_ipg * sblock.fs_ncg;
116 for (ino = 0; ino < nfiles; ) {
117 iblk = fsbtodb(&sblock, itod(&sblock, ino));
118 bread(iblk, (char *)itab, sblock.fs_bsize);
119 for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++) {
120 if (ino++ < ROOTINO)
121 continue;
bea492ce
BJ
122 acct(&itab[j]);
123 }
124 }
125}
126
127acct(ip)
f6910205 128 register struct dinode *ip;
bea492ce 129{
bea492ce 130 register char *np;
f6910205
KM
131 long blks, frags, size;
132 char n;
bea492ce
BJ
133 static fino;
134
135 if ((ip->di_mode&IFMT) == 0)
136 return;
f6910205
KM
137 if (!hflg) {
138 /*
139 * Assume that there are no holes in files.
140 */
141 blks = lblkno(&sblock, ip->di_size);
142 frags = blks * sblock.fs_frag +
143 numfrags(&sblock, dblksize(&sblock, ip, blks));
144 } else {
145 /*
146 * Actually go out and count the number of allocated blocks.
147 */
148 printf("Sorry, hard way not implemented yet...\n");
149 exit(1);
150 }
151 size = frags * sblock.fs_fsize / 1024;
bea492ce
BJ
152 if (cflg) {
153 if ((ip->di_mode&IFMT)!=IFDIR && (ip->di_mode&IFMT)!=IFREG)
154 return;
f6910205
KM
155 if (size >= TSIZE) {
156 overflow += size;
157 size = TSIZE-1;
bea492ce 158 }
f6910205 159 sizes[size]++;
bea492ce
BJ
160 return;
161 }
162 if (ip->di_uid >= NUID)
163 return;
f6910205 164 du[ip->di_uid].blocks += size;
6430f2d0
BJ
165#define DAY (60 * 60 * 24) /* seconds per day */
166 if (now - ip->di_atime > 30 * DAY)
f6910205 167 du[ip->di_uid].blocks30 += size;
6430f2d0 168 if (now - ip->di_atime > 60 * DAY)
f6910205 169 du[ip->di_uid].blocks60 += size;
6430f2d0 170 if (now - ip->di_atime > 90 * DAY)
f6910205 171 du[ip->di_uid].blocks90 += size;
bea492ce
BJ
172 du[ip->di_uid].nfiles++;
173 if (nflg) {
174 tryagain:
175 if (fino==0)
176 if (scanf("%d", &fino)<=0)
177 return;
178 if (fino > ino)
179 return;
180 if (fino<ino) {
181 while ((n=getchar())!='\n' && n!=EOF)
182 ;
183 fino = 0;
184 goto tryagain;
185 }
186 if (np = du[ip->di_uid].name)
187 printf("%.7s ", np);
188 else
189 printf("%d ", ip->di_uid);
190 while ((n = getchar())==' ' || n=='\t')
191 ;
192 putchar(n);
193 while (n!=EOF && n!='\n') {
194 n = getchar();
195 putchar(n);
196 }
197 fino = 0;
198 }
199}
200
201bread(bno, buf, cnt)
202unsigned bno;
203char *buf;
204{
205
f6910205 206 lseek(fi, (long)bno*DEV_BSIZE, 0);
bea492ce
BJ
207 if (read(fi, buf, cnt) != cnt) {
208 printf("read error %u\n", bno);
209 exit(1);
210 }
211}
212
213qcmp(p1, p2)
214register struct du *p1, *p2;
215{
216 if (p1->blocks > p2->blocks)
217 return(-1);
218 if (p1->blocks < p2->blocks)
219 return(1);
b47543fa
SL
220 if (p1->name == 0 || p2->name == 0)
221 return(0); /* doesn't matter */
bea492ce
BJ
222 return(strcmp(p1->name, p2->name));
223}
224
225report()
226{
227 register i;
228
229 if (nflg)
230 return;
231 if (cflg) {
232 long t = 0;
233 for (i=0; i<TSIZE-1; i++)
234 if (sizes[i]) {
235 t += i*sizes[i];
236 printf("%d %d %D\n", i, sizes[i], t);
237 }
238 printf("%d %d %D\n", TSIZE-1, sizes[TSIZE-1], overflow+t);
239 return;
240 }
241 qsort(du, NUID, sizeof(du[0]), qcmp);
242 for (i=0; i<NUID; i++) {
243 if (du[i].blocks==0)
244 return;
245 printf("%5D\t", du[i].blocks);
246 if (fflg)
247 printf("%5D\t", du[i].nfiles);
248 if (du[i].name)
6430f2d0 249 printf("%-8.8s", du[i].name);
bea492ce 250 else
6430f2d0
BJ
251 printf("#%-8d", du[i].uid);
252 if (vflg)
253 printf("\t%5D\t%5D\t%5D",
254 du[i].blocks30, du[i].blocks60, du[i].blocks90);
255 printf("\n");
bea492ce
BJ
256 }
257}
258
259char *
260copy(s)
261char *s;
262{
263 register char *p;
264 register n;
265
266 for(n=0; s[n]; n++)
267 ;
268 p = malloc((unsigned)n+1);
269 for(n=0; p[n] = s[n]; n++)
270 ;
271 return(p);
272}