Annotation of coherent/d/bin/quot.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Produce various information about
        !             3:  * filesystem space usage and owners.
        !             4:  * The options of this command seem a
        !             5:  * little too disjoint in their functionality.
        !             6:  */
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include <sys/ino.h>
        !            10: #include <sys/filsys.h>
        !            11: #include <canon.h>
        !            12: #include <pwd.h>
        !            13: #include <ctype.h>
        !            14: 
        !            15: #define        NHASH   64              /* Hash names table (power of 2) */
        !            16: #define        NIREAD  (20*BUFSIZ)     /* Inode bytes per read */
        !            17: #define        NCUM    2047            /* Number of different size entries */
        !            18: #define        BADSIZE (-1)            /* not valid - for hash synonym checking */
        !            19: #define        BADUID  (-1)            /* not valid - for hash synonyms */
        !            20: 
        !            21: /*
        !            22:  * Hash table of names
        !            23:  */
        !            24: typedef        struct  NAME {
        !            25:        struct  NAME    *n_next;
        !            26:        unsigned short  n_uid;
        !            27:        char    n_name[];
        !            28: }      NAME;
        !            29: 
        !            30: /*
        !            31:  * Entry of hash table of
        !            32:  * -f and ordinary options.
        !            33:  */
        !            34: typedef        struct  FENTRY  {
        !            35:        unsigned short  f_uid;
        !            36:        long    f_nfiles;
        !            37:        long    f_nblocks;
        !            38: }      FENTRY;
        !            39: 
        !            40: /*
        !            41:  * Entry of hash table for
        !            42:  * -c (cumulative sizes)
        !            43:  */
        !            44: typedef        struct  CENTRY  {
        !            45:        unsigned long   c_nblocks;      /* Size of file in blocks */
        !            46:        long    c_nfiles;               /* #files of that size */
        !            47: }      CENTRY;
        !            48: 
        !            49: NAME   *names[NHASH];
        !            50: FENTRY *fentries;              /* File count and size entries */
        !            51: FENTRY *efp;                   /* Pointer to end of `fentries' */
        !            52: CENTRY *centries;              /* Cumulative size entries */
        !            53: CENTRY *ecp;                   /* Pointer to end of `centries' */
        !            54: CENTRY *lastcep;               /* Last for sorting */
        !            55: char   ibuf[NIREAD];           /* I-node read buffer */
        !            56: char   incopt[] = "incompatible options given";
        !            57: 
        !            58: int    cflag;                  /* cumulative sizes list */
        !            59: int    fflag;                  /* #files as well as space */
        !            60: int    nflag;                  /* List of files and owners (via ncheck) */
        !            61: int    tflag;                  /* Print a total */
        !            62: int    nuids;                  /* Number of uids found in /etc/passwd */
        !            63: ino_t  readino;                /* Last i-number read from input (`-n') */
        !            64: char   *readfile;              /* Last filename read as above */
        !            65: char   *line;                  /* Line that is read in */
        !            66: 
        !            67: char   *username();
        !            68: char   *alloc();
        !            69: FENTRY *getfentry();
        !            70: CENTRY *getcentry();
        !            71: int    fcomp();
        !            72: int    ccomp();
        !            73: 
        !            74: main(argc, argv)
        !            75: int argc;
        !            76: register char *argv[];
        !            77: {
        !            78:        register char *ap;
        !            79:        register int es = 0;
        !            80:        register int mflag;
        !            81:        register int fd;
        !            82: 
        !            83:        while (argc>1 && *argv[1]=='-') {
        !            84:                for (ap = &argv[1][1]; *ap!='\0'; ap++)
        !            85:                        switch (*ap) {
        !            86:                        case 'n':
        !            87:                                nflag++;
        !            88:                                if (cflag || fflag)
        !            89:                                        cerr(incopt);
        !            90:                                break;
        !            91: 
        !            92:                        case 'c':
        !            93:                                cflag++;
        !            94:                                if (nflag || fflag)
        !            95:                                        cerr(incopt);
        !            96:                                break;
        !            97: 
        !            98:                        case 'f':
        !            99:                                fflag++;
        !           100:                                if (nflag || cflag)
        !           101:                                        cerr(incopt);
        !           102:                                break;
        !           103: 
        !           104:                        case 't':
        !           105:                                tflag++;
        !           106:                                if (nflag)
        !           107:                                        cerr(incopt);
        !           108:                                break;
        !           109: 
        !           110:                        default:
        !           111:                                usage();
        !           112:                        }
        !           113:                argv++;
        !           114:                argc--;
        !           115:        }
        !           116:        argv++;
        !           117:        if (argc < 2)
        !           118:                usage();
        !           119:        mflag = 0;
        !           120:        if (argv[0]!=NULL && argv[1]!=NULL)
        !           121:                mflag++;
        !           122:        for ( ; *argv!=NULL; argv++) {
        !           123:                if ((fd = open(*argv, 0)) < 0) {
        !           124:                        cwarn("cannot open `%s'", *argv);
        !           125:                        continue;
        !           126:                }
        !           127:                if (mflag)
        !           128:                        fprintf(stderr, "%s:\n", *argv);
        !           129:                quotinit();
        !           130:                es |= quot(fd, *argv);
        !           131:                quotterm();
        !           132:                close(fd);
        !           133:        }
        !           134:        exit(es);
        !           135: }
        !           136: 
        !           137: /*
        !           138:  * Initialise things for `quot' for
        !           139:  * each filesystem pass.
        !           140:  */
        !           141: quotinit()
        !           142: {
        !           143:        if (!cflag && nuids==0) {
        !           144:                readnames();
        !           145:                nuids *= 2;
        !           146:        }
        !           147:        if (!nflag && !cflag) {
        !           148:                register FENTRY *fep;
        !           149: 
        !           150:                fentries = (FENTRY *)alloc(nuids*sizeof (FENTRY));
        !           151:                efp = &fentries[nuids];
        !           152:                for (fep = fentries; fep < efp; fep++)
        !           153:                        fep->f_uid = BADUID;
        !           154:        } else if (cflag) {
        !           155:                register CENTRY *cep;
        !           156: 
        !           157:                centries = (CENTRY *)alloc(NCUM*sizeof(CENTRY));
        !           158:                lastcep = centries;
        !           159:                ecp = &centries[NCUM];
        !           160:                for (cep = centries; cep < ecp; cep++)
        !           161:                        cep->c_nblocks = BADSIZE;
        !           162:        } else {
        !           163:                line = alloc(1000);
        !           164:                readino = 0;
        !           165:        }
        !           166: }
        !           167: 
        !           168: /*
        !           169:  * Routine run between filesystems
        !           170:  * to clean up allocated storage.
        !           171:  * Also may print out tables.
        !           172:  */
        !           173: quotterm()
        !           174: {
        !           175:        if (fentries != NULL) {
        !           176:                register FENTRY *fep;
        !           177:                long totblocks = 0;
        !           178:                long totfiles = 0;
        !           179: 
        !           180:                qsort((char *)fentries, nuids, sizeof(FENTRY), fcomp);
        !           181:                for (fep=fentries; fep < efp; fep++) {
        !           182:                        if (fep->f_uid == BADUID)
        !           183:                                break;
        !           184:                        if (tflag) {
        !           185:                                totblocks += fep->f_nblocks;
        !           186:                                totfiles += fep->f_nfiles;
        !           187:                        }
        !           188:                        if (fflag)
        !           189:                                printf("%8ld ", fep->f_nfiles);
        !           190:                        printf("%8ld    %s\n", fep->f_nblocks,
        !           191:                            username(fep->f_uid));
        !           192:                }
        !           193:                if (tflag) {
        !           194:                        if (fflag)
        !           195:                                printf("%8ld ", totfiles);
        !           196:                        printf("%8ld      Total\n", totblocks);
        !           197:                }
        !           198:                free((char *)fentries);
        !           199:                fentries = NULL;
        !           200:        } else if (centries != NULL) {
        !           201:                register CENTRY *cep;
        !           202:                long cumblocks = 0;
        !           203: 
        !           204:                qsort((char *)centries, lastcep-centries, sizeof(CENTRY), ccomp);
        !           205:                for (cep = centries; cep < lastcep; cep++) {
        !           206:                        if (cep->c_nblocks == BADSIZE)
        !           207:                                break;
        !           208:                        cumblocks += cep->c_nblocks*cep->c_nfiles;
        !           209:                        printf("%8ld %8ld %10ld\n", cep->c_nblocks,
        !           210:                            cep->c_nfiles, cumblocks);
        !           211:                }
        !           212:                free((char *)centries);
        !           213:                centries = NULL;
        !           214:        }
        !           215: }
        !           216: 
        !           217: /*
        !           218:  * Called for each filesystem that is read.
        !           219:  */
        !           220: quot(fsfd, fs)
        !           221: int fsfd;
        !           222: char *fs;
        !           223: {
        !           224:        register ino_t maxino;
        !           225:        register ino_t inum;
        !           226: 
        !           227:        {
        !           228:                register struct filsys *sbp;
        !           229: 
        !           230:                lseek(fsfd, (fsize_t)(SUPERI*BSIZE), 0);
        !           231:                if (read(fsfd, ibuf, BSIZE) != BSIZE)
        !           232:                        cerr("%s: bad filesystem format", fs);
        !           233:                sbp = ibuf;
        !           234:                canshort(sbp->s_isize);
        !           235:                candaddr(sbp->s_fsize);
        !           236:                if (sbp->s_isize > sbp->s_fsize) {
        !           237:                        cwarn("%s: ridiculous fsize/isize", fs);
        !           238:                        return (1);
        !           239:                }
        !           240:                maxino = (sbp->s_isize-INODEI) * INOPB;
        !           241:        }
        !           242:        lseek(fsfd, (fsize_t)(INODEI*BSIZE), 0);
        !           243:        inum = 0;
        !           244:        for (;;) {
        !           245:                register struct dinode *ip;
        !           246: 
        !           247:                if (read(fsfd, ibuf, sizeof ibuf) <= 0) {
        !           248:                        cwarn("%s: i-node read error", fs);
        !           249:                        return (1);
        !           250:                }
        !           251:                for (ip=ibuf; ip < &ibuf[NIREAD]; ip++) {
        !           252:                        if (inum++ >= maxino)
        !           253:                                break;
        !           254:                        canshort(ip->di_uid);
        !           255:                        canshort(ip->di_mode);
        !           256:                        cansize(ip->di_size);
        !           257:                        if (ilook(ip, inum))
        !           258:                                return (0);
        !           259:                }
        !           260:                if (inum > maxino)
        !           261:                        break;
        !           262:        }
        !           263:        return (0);
        !           264: }
        !           265: 
        !           266: /*
        !           267:  * Routine that looks at every I-node
        !           268:  * that we find.
        !           269:  * Return 1 for premature end.
        !           270:  */
        !           271: ilook(ip, ino)
        !           272: register struct dinode *ip;
        !           273: register ino_t ino;
        !           274: {
        !           275: 
        !           276:        if (ip->di_mode == 0)
        !           277:                return (0);
        !           278:        if (nflag) {
        !           279:                register char *lp;
        !           280: 
        !           281:                while (ino > readino) {
        !           282:                        if (gets(line) == NULL)
        !           283:                                return (1);
        !           284:                        for (lp=line; *lp==' ' || *lp=='\t'; lp++)
        !           285:                                ;
        !           286:                        if (!isdigit(*lp))
        !           287:                                continue;
        !           288:                        readino = atoi(lp);
        !           289:                        while (isdigit(*lp))
        !           290:                                lp++;
        !           291:                        while (*lp==' ' || *lp=='\t')
        !           292:                                lp++;
        !           293:                        readfile = lp;
        !           294:                }
        !           295:                if (readino == ino)
        !           296:                        printf("%-16s %s\n", username(ip->di_uid), readfile);
        !           297:        } else if (cflag) {
        !           298:                register CENTRY *cep;
        !           299:                long size;
        !           300: 
        !           301:                size = (ip->di_size+BSIZE-1)/BSIZE;
        !           302:                cep = getcentry(size);
        !           303:                cep->c_nfiles++;
        !           304:        } else {
        !           305:                register FENTRY *fep;
        !           306: 
        !           307:                fep = getfentry(ip->di_uid);
        !           308:                fep->f_nfiles++;
        !           309:                switch (ip->di_mode & IFMT) {
        !           310:                case IFREG:
        !           311:                case IFDIR:
        !           312:                        fep->f_nblocks += (ip->di_size+BSIZE-1)/BSIZE;
        !           313:                        break;
        !           314:                }
        !           315:        }
        !           316:        return (0);
        !           317: }
        !           318: 
        !           319: /*
        !           320:  * Using hashing from a large pool,
        !           321:  * return a pointer to where the FENTRY
        !           322:  * for that uid was put or created.
        !           323:  * The table has to be contiguous for sorting.
        !           324:  */
        !           325: FENTRY *
        !           326: getfentry(uid)
        !           327: register short unsigned uid;
        !           328: {
        !           329:        register FENTRY *fep;
        !           330: 
        !           331:        fep = &fentries[(uid<<1)%nuids];
        !           332:        for (;;) {
        !           333:                if (fep >= efp)
        !           334:                        fep = fentries;
        !           335:                if (fep->f_uid == uid)
        !           336:                        return (fep);
        !           337:                if (fep->f_uid == BADUID) {
        !           338:                        fep->f_uid = uid;
        !           339:                        return (fep);
        !           340:                }
        !           341:                fep++;
        !           342:        }
        !           343: }
        !           344: 
        !           345: /*
        !           346:  * Return a CENTRY for a particular file size.
        !           347:  * This is hashed much like the FENTRY code
        !           348:  * above.
        !           349:  */
        !           350: CENTRY *
        !           351: getcentry(nb)
        !           352: long nb;
        !           353: {
        !           354:        register CENTRY *cep;
        !           355: 
        !           356:        cep = &centries[((unsigned)nb<<1)%NCUM];
        !           357:        for (;;) {
        !           358:                if (cep >= ecp)
        !           359:                        cep = centries;
        !           360:                if (cep->c_nblocks == nb)
        !           361:                        return (cep);
        !           362:                if (cep->c_nblocks == BADSIZE) {
        !           363:                        cep->c_nblocks = nb;
        !           364:                        if (cep > lastcep)
        !           365:                                lastcep = cep+1;
        !           366:                        return (cep);
        !           367:                }
        !           368:                cep++;
        !           369:        }
        !           370: }
        !           371: 
        !           372: /*
        !           373:  * Read all of the names from `/etc/passwd'
        !           374:  * and build up a hash table.
        !           375:  * Duplicates are discarded.
        !           376:  */
        !           377: readnames()
        !           378: {
        !           379:        register NAME *np;
        !           380:        register unsigned short hash;
        !           381:        register struct passwd *pwp;
        !           382: 
        !           383:        while ((pwp = getpwent()) != NULL) {
        !           384:                hash = pwp->pw_uid%NHASH;
        !           385:                for (np = names[hash]; np != NULL; np = np->n_next)
        !           386:                        if (np->n_uid == pwp->pw_uid)
        !           387:                                break;
        !           388:                if (np == NULL) {
        !           389:                        nuids++;
        !           390:                        np = (NAME*)alloc(sizeof(NAME)+strlen(pwp->pw_name)+1);
        !           391:                        strcpy(np->n_name, pwp->pw_name);
        !           392:                        np->n_uid = pwp->pw_uid;
        !           393:                        np->n_next = names[hash];
        !           394:                        names[hash] = np;
        !           395:                }
        !           396:        }
        !           397:        endpwent();
        !           398: }
        !           399: 
        !           400: /*
        !           401:  * Return user name for a particular number.
        !           402:  * Names that are not located are given the string
        !           403:  * representation of the number.
        !           404:  */
        !           405: char *
        !           406: username(uid)
        !           407: unsigned short uid;
        !           408: {
        !           409:        register NAME *np;
        !           410:        static char buf[12];
        !           411: 
        !           412:        for (np = names[uid%NHASH]; np != NULL; np = np->n_next)
        !           413:                if (np->n_uid == uid)
        !           414:                        return (np->n_name);
        !           415:        return (sprintf(buf, "%u", uid));
        !           416: }
        !           417: 
        !           418: /*
        !           419:  * Comparison routine for no options
        !           420:  * and `-f'.  Sort by # blocks, then
        !           421:  * # files.
        !           422:  */
        !           423: fcomp(fep1, fep2)
        !           424: register FENTRY *fep1, *fep2;
        !           425: {
        !           426:        if (fep1->f_nblocks < fep2->f_nblocks)
        !           427:                return (1);
        !           428:        if (fep1->f_nblocks > fep2->f_nblocks)
        !           429:                return (-1);
        !           430:        if (fep1->f_nfiles < fep2->f_nfiles)
        !           431:                return (1);
        !           432:        if (fep1->f_nfiles > fep2->f_nfiles)
        !           433:                return (-1);
        !           434:        return (0);
        !           435: }
        !           436: 
        !           437: /*
        !           438:  * Sort comparison routine for the
        !           439:  * `-c' (cumulative size table)
        !           440:  * option.
        !           441:  */
        !           442: ccomp(cep1, cep2)
        !           443: register CENTRY *cep1, *cep2;
        !           444: {
        !           445:        if (cep1->c_nblocks < cep2->c_nblocks)
        !           446:                return (-1);
        !           447:        if (cep1->c_nblocks > cep2->c_nblocks)
        !           448:                return (1);
        !           449:        return (0);
        !           450: }
        !           451: 
        !           452: /*
        !           453:  * Call allocator and check for errors.
        !           454:  */
        !           455: char *
        !           456: alloc(nb)
        !           457: register unsigned nb;
        !           458: {
        !           459:        register char *ap;
        !           460: 
        !           461:        if ((ap = calloc(nb, 1)) == NULL)
        !           462:                cerr("out of memory");
        !           463:        return (ap);
        !           464: }
        !           465: 
        !           466: /*
        !           467:  * Errors and usage message.
        !           468:  */
        !           469: /* VARARGS */
        !           470: cerr(x)
        !           471: {
        !           472:        fprintf(stderr, "quot: %r\n", &x);
        !           473:        exit(1);
        !           474: }
        !           475: 
        !           476: cwarn(x)
        !           477: {
        !           478:        fprintf(stderr, "quot: %r\n", &x);
        !           479:        exit(1);
        !           480: }
        !           481: 
        !           482: usage()
        !           483: {
        !           484:        fprintf(stderr, "Usage: quot [-n] [-c] [-ft] filesystem [ ... ]\n");
        !           485:        exit(1);
        !           486: }

unix.superglobalmegacorp.com

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