[PATCH v3] Cygwin: respect PC_SYM_FOLLOW and PC_SYM_NOFOLLOW_REP with inner links

Jeremy Drake cygwin@jdrake.com
Thu Jun 3 20:29:32 GMT 2021


Just updated for formatting.

> Formatting should try to stick to 80 chars max line length, if possible.
> Kind of like this, just with TABs:
>
> -	  for (unsigned pc_flags = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE);
> +	  for (unsigned pc_flags = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE
> 					  | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP);
>
-------------- next part --------------
From 4bb959b57606465d5a7abe7d3ae168db66f5f6fa Mon Sep 17 00:00:00 2001
From: Jeremy Drake <cygwin@jdrake.com>
Date: Sat, 29 May 2021 13:17:08 -0700
Subject: [PATCH 1/2] Revert "Cygwin: Handle virtual drives as non-symlinks"

This reverts commit c8949d04001e3dbc03651475b6cd1c5623400835.
---
 winsup/cygwin/path.cc | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 6a07f0d06..e62f8fe2b 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -3505,9 +3505,14 @@ restart:
 
 		     subst X: C:\foo\bar
 
-		   Treat it as a normal file. */
+		   Treat it like a symlink.  This is required to tell an
+		   lstat caller that the "drive" is actually pointing
+		   somewhere else, thus, it's a symlink in POSIX speak. */
 		if (upath.Length == 14)	/* \??\X:\ */
-		  goto file_not_symlink;
+		  {
+		    fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
+		    path_flags |= PATH_SYMLINK;
+		  }
 		/* For final paths differing in inner path components return
 		   length as negative value.  This informs path_conv::check
 		   to skip realpath handling on the last path component. */
-- 
2.31.1.windows.1

-------------- next part --------------
From ea36ccb13b2080663535d867e6fe8edf246efe83 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <github@jdrake.com>
Date: Sat, 29 May 2021 11:48:11 -0700
Subject: [PATCH 2/2] Cygwin: respect PC_SYM_FOLLOW and PC_SYM_NOFOLLOW_REP
 with inner links.

The new GetFinalPathNameW handling for native symlinks in inner path
components is disabled if caller doesn't want to follow symlinks, or
doesn't want to follow reparse points.  Set flag to not follow reparse
points in chdir, allowing native processes to see their cwd potentially
including native symlinks, rather than dereferencing them.
---
 winsup/cygwin/path.cc | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index e62f8fe2b..a6bb3aeff 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -722,9 +722,10 @@ path_conv::check (const char *src, unsigned opt,
 	  int symlen = 0;
 
 	  /* Make sure to check certain flags on last component only. */
-	  for (unsigned pc_flags = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE);
+	  for (unsigned pc_flags = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE
+					 | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP);
 	       ;
-	       pc_flags = 0)
+	       pc_flags = opt & (PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP))
 	    {
 	      const suffix_info *suff;
 	      char *full_path;
@@ -3452,6 +3453,8 @@ restart:
 	    break;
 	}
 
+      if ((pc_flags & (PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP)) == PC_SYM_FOLLOW)
+      {
       /* Check if the inner path components contain native symlinks or
 	 junctions, or if the drive is a virtual drive.  Compare incoming
 	 path with path returned by GetFinalPathNameByHandleA.  If they
@@ -3522,6 +3525,7 @@ restart:
 	      }
 	  }
       }
+      }
 
     /* Normal file. */
     file_not_symlink:
@@ -3704,7 +3708,8 @@ chdir (const char *in_dir)
 
       /* Convert path.  PC_NONULLEMPTY ensures that we don't check for
 	 NULL/empty/invalid again. */
-      path_conv path (in_dir, PC_SYM_FOLLOW | PC_POSIX | PC_NONULLEMPTY);
+      path_conv path (in_dir, PC_SYM_FOLLOW | PC_POSIX | PC_NONULLEMPTY
+			      | PC_SYM_NOFOLLOW_REP);
       if (path.error)
 	{
 	  set_errno (path.error);
-- 
2.31.1.windows.1



More information about the Cygwin-patches mailing list