commit 6591fb988884755d9f3c065add8ace0bf3747157 Author: Roberto E. Vargas Caballero <k...@shike2.com> AuthorDate: Fri Mar 22 04:32:56 2024 +0100 Commit: Roberto E. Vargas Caballero <k...@shike2.com> CommitDate: Thu Dec 19 13:35:08 2024 +0100
Move more things around diff --git a/ubase/libutil/ealloc.c b/ubase/libutil/ealloc.c index 05bdd62..320865d 100644 --- a/ubase/libutil/ealloc.c +++ b/ubase/libutil/ealloc.c @@ -6,42 +6,83 @@ void * ecalloc(size_t nmemb, size_t size) +{ + return encalloc(1, nmemb, size); +} + +void * +emalloc(size_t size) +{ + return enmalloc(1, size); +} + +void * +erealloc(void *p, size_t size) +{ + return enrealloc(1, p, size); +} + +char * +estrdup(const char *s) +{ + return enstrdup(1, s); +} + +char * +estrndup(const char *s, size_t n) +{ + return enstrndup(1, s, n); +} + +void * +encalloc(int status, size_t nmemb, size_t size) { void *p; p = calloc(nmemb, size); if (!p) - eprintf("calloc: out of memory\n"); + enprintf(status, "calloc: out of memory\n"); return p; } void * -emalloc(size_t size) +enmalloc(int status, size_t size) { void *p; p = malloc(size); if (!p) - eprintf("malloc: out of memory\n"); + enprintf(status, "malloc: out of memory\n"); return p; } void * -erealloc(void *p, size_t size) +enrealloc(int status, void *p, size_t size) { p = realloc(p, size); if (!p) - eprintf("realloc: out of memory\n"); + enprintf(status, "realloc: out of memory\n"); return p; } char * -estrdup(const char *s) +enstrdup(int status, const char *s) { char *p; p = strdup(s); if (!p) - eprintf("strdup: out of memory\n"); + enprintf(status, "strdup: out of memory\n"); + return p; +} + +char * +enstrndup(int status, const char *s, size_t n) +{ + char *p; + + p = strndup(s, n); + if (!p) + enprintf(status, "strndup: out of memory\n"); return p; } diff --git a/ubase/libutil/putword.c b/ubase/libutil/putword.c index c460703..80a9860 100644 --- a/ubase/libutil/putword.c +++ b/ubase/libutil/putword.c @@ -4,13 +4,13 @@ #include "../util.h" void -putword(const char *s) +putword(FILE *fp, const char *s) { static int first = 1; if (!first) - putchar(' '); + fputc(' ', fp); - fputs(s, stdout); + fputs(s, fp); first = 0; } diff --git a/ubase/libutil/recurse.c b/ubase/libutil/recurse.c index 318987d..e66efaf 100644 --- a/ubase/libutil/recurse.c +++ b/ubase/libutil/recurse.c @@ -1,5 +1,7 @@ /* See LICENSE file for copyright and license details. */ #include <dirent.h> +#include <errno.h> +#include <fcntl.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> @@ -8,35 +10,99 @@ #include <sys/types.h> #include <unistd.h> +#include "../fs.h" #include "../util.h" +int recurse_status = 0; + void -recurse(const char *path, void (*fn)(const char *)) +recurse(int dirfd, const char *name, void *data, struct recursor *r) { - char buf[PATH_MAX]; struct dirent *d; - struct stat st; + struct history *new, *h; + struct stat st, dst; DIR *dp; + int flags = 0, fd; + size_t pathlen = r->pathlen; + + if (dirfd == AT_FDCWD) + pathlen = estrlcpy(r->path, name, sizeof(r->path)); + + if (r->follow == 'P' || (r->follow == 'H' && r->depth)) + flags |= AT_SYMLINK_NOFOLLOW; - if (lstat(path, &st) == -1 || S_ISDIR(st.st_mode) == 0) + if (fstatat(dirfd, name, &st, flags) < 0) { + if (!(r->flags & SILENT)) { + weprintf("stat %s:", r->path); + recurse_status = 1; + } return; + } + if (!S_ISDIR(st.st_mode)) { + r->fn(dirfd, name, &st, data, r); + return; + } - if (!(dp = opendir(path))) - eprintf("opendir %s:", path); - - while ((d = readdir(dp))) { - if (strcmp(d->d_name, ".") == 0 || - strcmp(d->d_name, "..") == 0) - continue; - if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) - eprintf("path too long\n"); - if (buf[strlen(buf) - 1] != '/') - if (strlcat(buf, "/", sizeof(buf)) >= sizeof(buf)) - eprintf("path too long\n"); - if (strlcat(buf, d->d_name, sizeof(buf)) >= sizeof(buf)) - eprintf("path too long\n"); - fn(buf); + new = emalloc(sizeof(struct history)); + new->prev = r->hist; + r->hist = new; + new->dev = st.st_dev; + new->ino = st.st_ino; + + for (h = new->prev; h; h = h->prev) + if (h->ino == st.st_ino && h->dev == st.st_dev) + return; + + if (!r->depth && (r->flags & DIRFIRST)) + r->fn(dirfd, name, &st, data, r); + + if (!r->maxdepth || r->depth + 1 < r->maxdepth) { + fd = openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_DIRECTORY); + if (fd < 0) { + weprintf("open %s:", r->path); + recurse_status = 1; + } + if (!(dp = fdopendir(fd))) { + if (!(r->flags & SILENT)) { + weprintf("fdopendir:"); + recurse_status = 1; + } + return; + } + if (r->path[pathlen - 1] != '/') + r->path[pathlen++] = '/'; + if (r->follow == 'H') + flags |= AT_SYMLINK_NOFOLLOW; + while ((d = readdir(dp))) { + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + r->pathlen = pathlen + estrlcpy(r->path + pathlen, d->d_name, sizeof(r->path) - pathlen); + if (fstatat(fd, d->d_name, &dst, flags) < 0) { + if (!(r->flags & SILENT)) { + weprintf("stat %s:", r->path); + recurse_status = 1; + } + } else if ((r->flags & SAMEDEV) && dst.st_dev != st.st_dev) { + continue; + } else { + r->depth++; + r->fn(fd, d->d_name, &dst, data, r); + r->depth--; + } + } + r->path[pathlen - 1] = '\0'; + r->pathlen = pathlen - 1; + closedir(dp); } - closedir(dp); + if (!r->depth) { + if (!(r->flags & DIRFIRST)) + r->fn(dirfd, name, &st, data, r); + + while (r->hist) { + h = r->hist; + r->hist = r->hist->prev; + free(h); + } + } }