commit: 7c50cbab04faffa818b127dd3b55047dc01cfc4f
parent d32d759c54b2657970b62eba39f5707dee4bb8b9
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sun, 11 Jan 2026 14:52:57 +0100
libutils/lib_mkdir: fix recursion loop
Diffstat:
6 files changed, 101 insertions(+), 25 deletions(-)
diff --git a/Makefile b/Makefile
@@ -33,7 +33,7 @@ selfcheck-cmds: $(EXE) $(TEST_CMDS)
LDSTATIC="$(LDSTATIC)" ./check-cmds.sh
.PHONY: selfcheck-libs
-TEST_LIBS = test-libutils/t_mode test-libutils/t_strtodur test-libutils/t_symbolize_mode test-libutils/t_truncation test-lib/t_sha1 test-lib/t_sha256 test-lib/t_sha512 test-libutils/t_humanize test-libutils/t_strlcpy
+TEST_LIBS = test-libutils/t_mode test-libutils/t_strtodur test-libutils/t_symbolize_mode test-libutils/t_truncation test-lib/t_sha1 test-lib/t_sha256 test-lib/t_sha512 test-libutils/t_humanize test-libutils/t_strlcpy test-libutils/t_strip_lastelem
selfcheck-libs: $(TEST_LIBS)
LDSTATIC="$(LDSTATIC)" ./check-libs.sh $(TEST_LIBS)
@@ -181,3 +181,4 @@ test-libutils/t_strtodur: test-libutils/t_strtodur.c libutils/strtodur.o
test-libutils/t_strlcpy: test-libutils/t_strlcpy.c libutils/lib_strlcpy.o
test-libutils/t_symbolize_mode: test-libutils/t_symbolize_mode.c libutils/symbolize_mode.o
test-libutils/t_truncation: test-libutils/t_truncation.c libutils/truncation.o
+test-libutils/t_strip_lastelem: test-libutils/t_strip_lastelem.c libutils/strip_lastelem.o
diff --git a/libutils/fs.h b/libutils/fs.h
@@ -31,5 +31,5 @@ ssize_t auto_file_copy(int fd_in, int fd_out, off_t len, int flags);
ssize_t auto_fd_copy(int fd_in, int fd_out, size_t len);
#endif
-// lib/offline_realpath.c
+// libutils/offline_realpath.c
char *offline_realpath(const char *restrict filename, char *restrict resolved);
diff --git a/libutils/lib_mkdir.c b/libutils/lib_mkdir.c
@@ -8,6 +8,7 @@
#include "./lib_string.h"
#include "./mode.h"
+#include "./strip_lastelem.h"
#include <errno.h>
#include <limits.h> // PATH_MAX
@@ -64,34 +65,14 @@ wrap_mkdir(const char *path, mode_t mode)
return 0;
}
-static void
-strip_basename(char *parent)
-{
- size_t i = strlen(parent);
-
- while(i-- > 0)
- {
- if(parent[i] != '/') break;
-
- parent[i] = '\0';
- }
-
- while(i-- > 0)
- {
- if(parent[i] == '/') break;
-
- parent[i] = '\0';
- }
-}
-
static int
mkdir_elders(char *path, mode_t mode)
{
- if(path[0] == 0) return 0;
+ if(path[0] == '\0') return 0;
char parent[PATH_MAX] = "";
lib_strlcpy(parent, path, PATH_MAX);
- strip_basename(parent);
+ strip_lastelem(parent);
if(mkdir_elders(parent, mode) < 0) return -1;
@@ -129,7 +110,7 @@ mkdir_parents(char *path, mode_t mode)
char parent[PATH_MAX] = "";
lib_strlcpy(parent, path, PATH_MAX);
- strip_basename(parent);
+ strip_lastelem(parent);
mode_t elders_mode = (S_IWUSR | S_IXUSR | ~mkdir_parents_filemask) & 0777;
diff --git a/libutils/strip_lastelem.c b/libutils/strip_lastelem.c
@@ -0,0 +1,28 @@
+// utils-std: Collection of commonly available Unix tools
+// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#include "./strip_lastelem.h"
+
+#include <string.h>
+
+// "/foo/bar/" -> "/foo/"
+// "/foo/bar" -> "/foo/"
+// "/" -> ""
+void
+strip_lastelem(char *parent)
+{
+ size_t i = strlen(parent);
+ if(i == 0)
+ return;
+ else
+ i--;
+
+ while(i > 0 && parent[i] == '/')
+ parent[i--] = '\0';
+
+ while(i > 0 && parent[i] != '/')
+ parent[i--] = '\0';
+
+ if(i == 0) parent[i--] = '\0';
+}
diff --git a/libutils/strip_lastelem.h b/libutils/strip_lastelem.h
@@ -0,0 +1,5 @@
+// utils-std: Collection of commonly available Unix tools
+// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+void strip_lastelem(char *parent);
diff --git a/test-libutils/t_strip_lastelem.c b/test-libutils/t_strip_lastelem.c
@@ -0,0 +1,61 @@
+// utils-std: Collection of commonly available Unix tools
+// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#define _POSIX_C_SOURCE 200809L
+#include "../libutils/strip_lastelem.h"
+
+#include <assert.h>
+#include <stdio.h> // printf
+#include <string.h> // strcmp
+
+int counter = 0;
+int err = 0;
+
+static void
+t_strip_lastelem(const char *in, const char *exp)
+{
+ int id = ++counter;
+ static char buf[512];
+
+ strcpy(buf, in);
+
+ strip_lastelem(buf);
+
+ if(strcmp(buf, exp) == 0)
+ {
+ printf("ok %d - \"%s\" -> \"%s\"\n", id, in, exp);
+ return;
+ }
+
+ err = 1;
+ printf("not ok %d - \"%s\" -> \"%s\"\n", id, in, exp);
+ printf("# Got: \"%s\"\n", buf);
+}
+
+int
+main(void)
+{
+ int plan = 11;
+ printf("1..%d\n", plan);
+
+ t_strip_lastelem("", "");
+
+ t_strip_lastelem("/", "");
+ t_strip_lastelem("//", "");
+
+ t_strip_lastelem("/foo", "");
+ t_strip_lastelem("/foo/", "");
+
+ t_strip_lastelem("/foo/bar", "/foo/");
+ t_strip_lastelem("/foo/bar/", "/foo/");
+
+ t_strip_lastelem("a", "");
+ t_strip_lastelem("a/", "");
+
+ t_strip_lastelem("a/b", "a/");
+ t_strip_lastelem("a/b/", "a/");
+
+ assert(counter == plan);
+ return err;
+}