sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

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 }