date and time created 83/05/22 14:52:26 by mckusick
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Mon, 23 May 1983 05:52:26 +0000 (21:52 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Mon, 23 May 1983 05:52:26 +0000 (21:52 -0800)
SCCS-vsn: sbin/quotacheck/quotacheck.c 4.1

usr/src/sbin/quotacheck/quotacheck.c [new file with mode: 0644]

diff --git a/usr/src/sbin/quotacheck/quotacheck.c b/usr/src/sbin/quotacheck/quotacheck.c
new file mode 100644 (file)
index 0000000..10193ad
--- /dev/null
@@ -0,0 +1,314 @@
+#ifndef lit
+static char sccsid[] = "@(#)quotacheck.c       4.1 (Melbourne) %G%";
+#endif
+
+/*
+ * Fix up / report on disc quotas & usage
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <sys/inode.h>
+#include <sys/fs.h>
+#define        QUOTA
+#include <sys/quota.h>
+#include <sys/stat.h>
+
+#define        ITABSZ  256
+#define        NUID    3500
+union {
+       struct  fs      sblk;
+       char    ___[MAXBSIZE];
+} un;
+#define        sblock  un.sblk
+struct dinode  itab[ITABSZ];
+struct dinode  *dp;
+struct dqblk   du[NUID];
+char   *dn[NUID];
+struct dqblk   zeroes;
+u_short        iuse[NUID];
+u_long buse[NUID];
+long   blocks;
+dev_t  dev;
+
+int    bflg;
+int    iflg;
+int    rflg;
+int    sflg;
+
+int    fi;
+unsigned       ino;
+unsigned       nfiles;
+int    highuid;
+
+struct passwd  *getpwent();
+struct dinode  *ginode();
+char   *malloc();
+char   *copy();
+
+main(argc, argv)
+       char **argv;
+{
+       register int n;
+       register struct passwd *lp;
+       register char *p;
+       register long unsigned i;
+       register c;
+       register cg;
+       FILE *qf;
+       struct stat statb;
+
+       while (--argc > 0 && *(p = *++argv) == '-')
+               while (c = *++p) switch (c) {
+
+               case 's':
+                       sflg++;
+                       break;
+
+               case 'b':
+                       bflg++;
+                       break;
+
+               case 'i':
+                       iflg++;
+                       break;
+
+               case 'r':
+                       rflg++;
+                       break;
+               }
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: fixquota filesys qfile\n");
+               exit(1);
+       }
+
+       fi = open(p, 0);
+       if (fi < 0) {
+               fprintf(stderr, "Can't open %s\n", p);
+               exit(1);
+       }
+
+       if (iflg || bflg || rflg) {
+               while((lp=getpwent()) != 0) {
+                       n = lp->pw_uid;
+                       if (n>=NUID)
+                               continue;
+                       if(dn[n])
+                               continue;
+                       dn[n] = copy(lp->pw_name);
+               }
+       }
+
+       if (!(iflg || bflg))
+               sflg++;
+
+       qf = fopen(*++argv, "r");
+       if (qf != NULL) {
+               fstat(fileno(qf), &statb);
+               dev = statb.st_dev;
+               quota(Q_SYNC, 0, dev, 0);
+               n = fread(du, sizeof(struct dqblk), NUID, qf);
+               if (n == EOF)
+                       n = 0;
+               highuid = n-1;
+               fclose(qf);
+       } else {
+               highuid = -1;
+               dev = NODEV;
+       }
+/*ZZprintf("highuid = %d\n", highuid);*/
+
+       for (n = 0; n <= highuid; n++) {
+               iuse[n] = du[n].dqb_curinodes;
+               buse[n] = du[n].dqb_curblocks;
+               du[n].dqb_curinodes = du[n].dqb_curblocks = 0;
+       }
+
+       sync();
+       bread(SBLOCK, (char *)&sblock, SBSIZE);
+       ino = 0;
+       for (cg = 0; cg < sblock.fs_ncg; cg++) {
+/*ZZprintf("cg %d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", cg);*/
+               dp = NULL;
+               for (i = 0; i < sblock.fs_ipg; i++)
+                       acct(ginode());
+       }
+       if (sflg && highuid >= 0) {
+               int sig;
+               int ssig;
+
+               sig = (int) signal(SIGINT, SIG_IGN);
+               ssig = (int) signal(SIGTSTP, SIG_IGN);
+               if ((qf = fopen(*argv, "a")) == NULL) {
+                       fprintf(stderr, "Can't create %s\n", *argv);
+                       exit(1);
+               }
+
+               rewind(qf);
+               fwrite(du, sizeof(struct dqblk), highuid+1, qf);
+               fclose(qf);
+               signal(SIGTSTP, ssig);
+               sysset();
+               signal(SIGINT, sig);
+       }
+       report();
+}
+
+acct(ip)
+       register struct dinode *ip;
+{
+       register n;
+
+       if (ip == NULL)
+               return;
+       if (ip->di_mode == 0)
+/*ZZ{printf(" unallocated\n");*/
+               return;
+/*ZZ}*/
+       if (ip->di_uid >= NUID)
+/*ZZ{printf(" uid oor\n");*/
+               return;
+/*ZZ}*/
+       if (ip->di_uid > highuid) {
+               for (n = highuid+1; n <= ip->di_uid; n++)
+                       du[n] = zeroes;
+               highuid = ip->di_uid;
+       }
+       du[ip->di_uid].dqb_curinodes++;
+       if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK)
+/*ZZ{printf(" special\n");*/
+               return;
+/*ZZ}*/
+       blocks = 0;
+       for (n = 0; n < NDADDR; n++)
+               if (ip->di_db[n])
+                       blocks += dblksize(&sblock, ip, n) / DEV_BSIZE;
+       for (n = 0; n < NIADDR; n++)
+               tloop(ip->di_ib[n], ip, n);
+       du[ip->di_uid].dqb_curblocks += blocks;
+       if (blocks != ip->di_blocks)
+               printf("Ino %d: <calc %d, recorded %d>\n", ino, blocks, ip->di_blocks);
+/*ZZprintf(" %d blks\n", blocks);*/
+}
+
+tloop(bn, ip, f)
+       long bn;
+{
+       register i;
+       long    iblk[MAXBSIZE/sizeof(long)];
+
+       if (!bn)
+               return;
+       blocks += sblock.fs_bsize / DEV_BSIZE;
+       bread(fsbtodb(&sblock, bn), iblk, sblock.fs_bsize);
+       if (f) {
+               for (i = 0; i < NINDIR(&sblock); i++)
+                       tloop(iblk[i], ip, f-1);
+       } else {
+               for (i = 0; i < NINDIR(&sblock); i++)
+                       if (iblk[i])
+                               blocks += sblock.fs_bsize / DEV_BSIZE;
+       }
+}
+
+struct dinode *
+ginode()
+{
+       register unsigned long iblk;
+
+       if (dp == NULL || ++dp >= &itab[ITABSZ]) {
+               iblk = itod(&sblock, ino);
+/*ZZprintf("dp = %x, itab=%x", dp, itab);*/
+/*ZZprintf(" Reading inodes from fs blk %d ", iblk);*/
+               bread(fsbtodb(&sblock, iblk), (char *)itab, sizeof itab);
+               dp = &itab[ino % INOPB(&sblock)];
+/*ZZprintf("dp = %x\n", dp, itab);*/
+       }
+/*ZZprintf("ino %d ", ino);*/
+       if (ino++ < ROOTINO)
+               return(NULL);
+       return(dp);
+}
+
+bread(bno, buf, cnt)
+       long unsigned bno;
+       char *buf;
+{
+
+       lseek(fi, (long)bno*DEV_BSIZE, 0);
+       if (read(fi, buf, cnt) != cnt) {
+               printf("read error %u\n", bno);
+               exit(1);
+       }
+}
+
+sysset()
+{
+       struct dqusage usage;
+       register i;
+
+       for (i = 0; i <= highuid; i++) {
+               if (du[i].dqb_curinodes != iuse[i] || du[i].dqb_curblocks != buse[i]) {
+                       if (du[i].dqb_isoftlimit == 0 && du[i].dqb_bsoftlimit == 0)
+                               continue;
+                       if (rflg) {
+                               if (dn[i])
+                                       printf("%s", dn[i]);
+                               else
+                                       printf("#%d", i);
+                               printf(": i %d->%d, b %d->%d\n"
+                                       , iuse[i]
+                                       , du[i].dqb_curinodes
+                                       , buse[i]
+                                       , du[i].dqb_curblocks
+                               );
+                       }
+                       usage.du_curinodes = du[i].dqb_curinodes;
+                       usage.du_curblocks = du[i].dqb_curblocks;
+                       quota(Q_SETDUSE, i, dev, &usage);
+               }
+       }
+}
+
+report()
+{
+       register i;
+
+       if (iflg)
+               for (i = 0; i <= highuid; i++)
+                       if (du[i].dqb_isoftlimit && du[i].dqb_curinodes >= du[i].dqb_isoftlimit) {
+                               if (dn[i])
+                                       printf("%-10s", dn[i]);
+                               else
+                                       printf("#%-9d", i);
+                               printf("%5d (iq = %d)\n", du[i].dqb_curinodes, du[i].dqb_isoftlimit);
+                       }
+
+       if (bflg)
+               for (i = 0; i <= highuid; i++)
+                       if (du[i].dqb_bsoftlimit && du[i].dqb_curblocks >= du[i].dqb_bsoftlimit) {
+                               if (dn[i])
+                                       printf("%-10s", dn[i]);
+                               else
+                                       printf("#%-9s", i);
+                               printf("%5d (quot = %d)\n", du[i].dqb_curblocks, du[i].dqb_bsoftlimit);
+                       }
+}
+
+char *
+copy(s)
+       char *s;
+{
+       register char *p;
+       register n;
+
+       for(n=0; s[n]; n++)
+               ;
+       p = malloc((unsigned)n+1);
+       for(n=0; p[n] = s[n]; n++)
+               ;
+       return(p);
+}