Subject: bug#36405: closed (Re: 26.2.90; O_PATH problem on some versions of Cygwin)

From: [email-masked] (GNU bug Tracking System)
Date: Thu, 27 Jun 2019 20:48:03 +0000

Your bug report

#36405: 26.2.90; O_PATH problem on some versions of Cygwin

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
36405: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=36405
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: 26.2.90; O_PATH problem on some versions of Cygwin
From: Paul Eggert <[email-masked]>
To: Ken Brown <[email-masked]>
Cc: [email-masked]
Date: Thu, 27 Jun 2019 13:47:27 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Thanks, but that patch intrudes on the mainline code a bit. It's simpler 
to just disable O_PATH on Cygwin until the old Cygwin versions die out. 
Also, there's a similar issue in fileio.c. I installed the attached, 
which should work around the problem in both source files.
>From e7200b3cf9b4a6470197915a31c45739f078683b Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Thu, 27 Jun 2019 13:05:05 -0700
Subject: [PATCH] Work around Cygwin bug with O_PATH

Problem reported by Ken Brown (Bug#36405).
* src/dired.c, src/fileio.c (O_PATH) [__CYGWIN__]: Undef.
---
 src/dired.c  | 4 ++++
 src/fileio.c | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/src/dired.c b/src/dired.c
index 493758292b..b8197d36a0 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -41,6 +41,10 @@
 #include "buffer.h"
 #include "coding.h"
 
+#ifdef __CYGWIN__
+# undef O_PATH /* Buggy in Cygwin 3.0.0 through 3.0.7.  */
+#endif
+
 #ifdef MSDOS
 #include "msdos.h"	/* for fstatat */
 #endif
diff --git a/src/fileio.c b/src/fileio.c
index ed1d2aedf3..e36118652c 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -61,6 +61,10 @@ Copyright (C) 1985-1988, 1993-2019 Free Software Foundation, Inc.
 # include <linux/fs.h>
 #endif
 
+#ifdef __CYGWIN__
+# undef O_PATH /* Buggy in Cygwin 3.0.0 through 3.0.7.  */
+#endif
+
 #ifdef WINDOWSNT
 #define NOMINMAX 1
 #include <windows.h>
-- 
2.21.0

Subject: 26.2.90; O_PATH problem on some versions of Cygwin
From: Ken Brown <[email-masked]>
To: "[email-masked]" <[email-masked]>
Date: Thu, 27 Jun 2019 19:28:48 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

Cygwin supports the O_PATH flag starting with release 3.0.0, but it is buggy 
until release 3.0.8.  (Opening a FIFO with O_PATH causes a hang.)  The attached 
patches work around this problem.  The first patch (which still has a bug number 
that needs to be filled in) uses incorrect indentation for legibility.  The 
second patch fixes the indentation.

Ken
From 8a350e90dc8d047e8372a53dd64fc178157b3f52 Mon Sep 17 00:00:00 2001
From: Ken Brown <[email-masked]>
Date: Thu, 27 Jun 2019 14:54:09 -0400
Subject: [PATCH 1/2] Avoid O_PATH on versions of Cygwin where it is buggy

* src/dired.c [O_PATH] (use_o_path): New function.
(file_attributes): Use it.  (Bug#99999)
---
 src/dired.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/dired.c b/src/dired.c
index 493758292b..ac83a026de 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -36,6 +36,10 @@
 #include <filemode.h>
 #include <stat-time.h>
 
+#if defined CYGWIN && defined O_PATH
+#include <sys/utsname.h>
+#endif
+
 #include "lisp.h"
 #include "systime.h"
 #include "buffer.h"
@@ -921,6 +925,21 @@ DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0,
 			  id_format);
 }
 
+/* Cygwin supports O_PATH starting with release 3.0.0, but it is buggy
+   until release 3.0.8.  */
+#ifdef O_PATH
+static bool
+use_o_path (void)
+{
+# ifdef CYGWIN
+  struct utsname name;
+  return uname (&name) >= 0 && strverscmp (name.release, "3.0.8") >= 0;
+# else
+  return true;
+# endif
+}
+#endif
+
 static Lisp_Object
 file_attributes (int fd, char const *name,
 		 Lisp_Object dirname, Lisp_Object filename,
@@ -938,6 +957,8 @@ file_attributes (int fd, char const *name,
   int err = EINVAL;
 
 #ifdef O_PATH
+ if (use_o_path ())
+ {
   int namefd = openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW);
   if (namefd < 0)
     err = errno;
@@ -960,6 +981,7 @@ file_attributes (int fd, char const *name,
 	  name = "";
 	}
     }
+ }
 #endif
 
   if (err == EINVAL)
-- 
2.21.0

From cd7bbc1e088033789b2948578fc85099ed11a2f1 Mon Sep 17 00:00:00 2001
From: Ken Brown <[email-masked]>
Date: Thu, 27 Jun 2019 15:04:05 -0400
Subject: [PATCH 2/2] ; * src/dired.c (file_attributes): Fix indentation

---
 src/dired.c | 48 ++++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/src/dired.c b/src/dired.c
index ac83a026de..dfec2d89d8 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -958,30 +958,30 @@ file_attributes (int fd, char const *name,
 
 #ifdef O_PATH
  if (use_o_path ())
- {
-  int namefd = openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW);
-  if (namefd < 0)
-    err = errno;
-  else
-    {
-      record_unwind_protect_int (close_file_unwind, namefd);
-      if (fstat (namefd, &s) != 0)
-	{
-	  err = errno;
-	  /* The Linux kernel before version 3.6 does not support
-	     fstat on O_PATH file descriptors.  Handle this error like
-	     missing support for O_PATH.  */
-	  if (err == EBADF)
-	    err = EINVAL;
-	}
-      else
-	{
-	  err = 0;
-	  fd = namefd;
-	  name = "";
-	}
-    }
- }
+   {
+     int namefd = openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW);
+     if (namefd < 0)
+       err = errno;
+     else
+       {
+	 record_unwind_protect_int (close_file_unwind, namefd);
+	 if (fstat (namefd, &s) != 0)
+	   {
+	     err = errno;
+	     /* The Linux kernel before version 3.6 does not support
+		fstat on O_PATH file descriptors.  Handle this error like
+		missing support for O_PATH.  */
+	     if (err == EBADF)
+	       err = EINVAL;
+	   }
+	 else
+	   {
+	     err = 0;
+	     fd = namefd;
+	     name = "";
+	   }
+       }
+   }
 #endif
 
   if (err == EINVAL)
-- 
2.21.0