commit 6591fb988884755d9f3c065add8ace0bf3747157
Author: Roberto E. Vargas Caballero <[email protected]>
AuthorDate: Fri Mar 22 04:32:56 2024 +0100
Commit: Roberto E. Vargas Caballero <[email protected]>
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);
+ }
+ }
}