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);
+               }
+       }
 }

Reply via email to