diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-03-06 05:04:26 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-03-06 05:06:30 +0100 |
| commit | 804b8841f3fe59f7058c91fa25c1694f4433642a (patch) | |
| tree | 1222273bfcbc1321095f0688837176d2fa0d46ad /cftw.c | |
| parent | 3e95727e275f650d2c6703aa8753b1c72d366d40 (diff) | |
| download | slcl-804b8841f3fe59f7058c91fa25c1694f4433642a.tar.gz | |
Add cftw
POSIX functions ftw(3) and nftw(3) do not allow passing an opaque
pointer to the callback they call, so it forces the use of statically
allocated data.
ctfw (from "custom ftw") is a custom implementation that solves this,
while also removing unneeded stuff.
This function will be used by future commits.
Diffstat (limited to 'cftw.c')
| -rw-r--r-- | cftw.c | 61 |
1 files changed, 61 insertions, 0 deletions
@@ -0,0 +1,61 @@ +#include "cftw.h" +#include <dynstr.h> +#include <dirent.h> +#include <sys/stat.h> +#include <errno.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +int cftw(const char *const dirpath, int (*const fn)(const char *, + const struct stat *, void *), void *const user) +{ + DIR *const d = opendir(dirpath); + struct dirent *de; + + if (!d) + { + fprintf(stderr, "%s: opendir(2): %s\n", __func__, strerror(errno)); + return -1; + } + + while ((de = readdir(d))) + { + const char *const path = de->d_name; + + if (!strcmp(path, ".") || !strcmp(path, "..")) + continue; + + struct stat sb; + struct dynstr d; + + dynstr_init(&d); + + if (dynstr_append(&d, "%s/%s", dirpath, path)) + { + fprintf(stderr, "%s: dynstr_append failed\n", __func__); + return -1; + } + + const int r = stat(d.str, &sb); + int ret = -1; + + if (r) + fprintf(stderr, "%s: stat(2) %s: %s\n", + __func__, path, strerror(errno)); + else if (S_ISDIR(sb.st_mode)) + ret = cftw(d.str, fn, user); + else if (S_ISREG(sb.st_mode)) + ret = fn(d.str, &sb, user); + else + fprintf(stderr, "%s: unexpected st_mode %ju\n", + __func__, (uintmax_t)sb.st_mode); + + dynstr_free(&d); + + if (ret) + return ret; + } + + return 0; +} |
