use fstab, add -a and -v flags
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 25 May 1983 04:13:11 +0000 (20:13 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 25 May 1983 04:13:11 +0000 (20:13 -0800)
SCCS-vsn: sbin/quotacheck/quotacheck.c 4.2

usr/src/sbin/quotacheck/quotacheck.c

index 10193ad..c4bc157 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef lit
-static char sccsid[] = "@(#)quotacheck.c       4.1 (Melbourne) %G%";
+#ifndef lint
+static char sccsid[] = "@(#)quotacheck.c       4.2 (Berkeley, Melbourne) %G%";
 #endif
 
 /*
 #endif
 
 /*
@@ -15,203 +15,194 @@ static char sccsid[] = "@(#)quotacheck.c  4.1 (Melbourne) %G%";
 #define        QUOTA
 #include <sys/quota.h>
 #include <sys/stat.h>
 #define        QUOTA
 #include <sys/quota.h>
 #include <sys/stat.h>
+#include <fstab.h>
 
 
-#define        ITABSZ  256
-#define        NUID    3500
 union {
        struct  fs      sblk;
 union {
        struct  fs      sblk;
-       char    ___[MAXBSIZE];
+       char    dummy[MAXBSIZE];
 } un;
 #define        sblock  un.sblk
 } un;
 #define        sblock  un.sblk
+
+#define        ITABSZ  256
 struct dinode  itab[ITABSZ];
 struct dinode  *dp;
 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;
 
 long   blocks;
 dev_t  dev;
 
-int    bflg;
-int    iflg;
-int    rflg;
-int    sflg;
-
-int    fi;
-unsigned       ino;
-unsigned       nfiles;
-int    highuid;
-
+struct fileusage {
+       struct dqusage fu_usage;
+       u_short fu_uid;
+       struct fileusage *fu_next;
+};
+#define FUHASH 997
+struct fileusage *fuhead[FUHASH];
+struct fileusage *lookup();
+struct fileusage *adduid();
+int highuid;
+
+int fi;
+ino_t ino;
+long done;
 struct passwd  *getpwent();
 struct dinode  *ginode();
 struct passwd  *getpwent();
 struct dinode  *ginode();
-char   *malloc();
-char   *copy();
+char *malloc(), *makerawname();
+
+int    vflag;          /* verbose */
+int    aflag;          /* all file systems */
+
+char *qfname = "quotas";
+char quotafile[MAXPATHLEN + 1];
 
 main(argc, argv)
 
 main(argc, argv)
+       int argc;
        char **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);
+       register struct fstab *fs;
+       int i, errs = 0;
+
+again:
+       argc--, argv++;
+       if (argc > 0 && strcmp(*argv, "-v") == 0) {
+               vflag++;
+               goto again;
        }
        }
-
-       fi = open(p, 0);
-       if (fi < 0) {
-               fprintf(stderr, "Can't open %s\n", p);
+       if (argc > 0 && strcmp(*argv, "-a") == 0) {
+               aflag++;
+               goto again;
+       }
+       if (argc <= 0 && !aflag) {
+               fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
+                       "quotacheck [-v] -a",
+                       "quotacheck [-v] filesys ...");
                exit(1);
        }
                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);
-               }
+       setfsent();
+       while ((fs = getfsent()) != NULL) {
+               if (aflag &&
+                   (fs->fs_type == 0 || strcmp(fs->fs_type, "rq") != 0))
+                       continue;
+               if (!aflag &&
+                   !(oneof(fs->fs_file, argv, argc) ||
+                     oneof(fs->fs_spec, argv, argc)))
+                       continue;
+               (void) sprintf(quotafile, "%s/%s", fs->fs_file, qfname);
+               errs += chkquota(fs->fs_spec, quotafile);
        }
        }
+       endfsent();
+       for (i = 0; i < argc; i++)
+               if ((done & (1 << i)) == 0)
+                       fprintf(stderr, "%s not found in /etc/fstab\n",
+                               argv[i]);
+       exit(errs);
+}
 
 
-       if (!(iflg || bflg))
-               sflg++;
+chkquota(fsdev, qffile)
+       char *fsdev;
+       char *qffile;
+{
+       register struct fileusage *fup;
+       dev_t quotadev;
+       FILE *qf;
+       u_short uid;
+       int cg, i;
+       char *rawdisk;
+       struct stat statb;
+       struct dqblk dqbuf;
 
 
-       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;
+       rawdisk = makerawname(fsdev);
+       if (vflag)
+               fprintf(stdout, "*** Check quotas for %s\n", rawdisk);
+       fi = open(rawdisk, 0);
+       if (fi < 0) {
+               perror(rawdisk);
+               return (1);
        }
        }
-/*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;
+       qf = fopen(qffile, "r+");
+       if (qf == NULL) {
+               perror(qffile);
+               return (1);
        }
        }
-
+       if (fstat(fileno(qf), &statb) < 0) {
+               perror(qffile);
+               return (1);
+       }
+       quotadev = statb.st_dev;
+       if (stat(fsdev, &statb) < 0) {
+               perror(fsdev);
+               return (1);
+       }
+       if (quotadev != statb.st_rdev) {
+               fprintf(stderr, "%s dev (0x%x) mismatch %s dev (0x%x)\n",
+                       qffile, quotadev, fsdev, statb.st_rdev);
+               return (1);
+       }
+       quota(Q_SYNC, 0, quotadev, 0);
        sync();
        bread(SBLOCK, (char *)&sblock, SBSIZE);
        ino = 0;
        for (cg = 0; cg < sblock.fs_ncg; cg++) {
        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());
        }
                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);
+       for (uid = 0; uid <= highuid; uid++) {
+               fup = lookup(uid);
+               if (fup == 0)
+                       continue;
+               fseek(qf, uid * sizeof(struct dqblk), 0);
+               i = fread(&dqbuf, sizeof(struct dqblk), 1, qf);
+               if (i == 0)
+                       bzero(&dqbuf, sizeof(struct dqblk));
+               if (dqbuf.dqb_curinodes == fup->fu_usage.du_curinodes &&
+                   dqbuf.dqb_curblocks == fup->fu_usage.du_curblocks)
+                       continue;
+               if (vflag) {
+                       fprintf(stdout, "uid %d fixed:", uid);
+                       fprintf(stdout, " inodes (old %d, new %d)",
+                           dqbuf.dqb_curinodes, fup->fu_usage.du_curinodes);
+                       fprintf(stdout, " blocks (old %d, new %d)\n",
+                           dqbuf.dqb_curblocks, fup->fu_usage.du_curblocks);
                }
                }
-
-               rewind(qf);
-               fwrite(du, sizeof(struct dqblk), highuid+1, qf);
-               fclose(qf);
-               signal(SIGTSTP, ssig);
-               sysset();
-               signal(SIGINT, sig);
+               dqbuf.dqb_curinodes = fup->fu_usage.du_curinodes;
+               dqbuf.dqb_curblocks = fup->fu_usage.du_curblocks;
+               fseek(qf, uid * sizeof(struct dqblk), 0);
+               fwrite(&dqbuf, sizeof(struct dqblk), 1, qf);
+               quota(Q_SETDUSE, uid, quotadev, &fup->fu_usage);
        }
        }
-       report();
+       return (0);
 }
 
 acct(ip)
        register struct dinode *ip;
 {
        register n;
 }
 
 acct(ip)
        register struct dinode *ip;
 {
        register n;
+       register struct fileusage *fup;
 
        if (ip == NULL)
                return;
        if (ip->di_mode == 0)
 
        if (ip == NULL)
                return;
        if (ip->di_mode == 0)
-/*ZZ{printf(" unallocated\n");*/
                return;
                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++;
+       fup = lookup(ip->di_uid);
+       if (fup == 0)
+               fup = adduid(ip->di_uid);
+       fup->fu_usage.du_curinodes++;
        if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK)
        if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK)
-/*ZZ{printf(" special\n");*/
                return;
                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);*/
+       fup->fu_usage.du_curblocks += ip->di_blocks;
 }
 
 }
 
-tloop(bn, ip, f)
-       long bn;
+oneof(target, list, n)
+       char *target, *list[];
+       register int n;
 {
 {
-       register i;
-       long    iblk[MAXBSIZE/sizeof(long)];
+       register int i;
 
 
-       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;
-       }
+       for (i = 0; i < n; i++)
+               if (strcmp(target, list[i]) == 0) {
+                       done |= 1 << i;
+                       return (1);
+               }
+       return (0);
 }
 
 struct dinode *
 }
 
 struct dinode *
@@ -221,13 +212,9 @@ ginode()
 
        if (dp == NULL || ++dp >= &itab[ITABSZ]) {
                iblk = itod(&sblock, ino);
 
        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)];
                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);
        if (ino++ < ROOTINO)
                return(NULL);
        return(dp);
@@ -238,77 +225,66 @@ bread(bno, buf, cnt)
        char *buf;
 {
 
        char *buf;
 {
 
-       lseek(fi, (long)bno*DEV_BSIZE, 0);
+       lseek(fi, (long)dbtob(bno), 0);
        if (read(fi, buf, cnt) != cnt) {
                printf("read error %u\n", bno);
                exit(1);
        }
 }
 
        if (read(fi, buf, cnt) != cnt) {
                printf("read error %u\n", bno);
                exit(1);
        }
 }
 
-sysset()
+struct fileusage *
+lookup(uid)
+       u_short uid;
 {
 {
-       struct dqusage usage;
-       register i;
+       register struct fileusage *fup;
 
 
-       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);
-               }
-       }
+       for (fup = fuhead[uid % FUHASH]; fup != 0; fup = fup->fu_next)
+               if (fup->fu_uid == uid)
+                       return (fup);
+       return ((struct fileusage *)0);
 }
 
 }
 
-report()
+struct fileusage *
+adduid(uid)
+       u_short uid;
 {
 {
-       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);
-                       }
+       struct fileusage *fup, **fhp;
+
+       fup = lookup(uid);
+       if (fup != 0)
+               return (fup);
+       fup = (struct fileusage *)calloc(1, sizeof(struct fileusage));
+       if (fup == 0) {
+               fprintf(stderr, "out of memory for fileusage structures\n");
+               exit(1);
+       }
+       fhp = &fuhead[uid % FUHASH];
+       fup->fu_next = *fhp;
+       *fhp = fup;
+       fup->fu_uid = uid;
+       if (uid > highuid)
+               highuid = uid;
+       return (fup);
 }
 
 char *
 }
 
 char *
-copy(s)
-       char *s;
+makerawname(name)
+       char *name;
 {
 {
-       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);
+       register char *cp;
+       char tmp, ch, *rindex();
+       static char rawname[MAXPATHLEN];
+
+       strcpy(rawname, name);
+       cp = rindex(rawname, '/') + 1;
+       if (cp == (char *)1 || *cp == 'r')
+               return (name);
+       for (ch = 'r'; *cp != '\0'; ) {
+               tmp = *cp;
+               *cp++ = ch;
+               ch = tmp;
+       }
+       *cp++ = ch;
+       *cp = '\0';
+       return (rawname);
 }
 }