From 45fb1d952c3b262278a3b22e9c7d60cca19a5407 Mon Sep 17 00:00:00 2001
From: Tavian Barnes <tavianator@tavianator.com>
Date: Wed, 3 Jan 2024 17:17:35 -0500
Subject: Work around DragonFly BSD kernel bug

DragonFly's x86_64 assembly implementation of copyinstr() checks the
wrong pointer when deciding whether to return EFAULT or ENAMETOOLONG,
causing it to always return EFAULT for overlong paths.  Work around it
by treating EFAULT the same as ENAMETOOLONG on DragonFly.

Link: https://twitter.com/tavianator/status/1742991411203485713
---
 src/bftw.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/bftw.c b/src/bftw.c
index 0b74cd9..355cb54 100644
--- a/src/bftw.c
+++ b/src/bftw.c
@@ -739,10 +739,22 @@ static int bftw_file_open(struct bftw_state *state, struct bftw_file *file, cons
 	}
 
 	int fd = bftw_file_openat(state, file, base, at_path);
-	if (fd >= 0 || errno != ENAMETOOLONG) {
+	if (fd >= 0) {
 		return fd;
 	}
 
+	switch (errno) {
+	case ENAMETOOLONG:
+#if __DragonFly__
+	// https://twitter.com/tavianator/status/1742991411203485713
+	case EFAULT:
+#endif
+		break;
+
+	default:
+		return -1;
+	}
+
 	// Handle ENAMETOOLONG by manually traversing the path component-by-component
 	struct bftw_list parents;
 	SLIST_INIT(&parents);
-- 
cgit v1.2.3