#include "stat.h" /* du [dir]: disk usage per entry, and a total, in 256-byte blocks. * * Blocks, not bytes, for two reasons: it is the unit df(1) and the filesystem * itself use, and bytes overflow - /bin alone is 52 programs x 16 KiB, which * wraps a 16-bit counter (it printed 32768). * * Recurses by re-opendir'ing: the kernel keeps ONE "directory being listed" * (wListDir), so walking into a child loses the parent's cursor - the parent * has to be re-opened and re-indexed on the way back up. With 32 inodes and * shallow trees that costs nothing. */ #define MAXDEPTH 3 static unsigned int total; /* 256-byte blocks */ static void pad(unsigned int n, unsigned char w) { unsigned char d = 1; unsigned int v = n; while (v >= 10) { v = v / 10; d++; } while (d++ < w) putc(' '); putu(n); } /* sum one directory, printing each entry; returns its byte total */ static unsigned int walk(char *path, unsigned char depth) { char name[16]; char child[40]; struct gstat st; unsigned int sum = 0; unsigned char i, j, k; for (i = 0;; i++) { if (opendir(path)) return sum; /* re-open: flist has one cursor */ if (!flist(i, name)) break; name[15] = 0; j = 0; for (k = 0; path[k] && j < 30; k++) child[j++] = path[k]; if (j && child[j - 1] != '/') child[j++] = '/'; for (k = 0; name[k] && j < 38; k++) child[j++] = name[k]; child[j] = 0; if (!gstat(child, &st)) continue; if (st.type == ST_DIR && depth < MAXDEPTH) { sum += walk(child, (unsigned char)(depth + 1)); } else { { unsigned int blk = (unsigned int)((st.size + 255) / 256); sum += blk; pad(blk, 6); } putc(' '); puts(child); nl(); } } pad(sum, 6); putc(' '); puts(path); nl(); return sum; } void main(void) { char dir[32]; char *argv[4]; unsigned char argc = argv_parse(argv, 4); unsigned char i, j, have = 0; /* copy the argument before gstat's static request block lands on $A000 */ for (i = 0; i < argc; i++) if (argv[i][0] != '-') { for (j = 0; argv[i][j] && j < 31; j++) dir[j] = argv[i][j]; dir[j] = 0; have = 1; break; } if (!have) { dir[0] = '/'; dir[1] = 0; } total = walk(dir, 0); }