/* See LICENSE file for copyright and license details. */ #include #include #include #include #include #include #include #include #include "fs.h" #include "util.h" static size_t maxdepth = SIZE_MAX; static size_t blksize = 512; static int aflag = 0; static int sflag = 0; static int hflag = 0; static void printpath(off_t n, const char *path) { if (hflag) printf("%s\t%s\n", humansize(n * blksize), path); else printf("%jd\t%s\n", (intmax_t)n, path); } static off_t nblks(blkcnt_t blocks) { return (512 * blocks + blksize - 1) / blksize; } static void du(const char *path, struct stat *st, void *total, struct recursor *r) { off_t subtotal = 0; if (st && S_ISDIR(st->st_mode)) recurse(path, &subtotal, r); *((off_t *)total) += subtotal + nblks(st ? st->st_blocks : 0); if (!sflag && r->depth <= maxdepth && r->depth && st && (S_ISDIR(st->st_mode) || aflag)) printpath(subtotal + nblks(st->st_blocks), path); } static void usage(void) { eprintf("usage: %s [-a | -s] [-d depth] [-h] [-k] [-H | -L | -P] [-x] [file ...]\n", argv0); } int main(int argc, char *argv[]) { struct recursor r = { .fn = du, .hist = NULL, .depth = 0, .maxdepth = 0, .follow = 'P', .flags = 0 }; off_t n = 0; int kflag = 0, dflag = 0; char *bsize; ARGBEGIN { case 'a': aflag = 1; break; case 'd': dflag = 1; maxdepth = estrtonum(EARGF(usage()), 0, MIN(LLONG_MAX, SIZE_MAX)); break; case 'h': hflag = 1; break; case 'k': kflag = 1; break; case 's': sflag = 1; break; case 'x': r.flags |= SAMEDEV; break; case 'H': case 'L': case 'P': r.follow = ARGC(); break; default: usage(); } ARGEND if ((aflag && sflag) || (dflag && sflag)) usage(); bsize = getenv("BLOCKSIZE"); if (bsize) blksize = estrtonum(bsize, 1, MIN(LLONG_MAX, SIZE_MAX)); if (kflag) blksize = 1024; if (!argc) { recurse(".", &n, &r); printpath(n, "."); } else { for (; *argv; argc--, argv++) { n = 0; recurse(*argv, &n, &r); printpath(n, *argv); } } return fshut(stdout, "") || recurse_status; }