Annotation of 43BSD/etc/quotacheck.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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