Annotation of coherent/d/bin/du.c, revision 1.1.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.