public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] Add support for Windows network paths to the UNC support in _bfd_real_open().
@ 2024-04-05  8:43 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2024-04-05  8:43 UTC (permalink / raw)
  To: binutils-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=eac88f3298491fdf2caa0d7dd97a3dde954b8b74

commit eac88f3298491fdf2caa0d7dd97a3dde954b8b74
Author: Zhiqing Xiong <zhiqxion@qti.qualcomm.com>
Date:   Fri Apr 5 09:41:40 2024 +0100

    Add support for Windows network paths to the UNC support in _bfd_real_open().
    
    PR 31527

Diff:
---
 bfd/bfdio.c | 108 ++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 72 insertions(+), 36 deletions(-)

diff --git a/bfd/bfdio.c b/bfd/bfdio.c
index 4ed0eeadc52..718cbe89023 100644
--- a/bfd/bfdio.c
+++ b/bfd/bfdio.c
@@ -29,6 +29,8 @@
 #if defined (_WIN32)
 #include <windows.h>
 #include <locale.h>
+/* FIXME: Do we need a configure time test for the presence of this headers ?  */
+#include <shlwapi.h>  /* Needed for PathIsNetworkPathA().  */
 #endif
 
 #ifndef S_IXUSR
@@ -118,61 +120,95 @@ _bfd_real_fopen (const char *filename, const char *modes)
 
 #elif defined (_WIN32)
   /* PR 25713: Handle extra long path names possibly containing '..' and '.'.  */
-   wchar_t **     lpFilePart = {NULL};
-   const wchar_t  prefix[] = L"\\\\?\\";
-   const size_t   partPathLen = strlen (filename) + 1;
+  wchar_t **      lpFilePart = {NULL};
+  const wchar_t   prefixDOS[] = L"\\\\?\\";
+  const wchar_t   prefixUNC[] = L"\\\\?\\UNC\\";
+  const size_t    partPathLen = strlen (filename) + 1;
+  const wchar_t * prefix;
+  size_t          sizeof_prefix;
+
+  /* PR 31527: Paths that begin with two backslash characters
+     (\\) are interpreted as Universal Naming Convention (UNC)
+     paths.  They use the "\\?\UNC\" prefix for network UNC paths
+     and  the "\\?\" prefix for dos UNC paths.  For more information
+     see: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry
+  */
+  bool is_network_path = PathIsNetworkPathA (filename);
+
+  if (is_network_path)
+    {
+      prefix = prefixUNC;
+      sizeof_prefix = sizeof (prefixUNC);
+    }
+  else
+    {
+      prefix = prefixDOS;
+      sizeof_prefix = sizeof (prefixDOS);
+    }
+
 #ifdef __MINGW32__
 #if !HAVE_DECL____LC_CODEPAGE_FUNC
-/* This prototype was added to locale.h in version 9.0 of MinGW-w64.  */
-   _CRTIMP unsigned int __cdecl ___lc_codepage_func (void);
+  /* This prototype was added to locale.h in version 9.0 of MinGW-w64.  */
+  _CRTIMP unsigned int __cdecl ___lc_codepage_func (void);
 #endif
-   const unsigned int cp = ___lc_codepage_func ();
+  const unsigned int cp = ___lc_codepage_func ();
 #else
-   const unsigned int cp = CP_UTF8;
+  const unsigned int cp = CP_UTF8;
 #endif
 
-   /* Converting the partial path from ascii to unicode.
-      1) Get the length: Calling with lpWideCharStr set to null returns the length.
-      2) Convert the string: Calling with cbMultiByte set to -1 includes the terminating null.  */
-   size_t         partPathWSize = MultiByteToWideChar (cp, 0, filename, -1, NULL, 0);
-   wchar_t *      partPath = calloc (partPathWSize, sizeof(wchar_t));
-   size_t         ix;
+  /* Converting the partial path from ascii to unicode.
+     1) Get the length: Calling with lpWideCharStr set to null returns the length.
+     2) Convert the string: Calling with cbMultiByte set to -1 includes the terminating null.  */
+  size_t     partPathWSize = MultiByteToWideChar (cp, 0, filename, -1, NULL, 0);
+  wchar_t *  partPath = calloc (partPathWSize, sizeof(wchar_t));
+  size_t     ix;
 
-   MultiByteToWideChar (cp, 0, filename, -1, partPath, partPathWSize);
+  MultiByteToWideChar (cp, 0, filename, -1, partPath, partPathWSize);
 
-   /* Convert any UNIX style path separators into the DOS i.e. backslash separator.  */
-   for (ix = 0; ix < partPathLen; ix++)
-     if (IS_UNIX_DIR_SEPARATOR(filename[ix]))
-       partPath[ix] = '\\';
+  /* Convert any UNIX style path separators into the DOS i.e. backslash separator.  */
+  for (ix = 0; ix < partPathLen; ix++)
+    if (IS_UNIX_DIR_SEPARATOR(filename[ix]))
+      partPath[ix] = '\\';
 
-   /* Getting the full path from the provided partial path.
-      1) Get the length.
-      2) Resolve the path.  */
-   long       fullPathWSize = GetFullPathNameW (partPath, 0, NULL, lpFilePart);
-   wchar_t *  fullPath = calloc (fullPathWSize + sizeof(prefix) + 1, sizeof(wchar_t));
+  /* Getting the full path from the provided partial path.
+     1) Get the length.
+     2) Resolve the path.  */
+  long       fullPathWSize = GetFullPathNameW (partPath, 0, NULL, lpFilePart);
+  wchar_t *  fullPath = calloc (fullPathWSize + sizeof_prefix + 1, sizeof(wchar_t));
 
-   wcscpy (fullPath, prefix);
+  wcscpy (fullPath, prefix);
 
-   int        prefixLen = sizeof(prefix) / sizeof(wchar_t);
+  int  prefixLen = sizeof_prefix / sizeof(wchar_t);
 
-   /* Do not add a prefix to the null device.  */
-   if (stricmp (filename, "nul") == 0)
+  /* Do not add a prefix to the null device.  */
+  if (stricmp (filename, "nul") == 0)
     prefixLen = 1;
 
-   wchar_t *  fullPathOffset = fullPath + prefixLen - 1;
+  wchar_t *  fullPathOffset = fullPath + prefixLen - 1;
+
+  GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart);
+
+  if (is_network_path)
+    {
+      /* Remove begining of the beginning two backslash characters (\\).  */
+      wchar_t *_fullPath = calloc (fullPathWSize + sizeof_prefix + 1, sizeof(wchar_t));
+
+      GetFullPathNameW (fullPath, fullPathWSize + sizeof_prefix + 1, _fullPath, lpFilePart);
+      free (fullPath);
+      fullPath = _fullPath;
+    }
 
-   GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart);
-   free (partPath);
+  free (partPath);
 
-   /* It is non-standard for modes to exceed 16 characters.  */
-   wchar_t    modesW[16];
+  /* It is non-standard for modes to exceed 16 characters.  */
+  wchar_t  modesW[16];
 
-   MultiByteToWideChar (cp, 0, modes, -1, modesW, sizeof(modesW));
+  MultiByteToWideChar (cp, 0, modes, -1, modesW, sizeof(modesW));
 
-   FILE *     file = _wfopen (fullPath, modesW);
-   free (fullPath);
+  FILE *  file = _wfopen (fullPath, modesW);
+  free (fullPath);
 
-   return close_on_exec (file);
+  return close_on_exec (file);
 
 #elif defined (HAVE_FOPEN64)
   return close_on_exec (fopen64 (filename, modes));

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-04-05  8:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-05  8:43 [binutils-gdb] Add support for Windows network paths to the UNC support in _bfd_real_open() Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).