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

1.1     ! root        1: /*
        !             2:  * Print a disc usage summary for
        !             3:  * some directories.
        !             4:  */
        !             5: 
        !             6: #include <stdio.h>
        !             7: #include <sys/types.h>
        !             8: #include <sys/dir.h>
        !             9: #include <sys/stat.h>
        !            10: #include <sys/ino.h>
        !            11: #include <errno.h>
        !            12: 
        !            13: #define        DIOSIZ  (BUFSIZ/8)      /* Size of directory i/o, until stacks grow */
        !            14: #define        NLINK   500             /* Size of link table */
        !            15: #define        NFNAME  1000            /* Size of filename */
        !            16: #define        NRECUR  12              /* Depth of recursion < NFILE-3-2 */
        !            17: 
        !            18: int    aflag;                  /* do files as well */
        !            19: int    sflag;                  /* only give total */
        !            20: int    depth;                  /* recursion depth */
        !            21: 
        !            22: struct linktab {
        !            23:        ino_t   l_ino;
        !            24:        dev_t   l_dev;
        !            25: }      linktab[NLINK];
        !            26: struct linktab *ltp;
        !            27: 
        !            28: char   fname[NFNAME];
        !            29: 
        !            30: char   toodeep[] = "directory structure too deep to traverse";
        !            31: 
        !            32: struct stat    sb;
        !            33: 
        !            34: /*
        !            35:  * indirect block overhead based upon size of file
        !            36:  */
        !            37: long   ranges[] = {
        !            38:        ND,                             /* direct blocks */
        !            39:        ND + NBN,                       /* single indirect */
        !            40:        ND + NBN*NBN,                   /* double indirect */
        !            41:        ND + NBN*NBN*NBN                /* tripple indirect */
        !            42: };
        !            43:        
        !            44: long   duentry();
        !            45: long   dufork();
        !            46: long   dusize();
        !            47: char   *buildname();
        !            48: void   duerr();
        !            49: void   dumsg();
        !            50: void   usage();
        !            51: void   main();
        !            52: 
        !            53: void
        !            54: main(argc, argv)
        !            55: char *argv[];
        !            56: {
        !            57:        register int i;
        !            58:        register char *ap;
        !            59:        int estat;
        !            60: 
        !            61:        while (argc>1 && *argv[1]=='-') {
        !            62:                for (ap = &argv[1][1]; *ap != '\0'; ap++)
        !            63:                        switch (*ap) {
        !            64:                        case 'a':
        !            65:                                aflag = 1;
        !            66:                                break;
        !            67: 
        !            68:                        case 's':
        !            69:                                sflag = 1;
        !            70:                                break;
        !            71: 
        !            72:                        default:
        !            73:                                usage();
        !            74:                        }
        !            75:                argc--;
        !            76:                argv++;
        !            77:        }
        !            78:        if (argc < 2)
        !            79:                estat = du(".");
        !            80:        else {
        !            81:                estat = 0;
        !            82:                for (i=1; i<argc; i++)
        !            83:                        estat |= du(argv[i]);
        !            84:        }
        !            85:        exit (estat);
        !            86: }
        !            87: 
        !            88: /*
        !            89:  * Print out disc usage summary
        !            90:  */
        !            91: du(name)
        !            92: char *name;
        !            93: {
        !            94:        register char *ep, *cp;
        !            95:        fsize_t size;
        !            96:        int nondir;
        !            97: 
        !            98:        ltp = linktab;
        !            99:        cp = name;
        !           100:        ep = fname;
        !           101:        while (*cp)
        !           102:                *ep++ = *cp++;
        !           103:        *ep = '\0';
        !           104:        if (stat(name, &sb) < 0)
        !           105:                duerr("%s: nonexistent", name);
        !           106:        nondir = (sb.st_mode&S_IFMT) != S_IFDIR;
        !           107:        size = duentry(ep, &sb);
        !           108:        if (sflag || nondir)
        !           109:                printf("%ld\t%s\n", size, fname);
        !           110:        return (0);
        !           111: }
        !           112: 
        !           113: /*
        !           114:  * Do a du on a single entry
        !           115:  * The pointer is the end pointer
        !           116:  * into the fname buffer.
        !           117:  */
        !           118: long
        !           119: duentry(ep, sbp)
        !           120: char *ep;
        !           121: struct stat *sbp;
        !           122: {
        !           123:        extern int errno;
        !           124:        fsize_t total, fsize;
        !           125:        char iobuf[DIOSIZ];
        !           126:        register char *np;
        !           127:        register struct direct *dp;
        !           128:        register int nb;
        !           129:        int fd;
        !           130:        int dirf;
        !           131: 
        !           132:        switch (sbp->st_mode & S_IFMT) {
        !           133:        case S_IFREG:
        !           134:                return (dusize(sbp));
        !           135: 
        !           136:        case S_IFDIR:
        !           137:                total = dusize(sbp);
        !           138:                if (++depth >= NRECUR) {
        !           139:                        depth = 0;
        !           140:                        return (dufork(ep, sbp));
        !           141:                }
        !           142:                if ((fd = open(fname, 0)) < 0) {
        !           143:                        dumsg("cannot open `%s'", fname);
        !           144:                        return (0);
        !           145:                }
        !           146:                while ((nb = read(fd, iobuf, DIOSIZ)) > 0)
        !           147:                        for (dp = iobuf; dp < &iobuf[nb]; dp++) {
        !           148:                                np = dp->d_name;
        !           149:                                if (*np++=='.'
        !           150:                                  && (*np=='\0' || (*np++=='.' && *np=='\0')))
        !           151:                                        continue;
        !           152:                                if (dp->d_ino == 0)
        !           153:                                        continue;
        !           154:                                if ((np = buildname(dp, ep)) == NULL)
        !           155:                                        continue;
        !           156:                                if (stat(fname, &sb) < 0) {
        !           157:                                        dumsg("stat failed on `%s'", fname);
        !           158:                                        continue;
        !           159:                                }
        !           160:                                dirf = (sb.st_mode&S_IFMT)==S_IFDIR;
        !           161:                                fsize = duentry(np, sbp);
        !           162:                                if (aflag && !sflag && !dirf)
        !           163:                                        prsize(fsize);
        !           164:                                total += fsize;
        !           165:                        }
        !           166:                if (nb < 0)
        !           167:                        dumsg("%s: directory read error", fname);
        !           168:                close(fd);
        !           169:                *ep = '\0';
        !           170:                if (!sflag)
        !           171:                        prsize(total);
        !           172:                --depth;
        !           173:                return (total);
        !           174: 
        !           175:        default:
        !           176:                return (0);
        !           177:        }
        !           178: }
        !           179: 
        !           180: /*
        !           181:  * Fork to do a du on recursive directory
        !           182:  * structure that is too deep to fit into
        !           183:  * user's open files.
        !           184:  */
        !           185: long
        !           186: dufork(ep, sbp)
        !           187: char *ep;
        !           188: struct stat *sbp;
        !           189: {
        !           190:        register int i;
        !           191:        register int pid;
        !           192:        int pfd[2] = {0, 0};
        !           193:        int status;
        !           194:        long sz = 0;
        !           195: 
        !           196:        fflush(stdout);
        !           197:        if (pipe(pfd)<0 || (pid = fork())<0) {
        !           198:                if (pfd[0]) {
        !           199:                        close(pfd[0]);
        !           200:                        close(pfd[1]);
        !           201:                }
        !           202:                dumsg(toodeep);
        !           203:                return (0);
        !           204:        }
        !           205:        if (pid) {
        !           206:                close(pfd[1]);
        !           207:                while (wait(&status) >= 0)
        !           208:                        ;
        !           209:                if (status || read(pfd[0], &sz, sizeof(long)) != sizeof(long))
        !           210:                        sz = 0;
        !           211:                close(pfd[0]);
        !           212:                return (sz);
        !           213:        }
        !           214:        for (i=3; i<_NFILE; i++)
        !           215:                if (i != pfd[1])
        !           216:                        close(i);
        !           217:        sz = duentry(ep, sbp);
        !           218:        write(pfd[1], &sz, sizeof(long));
        !           219:        close(pfd[1]);
        !           220:        exit(0);
        !           221: }
        !           222: 
        !           223: /*
        !           224:  * Do a du on a single file.
        !           225:  * Now takes into account indirect blocks.
        !           226:  */
        !           227: long
        !           228: dusize(sbp)
        !           229: struct stat *sbp;
        !           230: {
        !           231:        register int i;
        !           232:        register long blocks;
        !           233: 
        !           234:        if ((sbp->st_mode & S_IFMT) != S_IFDIR
        !           235:         && sbp->st_nlink > 1
        !           236:         && addlink(sbp->st_dev, sbp->st_ino))
        !           237:                return (0);
        !           238:        blocks = (sbp->st_size+BUFSIZ-1) / BUFSIZ;
        !           239:        for (i = 0; i < sizeof(ranges)/sizeof(ranges[0]); ++i)
        !           240:                if (blocks <= ranges[i])
        !           241:                        break;
        !           242:        return (blocks + i);
        !           243: }
        !           244: 
        !           245: /*
        !           246:  * Print out a size line.
        !           247:  */
        !           248: prsize(blocks)
        !           249: fsize_t blocks;
        !           250: {
        !           251:        printf("%ld\t%s\n", blocks, fname);
        !           252: }
        !           253: 
        !           254: /*
        !           255:  * Build up the next entry
        !           256:  * in the name.
        !           257:  */
        !           258: char *
        !           259: buildname(dp, ep)
        !           260: struct direct *dp;
        !           261: register char *ep;
        !           262: {
        !           263:        register char *cp = dp->d_name;
        !           264:        register unsigned n = DIRSIZ;
        !           265: 
        !           266:        if (ep+DIRSIZ+2 >= &fname[NFNAME]) {
        !           267:                dumsg(toodeep);
        !           268:                return (NULL);
        !           269:        }
        !           270:        if (ep[-1] != '/')
        !           271:                *ep++ = '/';
        !           272:        do {
        !           273:                if (*cp == '\0')
        !           274:                        break;
        !           275:                *ep++ = *cp++;
        !           276:        } while (--n);
        !           277:        *ep = '\0';
        !           278:        return (ep);
        !           279: }
        !           280: 
        !           281: /*
        !           282:  * Add an entry to the table
        !           283:  * of i-numbers with multiple links.
        !           284:  * If there are too many multi-link files,
        !           285:  * they will get counted twice.
        !           286:  * Return 1 if already there.
        !           287:  */
        !           288: addlink(dev, ino)
        !           289: register dev_t dev;
        !           290: register ino_t ino;
        !           291: {
        !           292:        register struct linktab *lp;
        !           293: 
        !           294:        for (lp = linktab; lp<ltp; lp++)
        !           295:                if (lp->l_ino==ino && lp->l_dev==dev)
        !           296:                        return (1);
        !           297:        if (lp-linktab >= NLINK)
        !           298:                return (0);
        !           299:        lp->l_ino = ino;
        !           300:        lp->l_dev = dev;
        !           301:        ltp++;
        !           302:        return (0);
        !           303: }
        !           304: 
        !           305: void
        !           306: usage()
        !           307: {
        !           308:        fprintf(stderr, "Usage: du [-s] [name ...]\n");
        !           309:        exit(1);
        !           310: }
        !           311: 
        !           312: /* VARARGS */
        !           313: void
        !           314: duerr(x)
        !           315: {
        !           316:        fprintf(stderr, "du: %r\n", &x);
        !           317:        exit (1);
        !           318: }
        !           319: 
        !           320: /* VARARGS */
        !           321: void
        !           322: dumsg(x)
        !           323: {
        !           324:        fprintf(stderr, "du: %r\n", &x);
        !           325: }

unix.superglobalmegacorp.com

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