|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)quotacheck.c 4.4 (Berkeley, Melbourne) 6/22/83";
3: #endif
4:
5: /*
6: * Fix up / report on disc quotas & usage
7: */
8: #include <stdio.h>
9: #include <ctype.h>
10: #include <signal.h>
11: #include <sys/param.h>
12: #include <sys/inode.h>
13: #include <sys/fs.h>
14: #include <sys/quota.h>
15: #include <sys/stat.h>
16: #include <fstab.h>
17: #include <pwd.h>
18:
19: union {
20: struct fs sblk;
21: char dummy[MAXBSIZE];
22: } un;
23: #define sblock un.sblk
24:
25: #define ITABSZ 256
26: struct dinode itab[ITABSZ];
27: struct dinode *dp;
28: long blocks;
29: dev_t dev;
30:
31: #define LOGINNAMESIZE 8
32: struct fileusage {
33: struct fileusage *fu_next;
34: struct dqusage fu_usage;
35: u_short fu_uid;
36: char fu_name[LOGINNAMESIZE + 1];
37: };
38: #define FUHASH 997
39: struct fileusage *fuhead[FUHASH];
40: struct fileusage *lookup();
41: struct fileusage *adduid();
42: int highuid;
43:
44: int fi;
45: ino_t ino;
46: long done;
47: struct passwd *getpwent();
48: struct dinode *ginode();
49: char *malloc(), *makerawname();
50:
51: int vflag; /* verbose */
52: int aflag; /* all file systems */
53:
54: char *qfname = "quotas";
55: char quotafile[MAXPATHLEN + 1];
56: struct dqblk zerodqbuf;
57:
58: main(argc, argv)
59: int argc;
60: char **argv;
61: {
62: register struct fstab *fs;
63: register struct fileusage *fup;
64: register struct passwd *pw;
65: int i, errs = 0;
66:
67: again:
68: argc--, argv++;
69: if (argc > 0 && strcmp(*argv, "-v") == 0) {
70: vflag++;
71: goto again;
72: }
73: if (argc > 0 && strcmp(*argv, "-a") == 0) {
74: aflag++;
75: goto again;
76: }
77: if (argc <= 0 && !aflag) {
78: fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
79: "quotacheck [-v] -a",
80: "quotacheck [-v] filesys ...");
81: exit(1);
82: }
83: if (vflag) {
84: setpwent();
85: while ((pw = getpwent()) != 0) {
86: fup = lookup(pw->pw_uid);
87: if (fup == 0)
88: fup = adduid(pw->pw_uid);
89: strncpy(fup->fu_name, pw->pw_name,
90: sizeof(fup->fu_name));
91: }
92: endpwent();
93: }
94: setfsent();
95: while ((fs = getfsent()) != NULL) {
96: if (aflag &&
97: (fs->fs_type == 0 || strcmp(fs->fs_type, "rq") != 0))
98: continue;
99: if (!aflag &&
100: !(oneof(fs->fs_file, argv, argc) ||
101: oneof(fs->fs_spec, argv, argc)))
102: continue;
103: (void) sprintf(quotafile, "%s/%s", fs->fs_file, qfname);
104: errs += chkquota(fs->fs_spec, quotafile);
105: }
106: endfsent();
107: for (i = 0; i < argc; i++)
108: if ((done & (1 << i)) == 0)
109: fprintf(stderr, "%s not found in /etc/fstab\n",
110: argv[i]);
111: exit(errs);
112: }
113:
114: chkquota(fsdev, qffile)
115: char *fsdev;
116: char *qffile;
117: {
118: register struct fileusage *fup;
119: dev_t quotadev;
120: FILE *qf;
121: u_short uid;
122: int cg, i;
123: char *rawdisk;
124: struct stat statb;
125: struct dqblk dqbuf;
126:
127: rawdisk = makerawname(fsdev);
128: if (vflag)
129: fprintf(stdout, "*** Check quotas for %s\n", rawdisk);
130: fi = open(rawdisk, 0);
131: if (fi < 0) {
132: perror(rawdisk);
133: return (1);
134: }
135: qf = fopen(qffile, "r+");
136: if (qf == NULL) {
137: perror(qffile);
138: return (1);
139: }
140: if (fstat(fileno(qf), &statb) < 0) {
141: perror(qffile);
142: return (1);
143: }
144: quotadev = statb.st_dev;
145: if (stat(fsdev, &statb) < 0) {
146: perror(fsdev);
147: return (1);
148: }
149: if (quotadev != statb.st_rdev) {
150: fprintf(stderr, "%s dev (0x%x) mismatch %s dev (0x%x)\n",
151: qffile, quotadev, fsdev, statb.st_rdev);
152: return (1);
153: }
154: quota(Q_SYNC, 0, quotadev, 0);
155: sync();
156: bread(SBLOCK, (char *)&sblock, SBSIZE);
157: ino = 0;
158: for (cg = 0; cg < sblock.fs_ncg; cg++) {
159: dp = NULL;
160: for (i = 0; i < sblock.fs_ipg; i++)
161: acct(ginode());
162: }
163: for (uid = 0; uid <= highuid; uid++) {
164: fup = lookup(uid);
165: if (fup == 0)
166: continue;
167: fseek(qf, uid * sizeof(struct dqblk), 0);
168: i = fread(&dqbuf, sizeof(struct dqblk), 1, qf);
169: if (i == 0)
170: dqbuf = zerodqbuf;
171: if (dqbuf.dqb_curinodes == fup->fu_usage.du_curinodes &&
172: dqbuf.dqb_curblocks == fup->fu_usage.du_curblocks) {
173: fup->fu_usage.du_curinodes = 0;
174: fup->fu_usage.du_curblocks = 0;
175: continue;
176: }
177: if (vflag) {
178: if (fup->fu_name[0] != '\0')
179: printf("%-10s fixed:", fup->fu_name);
180: else
181: printf("#%-9d fixed:", uid);
182: fprintf(stdout, " inodes (old %d, new %d)",
183: dqbuf.dqb_curinodes, fup->fu_usage.du_curinodes);
184: fprintf(stdout, " blocks (old %d, new %d)\n",
185: dqbuf.dqb_curblocks, fup->fu_usage.du_curblocks);
186: }
187: dqbuf.dqb_curinodes = fup->fu_usage.du_curinodes;
188: dqbuf.dqb_curblocks = fup->fu_usage.du_curblocks;
189: fseek(qf, uid * sizeof(struct dqblk), 0);
190: fwrite(&dqbuf, sizeof(struct dqblk), 1, qf);
191: quota(Q_SETDUSE, uid, quotadev, &fup->fu_usage);
192: fup->fu_usage.du_curinodes = 0;
193: fup->fu_usage.du_curblocks = 0;
194: }
195: return (0);
196: }
197:
198: acct(ip)
199: register struct dinode *ip;
200: {
201: register n;
202: register struct fileusage *fup;
203:
204: if (ip == NULL)
205: return;
206: if (ip->di_mode == 0)
207: return;
208: fup = lookup(ip->di_uid);
209: if (fup == 0)
210: fup = adduid(ip->di_uid);
211: fup->fu_usage.du_curinodes++;
212: if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK)
213: return;
214: fup->fu_usage.du_curblocks += ip->di_blocks;
215: }
216:
217: oneof(target, list, n)
218: char *target, *list[];
219: register int n;
220: {
221: register int i;
222:
223: for (i = 0; i < n; i++)
224: if (strcmp(target, list[i]) == 0) {
225: done |= 1 << i;
226: return (1);
227: }
228: return (0);
229: }
230:
231: struct dinode *
232: ginode()
233: {
234: register unsigned long iblk;
235:
236: if (dp == NULL || ++dp >= &itab[ITABSZ]) {
237: iblk = itod(&sblock, ino);
238: bread(fsbtodb(&sblock, iblk), (char *)itab, sizeof itab);
239: dp = &itab[ino % INOPB(&sblock)];
240: }
241: if (ino++ < ROOTINO)
242: return(NULL);
243: return(dp);
244: }
245:
246: bread(bno, buf, cnt)
247: long unsigned bno;
248: char *buf;
249: {
250:
251: lseek(fi, (long)dbtob(bno), 0);
252: if (read(fi, buf, cnt) != cnt) {
253: printf("read error %u\n", bno);
254: exit(1);
255: }
256: }
257:
258: struct fileusage *
259: lookup(uid)
260: u_short uid;
261: {
262: register struct fileusage *fup;
263:
264: for (fup = fuhead[uid % FUHASH]; fup != 0; fup = fup->fu_next)
265: if (fup->fu_uid == uid)
266: return (fup);
267: return ((struct fileusage *)0);
268: }
269:
270: struct fileusage *
271: adduid(uid)
272: u_short uid;
273: {
274: struct fileusage *fup, **fhp;
275:
276: fup = lookup(uid);
277: if (fup != 0)
278: return (fup);
279: fup = (struct fileusage *)calloc(1, sizeof(struct fileusage));
280: if (fup == 0) {
281: fprintf(stderr, "out of memory for fileusage structures\n");
282: exit(1);
283: }
284: fhp = &fuhead[uid % FUHASH];
285: fup->fu_next = *fhp;
286: *fhp = fup;
287: fup->fu_uid = uid;
288: if (uid > highuid)
289: highuid = uid;
290: return (fup);
291: }
292:
293: char *
294: makerawname(name)
295: char *name;
296: {
297: register char *cp;
298: char tmp, ch, *rindex();
299: static char rawname[MAXPATHLEN];
300:
301: strcpy(rawname, name);
302: cp = rindex(rawname, '/') + 1;
303: if (cp == (char *)1 || *cp == 'r')
304: return (name);
305: for (ch = 'r'; *cp != '\0'; ) {
306: tmp = *cp;
307: *cp++ = ch;
308: ch = tmp;
309: }
310: *cp++ = ch;
311: *cp = '\0';
312: return (rawname);
313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.