Annotation of 43BSDTahoe/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.
                      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.