[openssh-commits] [openssh] branch master updated: Add fallback for mkdir_path() without openat().

git+noreply at mindrot.org git+noreply at mindrot.org
Thu Sep 17 07:53:34 AEST 2026


This is an automated email from the git hooks/post-receive script.

dtucker pushed a commit to branch master
in repository openssh.

The following commit(s) were added to refs/heads/master by this push:
     new fb6d39e61 Add fallback for mkdir_path() without openat().
fb6d39e61 is described below

commit fb6d39e619f721ff588719c3ac8d417c0ebcffce
Author: Darren Tucker <dtucker at dtucker.net>
AuthorDate: Thu Sep 17 07:51:31 2026 +1000

    Add fallback for mkdir_path() without openat().
    
    Fixes builds on pre POSIX.1-2008 systems.
---
 configure.ac                       |  1 +
 misc.c                             | 36 ++++++++++++++++++++++++++++++++++++
 regress/unittests/misc/test_misc.c |  2 ++
 3 files changed, 39 insertions(+)

diff --git a/configure.ac b/configure.ac
index 224f29a5a..d4ccbe1ca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2170,6 +2170,7 @@ AC_CHECK_FUNCS([ \
 	nlist \
 	nsleep \
 	ogetaddrinfo \
+	openat \
 	openlog_r \
 	pledge \
 	poll \
diff --git a/misc.c b/misc.c
index dee84336e..866f7b8e2 100644
--- a/misc.c
+++ b/misc.c
@@ -3268,6 +3268,7 @@ get_homedir(void)
 int
 mkdir_path(const char *target, mode_t mode)
 {
+#if defined(HAVE_OPENAT) && defined(O_DIRECTORY)
 	char *dir, *odir = NULL, *next;
 	int fd = AT_FDCWD, fd2, subpath_len, ret = -1;
 
@@ -3311,4 +3312,39 @@ mkdir_path(const char *target, mode_t mode)
 	if (fd != AT_FDCWD)
 		close(fd);
 	return ret;
+#else
+	/*
+	 * If we don't have openat (which was added in POSIX.1-2008), fall back
+	 * to the possibly racy way.
+	 */
+	char *dir, *odir, *p, path[PATH_MAX] = "";
+	int ret = -1;
+	size_t plen = sizeof(path);
+
+	dir = odir = xstrdup(target);
+
+	/* If the dir is relative, start with cwd. */
+	if (*dir != '/' && getcwd(path, plen) == NULL) {
+		error_f("getcwd: %s", strerror(errno));
+		goto out;
+	}
+
+	/* Work through the path, component-wise */
+	while ((p = strsep(&dir, "/")) && p != '\0') {
+		if (strlcat(path, "/", plen) >= plen ||
+		    strlcat(path, p, plen) >= plen)
+			goto out;
+		if (mkdir(path, mode) == 0)
+			debug_f("created directory %s", path);
+		else if (errno != EEXIST && errno != EISDIR) {
+			error_f("mkdir(\"%s\"): %s", path, strerror(errno));
+			goto out;
+		}
+	}
+	/* success */
+	ret = 0;
+ out:
+	free(odir);
+	return ret;
+#endif
 }
diff --git a/regress/unittests/misc/test_misc.c b/regress/unittests/misc/test_misc.c
index db0b5bb66..317de9f14 100644
--- a/regress/unittests/misc/test_misc.c
+++ b/regress/unittests/misc/test_misc.c
@@ -462,6 +462,8 @@ test_skip_space(void)
 void
 test_misc(void)
 {
+	mkdir_path("/tmp/foo/bar", 0700);
+	exit(0);
 	test_chop();
 	test_rtrim();
 	test_strprefix();

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list