du.c (2121B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <sys/stat.h> 3 #include <sys/types.h> 4 5 #include <errno.h> 6 #include <limits.h> 7 #include <stdint.h> 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <unistd.h> 11 12 #include "fs.h" 13 #include "util.h" 14 15 static size_t maxdepth = SIZE_MAX; 16 static size_t blksize = 512; 17 18 static int aflag = 0; 19 static int sflag = 0; 20 static int hflag = 0; 21 22 static void 23 printpath(off_t n, const char *path) 24 { 25 if (hflag) 26 printf("%s\t%s\n", humansize(n * blksize), path); 27 else 28 printf("%jd\t%s\n", (intmax_t)n, path); 29 } 30 31 static off_t 32 nblks(blkcnt_t blocks) 33 { 34 return (512 * blocks + blksize - 1) / blksize; 35 } 36 37 static void 38 du(const char *path, struct stat *st, void *data, struct recursor *r) 39 { 40 off_t *total = data, subtotal; 41 42 subtotal = nblks(st->st_blocks); 43 if (S_ISDIR(st->st_mode)) 44 recurse(path, &subtotal, r); 45 *total += subtotal; 46 47 if (!r->depth) 48 printpath(*total, path); 49 else if (!sflag && r->depth <= maxdepth && (S_ISDIR(st->st_mode) || aflag)) 50 printpath(subtotal, path); 51 } 52 53 static void 54 usage(void) 55 { 56 eprintf("usage: %s [-a | -s] [-d depth] [-h] [-k] [-H | -L | -P] [-x] [file ...]\n", argv0); 57 } 58 59 int 60 main(int argc, char *argv[]) 61 { 62 struct recursor r = { .fn = du, .hist = NULL, .depth = 0, .maxdepth = 0, 63 .follow = 'P', .flags = 0 }; 64 off_t n = 0; 65 int kflag = 0, dflag = 0; 66 char *bsize; 67 68 ARGBEGIN { 69 case 'a': 70 aflag = 1; 71 break; 72 case 'd': 73 dflag = 1; 74 maxdepth = estrtonum(EARGF(usage()), 0, MIN(LLONG_MAX, SIZE_MAX)); 75 break; 76 case 'h': 77 hflag = 1; 78 break; 79 case 'k': 80 kflag = 1; 81 break; 82 case 's': 83 sflag = 1; 84 break; 85 case 'x': 86 r.flags |= SAMEDEV; 87 break; 88 case 'H': 89 case 'L': 90 case 'P': 91 r.follow = ARGC(); 92 break; 93 default: 94 usage(); 95 } ARGEND 96 97 if ((aflag && sflag) || (dflag && sflag)) 98 usage(); 99 100 bsize = getenv("BLOCKSIZE"); 101 if (bsize) 102 blksize = estrtonum(bsize, 1, MIN(LLONG_MAX, SIZE_MAX)); 103 if (kflag) 104 blksize = 1024; 105 106 if (!argc) { 107 recurse(".", &n, &r); 108 } else { 109 for (; *argv; argc--, argv++) { 110 n = 0; 111 recurse(*argv, &n, &r); 112 } 113 } 114 115 return fshut(stdout, "<stdout>") || recurse_status; 116 }