du.c (2108B)
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 <fcntl.h> 7 #include <limits.h> 8 #include <stdint.h> 9 #include <stdlib.h> 10 #include <stdio.h> 11 #include <unistd.h> 12 13 #include "fs.h" 14 #include "util.h" 15 16 static size_t maxdepth = SIZE_MAX; 17 static size_t blksize = 512; 18 19 static int aflag = 0; 20 static int sflag = 0; 21 static int hflag = 0; 22 23 static void 24 printpath(off_t n, const char *path) 25 { 26 if (hflag) 27 printf("%s\t%s\n", humansize(n * blksize), path); 28 else 29 printf("%jd\t%s\n", (intmax_t)n, path); 30 } 31 32 static off_t 33 nblks(blkcnt_t blocks) 34 { 35 return (512 * blocks + blksize - 1) / blksize; 36 } 37 38 static void 39 du(int dirfd, const char *path, struct stat *st, void *data, struct recursor *r) 40 { 41 off_t *total = data, subtotal; 42 43 subtotal = nblks(st->st_blocks); 44 if (S_ISDIR(st->st_mode)) 45 recurse(dirfd, path, &subtotal, r); 46 *total += subtotal; 47 48 if (!r->depth) 49 printpath(*total, r->path); 50 else if (!sflag && r->depth <= maxdepth && (S_ISDIR(st->st_mode) || aflag)) 51 printpath(subtotal, r->path); 52 } 53 54 static void 55 usage(void) 56 { 57 eprintf("usage: %s [-a | -s] [-d depth] [-h] [-k] [-H | -L | -P] [-x] [file ...]\n", argv0); 58 } 59 60 int 61 main(int argc, char *argv[]) 62 { 63 struct recursor r = { .fn = du, .follow = 'P' }; 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(AT_FDCWD, ".", &n, &r); 108 } else { 109 for (; *argv; argc--, argv++) { 110 n = 0; 111 recurse(AT_FDCWD, *argv, &n, &r); 112 } 113 } 114 115 return fshut(stdout, "<stdout>") || recurse_status; 116 }