Annotation of 43BSDTahoe/etc/quotacheck.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that the above copyright notice and this paragraph are
        !             7:  * duplicated in all such forms and that any documentation,
        !             8:  * advertising materials, and other materials related to such
        !             9:  * distribution and use acknowledge that the software was developed
        !            10:  * by the University of California, Berkeley.  The name of the
        !            11:  * University may not be used to endorse or promote products derived
        !            12:  * from this software without specific prior written permission.
        !            13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            16:  */
        !            17: 
        !            18: #ifndef lint
        !            19: char copyright[] =
        !            20: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
        !            21:  All rights reserved.\n";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #ifndef lint
        !            25: static char sccsid[] = "@(#)quotacheck.c       5.10 (Berkeley) 6/18/88";
        !            26: #endif /* not lint */
        !            27: 
        !            28: /*
        !            29:  * Fix up / report on disc quotas & usage
        !            30:  */
        !            31: #include <stdio.h>
        !            32: #include <ctype.h>
        !            33: #include <signal.h>
        !            34: #include <errno.h>
        !            35: #include <sys/param.h>
        !            36: #include <sys/inode.h>
        !            37: #include <sys/fs.h>
        !            38: #include <sys/quota.h>
        !            39: #include <sys/stat.h>
        !            40: #include <sys/wait.h>
        !            41: #include <fstab.h>
        !            42: #include <pwd.h>
        !            43: 
        !            44: union {
        !            45:        struct  fs      sblk;
        !            46:        char    dummy[MAXBSIZE];
        !            47: } un;
        !            48: #define        sblock  un.sblk
        !            49: 
        !            50: #define        ITABSZ  256
        !            51: struct dinode  itab[ITABSZ];
        !            52: struct dinode  *dp;
        !            53: 
        !            54: #define LOGINNAMESIZE 8
        !            55: struct fileusage {
        !            56:        struct fileusage *fu_next;
        !            57:        struct dqusage fu_usage;
        !            58:        u_short fu_uid;
        !            59:        char fu_name[LOGINNAMESIZE + 1];
        !            60: };
        !            61: #define FUHASH 997
        !            62: struct fileusage *fuhead[FUHASH];
        !            63: struct fileusage *lookup();
        !            64: struct fileusage *adduid();
        !            65: int highuid;
        !            66: 
        !            67: int fi;
        !            68: ino_t ino;
        !            69: long done;
        !            70: struct passwd  *getpwent();
        !            71: struct dinode  *ginode();
        !            72: char *malloc(), *makerawname();
        !            73: 
        !            74: int    vflag;          /* verbose */
        !            75: int    aflag;          /* all file systems */
        !            76: int    pflag;          /* fsck like parallel check */
        !            77: 
        !            78: char *qfname = "quotas";
        !            79: char quotafile[MAXPATHLEN + 1];
        !            80: struct dqblk zerodqbuf;
        !            81: struct fileusage zerofileusage;
        !            82: long dev_bsize = 1;
        !            83: 
        !            84: main(argc, argv)
        !            85:        int argc;
        !            86:        char **argv;
        !            87: {
        !            88:        register struct fstab *fs;
        !            89:        register struct fileusage *fup;
        !            90:        register struct passwd *pw;
        !            91:        int i, errs = 0;
        !            92: 
        !            93: again:
        !            94:        argc--, argv++;
        !            95:        if (argc > 0 && strcmp(*argv, "-v") == 0) {
        !            96:                vflag++;
        !            97:                goto again;
        !            98:        }
        !            99:        if (argc > 0 && strcmp(*argv, "-a") == 0) {
        !           100:                aflag++;
        !           101:                goto again;
        !           102:        }
        !           103:        if (argc > 0 && strcmp(*argv, "-p") == 0) {
        !           104:                pflag++;
        !           105:                goto again;
        !           106:        }
        !           107:        if (argc <= 0 && !aflag) {
        !           108:                fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
        !           109:                        "quotacheck [-v] [-p] -a",
        !           110:                        "quotacheck [-v] [-p] filesys ...");
        !           111:                exit(1);
        !           112:        }
        !           113: 
        !           114:        setpwent();
        !           115:        while ((pw = getpwent()) != 0) {
        !           116:                fup = lookup(pw->pw_uid);
        !           117:                if (fup == 0) {
        !           118:                        fup = adduid(pw->pw_uid);
        !           119:                        strncpy(fup->fu_name, pw->pw_name,
        !           120:                                sizeof(fup->fu_name));
        !           121:                }
        !           122:        }
        !           123:        endpwent();
        !           124: 
        !           125:        if (pflag)
        !           126:                errs = preen(argc, argv);
        !           127:        else {
        !           128:                if (setfsent() == 0) {
        !           129:                        fprintf(stderr, "Can't open ");
        !           130:                        perror(FSTAB);
        !           131:                        exit(8);
        !           132:                }
        !           133:                while ((fs = getfsent()) != NULL) {
        !           134:                        if (aflag &&
        !           135:                            (fs->fs_type == 0 ||
        !           136:                             strcmp(fs->fs_type, FSTAB_RQ) != 0))
        !           137:                                continue;
        !           138:                        if (!aflag &&
        !           139:                            !(oneof(fs->fs_file, argv, argc) ||
        !           140:                              oneof(fs->fs_spec, argv, argc)))
        !           141:                                continue;
        !           142:                        (void) sprintf(quotafile, "%s/%s", fs->fs_file, qfname);
        !           143:                        errs += chkquota(fs->fs_spec, fs->fs_file, quotafile);
        !           144:                }
        !           145:                endfsent();
        !           146:        }
        !           147: 
        !           148:        for (i = 0; i < argc; i++)
        !           149:                if ((done & (1 << i)) == 0)
        !           150:                        fprintf(stderr, "%s not found in %s\n",
        !           151:                                argv[i], FSTAB);
        !           152:        exit(errs);
        !           153: }
        !           154: 
        !           155: preen(argc, argv)
        !           156:        int argc;
        !           157:        char **argv;
        !           158: {
        !           159:        register struct fstab *fs;
        !           160:        register int passno, anygtr;
        !           161:        register int errs;
        !           162:        union wait status;
        !           163: 
        !           164:        passno = 1;
        !           165:        errs = 0;
        !           166:        do {
        !           167:                anygtr = 0;
        !           168: 
        !           169:                if (setfsent() == 0) {
        !           170:                        fprintf(stderr, "Can't open ");
        !           171:                        perror(FSTAB);
        !           172:                        exit(8);
        !           173:                }
        !           174: 
        !           175:                while ((fs = getfsent()) != NULL) {
        !           176:                        if (fs->fs_passno > passno)
        !           177:                                anygtr = 1;
        !           178: 
        !           179:                        if (aflag &&
        !           180:                            (fs->fs_type == 0 ||
        !           181:                             strcmp(fs->fs_type, FSTAB_RQ) != 0))
        !           182:                                continue;
        !           183: 
        !           184:                        if (!aflag &&
        !           185:                            !(oneof(fs->fs_file, argv, argc) ||
        !           186:                              oneof(fs->fs_spec, argv, argc)))
        !           187:                                continue;
        !           188: 
        !           189:                        if (fs->fs_passno != passno)
        !           190:                                continue;
        !           191: 
        !           192:                        switch (fork()) {
        !           193:                        case -1:
        !           194:                                perror("fork");
        !           195:                                exit(8);
        !           196:                                break;
        !           197: 
        !           198:                        case 0:
        !           199:                                (void) sprintf(quotafile, "%s/%s",
        !           200:                                        fs->fs_file, qfname);
        !           201:                                exit(chkquota(fs->fs_spec,
        !           202:                                        fs->fs_file, quotafile));
        !           203:                        }
        !           204:                }
        !           205: 
        !           206:                while (wait(&status) != -1) 
        !           207:                        errs += status.w_retcode;
        !           208: 
        !           209:                passno++;
        !           210:        } while (anygtr);
        !           211: 
        !           212:        return (errs);
        !           213: }
        !           214: 
        !           215: chkquota(fsdev, fsfile, qffile)
        !           216:        char *fsdev;
        !           217:        char *fsfile;
        !           218:        char *qffile;
        !           219: {
        !           220:        register struct fileusage *fup;
        !           221:        dev_t quotadev;
        !           222:        register FILE *qfi, *qfo;
        !           223:        u_short uid;
        !           224:        int cg, i, fdo;
        !           225:        char *rawdisk;
        !           226:        struct stat statb;
        !           227:        struct dqblk dqbuf;
        !           228:        static int warned = 0;
        !           229:        extern int errno;
        !           230: 
        !           231:        rawdisk = makerawname(fsdev);
        !           232:        if (vflag)
        !           233:                fprintf(stdout, "*** Checking quotas for %s (%s)\n", rawdisk, fsfile);
        !           234:        fi = open(rawdisk, 0);
        !           235:        if (fi < 0) {
        !           236:                perror(rawdisk);
        !           237:                return (1);
        !           238:        }
        !           239:        qfi = fopen(qffile, "r");
        !           240:        if (qfi == NULL) {
        !           241:                perror(qffile);
        !           242:                close(fi);
        !           243:                return (1);
        !           244:        }
        !           245:        if (fstat(fileno(qfi), &statb) < 0) {
        !           246:                perror(qffile);
        !           247:                fclose(qfi);
        !           248:                close(fi);
        !           249:                return (1);
        !           250:        }
        !           251:        quotadev = statb.st_dev;
        !           252:        if (stat(fsdev, &statb) < 0) {
        !           253:                perror(fsdev);
        !           254:                fclose(qfi);
        !           255:                close(fi);
        !           256:                return (1);
        !           257:        }
        !           258:        if (quotadev != statb.st_rdev) {
        !           259:                fprintf(stderr, "%s dev (0x%x) mismatch %s dev (0x%x)\n",
        !           260:                        qffile, quotadev, fsdev, statb.st_rdev);
        !           261:                fclose(qfi);
        !           262:                close(fi);
        !           263:                return (1);
        !           264:        }
        !           265:        /*
        !           266:         * Must do fdopen(open(qffile, 1), "w") instead of fopen(qffile, "w")
        !           267:         * because fopen(qffile, "w") would truncate the quota file.
        !           268:         */
        !           269:        fdo = open(qffile, 1);
        !           270:        if (fdo < 0 || (qfo = fdopen(fdo, "w")) == NULL) {
        !           271:                perror(qffile);
        !           272:                if (fdo >= 0)
        !           273:                        close(fdo);
        !           274:                fclose(qfi);
        !           275:                close(fi);
        !           276:                return (1);
        !           277:        }
        !           278:        if (quota(Q_SYNC, 0, quotadev, (caddr_t)0) < 0 &&
        !           279:            errno == EINVAL && !warned && vflag) {
        !           280:                warned++;
        !           281:                fprintf(stdout,
        !           282:                    "*** Warning: Quotas are not compiled into this kernel\n");
        !           283:        }
        !           284:        sync();
        !           285:        bread(SBOFF, (char *)&sblock, SBSIZE);
        !           286:        dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
        !           287:        ino = 0;
        !           288:        for (cg = 0; cg < sblock.fs_ncg; cg++) {
        !           289:                dp = NULL;
        !           290:                for (i = 0; i < sblock.fs_ipg; i++)
        !           291:                        acct(ginode());
        !           292:        }
        !           293:        for (uid = 0; uid <= highuid; uid++) {
        !           294:                i = fread(&dqbuf, sizeof(struct dqblk), 1, qfi);
        !           295:                if (i == 0)
        !           296:                        dqbuf = zerodqbuf;
        !           297:                fup = lookup(uid);
        !           298:                if (fup == 0)
        !           299:                        fup = &zerofileusage;
        !           300:                if (dqbuf.dqb_curinodes == fup->fu_usage.du_curinodes &&
        !           301:                    dqbuf.dqb_curblocks == fup->fu_usage.du_curblocks) {
        !           302:                        fup->fu_usage.du_curinodes = 0;
        !           303:                        fup->fu_usage.du_curblocks = 0;
        !           304:                        fseek(qfo, (long)sizeof(struct dqblk), 1);
        !           305:                        continue;
        !           306:                }
        !           307:                if (vflag) {
        !           308:                        if (pflag)
        !           309:                                printf("%s: ", rawdisk);
        !           310:                        if (fup->fu_name[0] != '\0')
        !           311:                                printf("%-8s fixed:", fup->fu_name);
        !           312:                        else
        !           313:                                printf("#%-7d fixed:", uid);
        !           314:                        if (dqbuf.dqb_curinodes != fup->fu_usage.du_curinodes)
        !           315:                                fprintf(stdout, "\tinodes %d -> %d",
        !           316:                                        dqbuf.dqb_curinodes, fup->fu_usage.du_curinodes);
        !           317:                        if (dqbuf.dqb_curblocks != fup->fu_usage.du_curblocks)
        !           318:                                fprintf(stdout, "\tblocks %d -> %d",
        !           319:                                        dqbuf.dqb_curblocks, fup->fu_usage.du_curblocks);
        !           320:                        fprintf(stdout, "\n");
        !           321:                }
        !           322:                dqbuf.dqb_curinodes = fup->fu_usage.du_curinodes;
        !           323:                dqbuf.dqb_curblocks = fup->fu_usage.du_curblocks;
        !           324:                fwrite(&dqbuf, sizeof(struct dqblk), 1, qfo);
        !           325:                quota(Q_SETDUSE, uid, quotadev, &fup->fu_usage);
        !           326:                fup->fu_usage.du_curinodes = 0;
        !           327:                fup->fu_usage.du_curblocks = 0;
        !           328:        }
        !           329:        fflush(qfo);
        !           330:        ftruncate(fileno(qfo), (off_t)((highuid + 1) * sizeof(struct dqblk)));
        !           331:        fclose(qfi);
        !           332:        fclose(qfo);
        !           333:        close(fi);
        !           334:        return (0);
        !           335: }
        !           336: 
        !           337: acct(ip)
        !           338:        register struct dinode *ip;
        !           339: {
        !           340:        register struct fileusage *fup;
        !           341: 
        !           342:        if (ip == NULL)
        !           343:                return;
        !           344:        if (ip->di_mode == 0)
        !           345:                return;
        !           346:        fup = adduid(ip->di_uid);
        !           347:        fup->fu_usage.du_curinodes++;
        !           348:        if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK)
        !           349:                return;
        !           350:        fup->fu_usage.du_curblocks += ip->di_blocks;
        !           351: }
        !           352: 
        !           353: oneof(target, list, n)
        !           354:        char *target, *list[];
        !           355:        register int n;
        !           356: {
        !           357:        register int i;
        !           358: 
        !           359:        for (i = 0; i < n; i++)
        !           360:                if (strcmp(target, list[i]) == 0) {
        !           361:                        done |= 1 << i;
        !           362:                        return (1);
        !           363:                }
        !           364:        return (0);
        !           365: }
        !           366: 
        !           367: struct dinode *
        !           368: ginode()
        !           369: {
        !           370:        register unsigned long iblk;
        !           371: 
        !           372:        if (dp == NULL || ++dp >= &itab[ITABSZ]) {
        !           373:                iblk = itod(&sblock, ino);
        !           374:                bread(fsbtodb(&sblock, iblk), (char *)itab, sizeof itab);
        !           375:                dp = &itab[ino % INOPB(&sblock)];
        !           376:        }
        !           377:        if (ino++ < ROOTINO)
        !           378:                return(NULL);
        !           379:        return(dp);
        !           380: }
        !           381: 
        !           382: bread(bno, buf, cnt)
        !           383:        long unsigned bno;
        !           384:        char *buf;
        !           385: {
        !           386: 
        !           387:        if (lseek(fi, bno * dev_bsize, 0) < 0) {
        !           388:                perror("lseek");
        !           389:                exit(1);
        !           390:        }
        !           391: 
        !           392:        if (read(fi, buf, cnt) != cnt) {
        !           393:                perror("read");
        !           394:                exit(1);
        !           395:        }
        !           396: }
        !           397: 
        !           398: struct fileusage *
        !           399: lookup(uid)
        !           400:        u_short uid;
        !           401: {
        !           402:        register struct fileusage *fup;
        !           403: 
        !           404:        for (fup = fuhead[uid % FUHASH]; fup != 0; fup = fup->fu_next)
        !           405:                if (fup->fu_uid == uid)
        !           406:                        return (fup);
        !           407:        return ((struct fileusage *)0);
        !           408: }
        !           409: 
        !           410: struct fileusage *
        !           411: adduid(uid)
        !           412:        u_short uid;
        !           413: {
        !           414:        struct fileusage *fup, **fhp;
        !           415:        extern char *calloc();
        !           416: 
        !           417:        fup = lookup(uid);
        !           418:        if (fup != 0)
        !           419:                return (fup);
        !           420:        fup = (struct fileusage *)calloc(1, sizeof(struct fileusage));
        !           421:        if (fup == 0) {
        !           422:                fprintf(stderr, "out of memory for fileusage structures\n");
        !           423:                exit(1);
        !           424:        }
        !           425:        fhp = &fuhead[uid % FUHASH];
        !           426:        fup->fu_next = *fhp;
        !           427:        *fhp = fup;
        !           428:        fup->fu_uid = uid;
        !           429:        if (uid > highuid)
        !           430:                highuid = uid;
        !           431:        return (fup);
        !           432: }
        !           433: 
        !           434: char *
        !           435: makerawname(name)
        !           436:        char *name;
        !           437: {
        !           438:        register char *cp;
        !           439:        char tmp, ch, *rindex();
        !           440:        static char rawname[MAXPATHLEN];
        !           441: 
        !           442:        strcpy(rawname, name);
        !           443:        cp = rindex(rawname, '/');
        !           444:        if (cp == NULL)
        !           445:                return (name);
        !           446:        else
        !           447:                cp++;
        !           448:        for (ch = 'r'; *cp != '\0'; ) {
        !           449:                tmp = *cp;
        !           450:                *cp++ = ch;
        !           451:                ch = tmp;
        !           452:        }
        !           453:        *cp++ = ch;
        !           454:        *cp = '\0';
        !           455:        return (rawname);
        !           456: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.