From e9a910b33c7837b4b868e3abda18eb4810df7f02 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Sat, 4 Oct 2025 09:14:33 +0100 Subject: config/git: import suckless sbase i currently use the output of sha512sum in several places of xbmk, which is a bit unreliable in case output changes. other cases where i use util outputs in variables are probably reliable, because i'm using mostly posix utilities in those. to mitigate this, i now import suckless sbase, which has a reasonable sha512sum implementation. *every* binary it builds is being placed in build.list, because i'll probably start using more of them. for example, i may start modifying the "date" implementation, adding the GNU-specific options that i need as mentioned on init.sh i'm importing it in util/ because the sha512sum util is needed for verifying project sources, so if sbase itself is a "project source", that means we can into a chicken and egg bootstrapping problem. this is sbase at revision: 055cc1ae1b3a13c3d8f25af0a4a3316590efcd48 Signed-off-by: Leah Rowe --- util/sbase/du.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 util/sbase/du.c (limited to 'util/sbase/du.c') diff --git a/util/sbase/du.c b/util/sbase/du.c new file mode 100644 index 00000000..782b09a2 --- /dev/null +++ b/util/sbase/du.c @@ -0,0 +1,167 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#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; + +struct file { + dev_t devno; + ino_t inode; +}; + +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 int +cmp(const void *p1, const void *p2) +{ + const struct file *f1 = p1, *f2 = p2; + + if (f1->devno > f2->devno) + return -1; + if (f1->devno < f2->devno) + return 1; + + /* f1->devno == f2->devno */ + if (f1->inode < f2->inode) + return -1; + if (f1->inode > f2->inode) + return 1; + + return 0; +} + +static int +duplicated(dev_t dev, ino_t ino) +{ + static void *tree; + struct file **fpp, *fp, file = {dev, ino}; + + if ((fpp = tsearch(&file, &tree, cmp)) == NULL) + eprintf("%s:", argv0); + + if (*fpp != &file) + return 1; + + /* new file added */ + fp = emalloc(sizeof(*fp)); + *fp = file; + *fpp = fp; + + return 0; +} + +static void +du(int dirfd, const char *path, struct stat *st, void *data, struct recursor *r) +{ + off_t *total = data, subtotal; + + subtotal = nblks(st->st_blocks); + if (S_ISDIR(st->st_mode)) { + recurse(dirfd, path, &subtotal, r); + } else if (r->follow != 'P' || st->st_nlink > 1) { + if (duplicated(st->st_dev, st->st_ino)) + goto print; + } + + *total += subtotal; + +print: + if (!r->depth) + printpath(*total, r->path); + else if (!sflag && r->depth <= maxdepth && (S_ISDIR(st->st_mode) || aflag)) + printpath(subtotal, r->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, .follow = 'P' }; + 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(AT_FDCWD, ".", &n, &r); + } else { + for (; *argv; argc--, argv++) { + n = 0; + recurse(AT_FDCWD, *argv, &n, &r); + } + } + + return fshut(stdout, "") || recurse_status; +} -- cgit v1.2.1