public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: realpath() patch to fix symlinks resolution for win32
@ 2023-01-16 17:06 i.nixman
  0 siblings, 0 replies; 12+ messages in thread
From: i.nixman @ 2023-01-16 17:06 UTC (permalink / raw)
  To: Gcc Patches

[-- Attachment #1: Type: text/plain, Size: 31 bytes --]


updated patch in attachments.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: lrealpath-resolve-symlinks-on-win32-bug-108350.patch --]
[-- Type: text/x-diff; name=lrealpath-resolve-symlinks-on-win32-bug-108350.patch, Size: 6191 bytes --]

diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c
index 3c7053b0b70..8858619e854 100644
--- a/libiberty/lrealpath.c
+++ b/libiberty/lrealpath.c
@@ -68,8 +68,138 @@ extern char *canonicalize_file_name (const char *);
   /* cygwin has realpath, so it won't get here.  */ 
 # if defined (_WIN32)
 #  define WIN32_LEAN_AND_MEAN
-#  include <windows.h> /* for GetFullPathName */
-# endif
+#  include <windows.h> /* for GetFullPathName/GetFinalPathNameByHandle/
+                          CreateFile/CloseHandle */
+#  define WIN32_REPLACE_SLASHES(_ptr, _len) \
+     for (unsigned i = 0; i != (_len); ++i) \
+       if ((_ptr)[i] == '\\') (_ptr)[i] = '/';
+
+#  define WIN32_UNC_PREFIX "//?/UNC/"
+#  define WIN32_UNC_PREFIX_LEN (sizeof(WIN32_UNC_PREFIX)-1)
+#  define WIN32_IS_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_UNC_PREFIX, WIN32_UNC_PREFIX_LEN))
+
+#  define WIN32_NON_UNC_PREFIX "//?/"
+#  define WIN32_NON_UNC_PREFIX_LEN (sizeof(WIN32_NON_UNC_PREFIX)-1)
+#  define WIN32_IS_NON_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_NON_UNC_PREFIX, WIN32_NON_UNC_PREFIX_LEN))
+
+# define WIN32_IS_SPECIAL_NUL_FILE(ptr) \
+  (0 == strcasecmp(ptr, "NUL"))
+
+/* Get full path name without symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_full_path_name(const char *filename) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+     from the man: `If the lpBuffer buffer is too small to contain
+     the path, the return value is the size, in TCHARs, of the buffer
+     that is required to hold the path _and_the_terminating_null_character_`
+  */
+  len = GetFullPathName(filename, 0, NULL, NULL);
+
+  if ( len == 0 )
+    return strdup(filename);
+
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFullPathName(filename, len, buf, NULL);
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+    ? (WIN32_UNC_PREFIX_LEN - 2)
+    : WIN32_IS_NON_UNC_PREFIX(buf)
+      ? WIN32_NON_UNC_PREFIX_LEN
+      : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+    ptr[0] = '/';
+    ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# if _WIN32_WINNT >= 0x0600
+
+/* Get full path name WITH symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_final_path_name(HANDLE fh) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+     from the  man: `If the function fails because lpszFilePath is too
+     small to hold the string plus the terminating null character,
+     the return value is the required buffer size, in TCHARs. This
+     value _includes_the_size_of_the_terminating_null_character_`.
+     but in my testcase I have path with 26 chars, the function
+     returns 26 also, ie without the trailing zero-char...
+  */
+  len = GetFinalPathNameByHandle(
+     fh
+    ,NULL
+    ,0
+    ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+
+  if ( len == 0 )
+    return NULL;
+
+  len += 1; /* for zero-char */
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFinalPathNameByHandle(
+     fh
+    ,buf
+    ,len
+    ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+    ? (WIN32_UNC_PREFIX_LEN - 2)
+    : WIN32_IS_NON_UNC_PREFIX(buf)
+      ? WIN32_NON_UNC_PREFIX_LEN
+      : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+    ptr[0] = '/';
+    ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# endif // _WIN32_WINNT >= 0x0600
+
+# endif // _WIN32
 #endif
 
 char *
@@ -128,30 +258,51 @@ lrealpath (const char *filename)
   }
 #endif
 
-  /* The MS Windows method.  If we don't have realpath, we assume we
-     don't have symlinks and just canonicalize to a Windows absolute
-     path.  GetFullPath converts ../ and ./ in relative paths to
-     absolute paths, filling in current drive if one is not given
-     or using the current directory of a specified drive (eg, "E:foo").
-     It also converts all forward slashes to back slashes.  */
+  /* The MS Windows method */
 #if defined (_WIN32)
   {
-    char buf[MAX_PATH];
-    char* basename;
-    DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename);
-    if (len == 0 || len > MAX_PATH - 1)
-      return strdup (filename);
-    else
-      {
-	/* The file system is case-preserving but case-insensitive,
-	   Canonicalize to lowercase, using the codepage associated
-	   with the process locale.  */
-        CharLowerBuff (buf, len);
-        return strdup (buf);
+    char *res;
+    /* For Windows Vista and greater */
+#if _WIN32_WINNT >= 0x0600
+
+    /* For some reason the function receives just empty `filename`, but not NULL.
+       What should we do in that case?
+       According to `strdup()` implementation
+         (https://elixir.bootlin.com/glibc/latest/source/string/strdup.c)
+       it will alloc 1 byte even for empty but non NULL string.
+       OK, will use `strdup()` for that case.
+    */
+    if ( 0 == strlen(filename) )
+      return strdup(filename);
+
+    if ( WIN32_IS_SPECIAL_NUL_FILE(filename) ) {
+      res = get_full_path_name(filename);
+    } else {
+      HANDLE fh = CreateFile(
+         filename
+        ,FILE_READ_ATTRIBUTES
+        ,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
+        ,NULL
+        ,OPEN_EXISTING
+        ,FILE_FLAG_BACKUP_SEMANTICS
+        ,NULL
+      );
+
+      if ( fh == INVALID_HANDLE_VALUE ) {
+        res = get_full_path_name(filename);
+      } else {
+        res = get_final_path_name(fh);
+        CloseHandle(fh);
       }
-  }
-#endif
+    }
+
+#else
+    /* For Windows XP */
+    res = get_full_path_name(filename);
 
-  /* This system is a lost cause, just duplicate the filename.  */
-  return strdup (filename);
+#endif // _WIN32_WINNT >= 0x0600
+
+    return res;
+  }
+#endif // _WIN32
 }

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-11 21:14             ` Gerald Pfeifer
@ 2023-02-13 12:03               ` Martin Liška
  0 siblings, 0 replies; 12+ messages in thread
From: Martin Liška @ 2023-02-13 12:03 UTC (permalink / raw)
  To: Gerald Pfeifer, NightStrike; +Cc: Jonathan Yong, i.nixman, GCC Patches

On 2/11/23 22:14, Gerald Pfeifer wrote:
> On Sat, 11 Feb 2023, NightStrike wrote:
>>>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
>> I would have expected the PR to have been automatically updated based on
>> the commit email. Any idea why that didn't happen? Not to change the state
>> to closed, but to add the commit information as a reply.
> 
> I assume the fact that the PR reference was spelt as
>    PR/108350
> without a slash, not a blank, after "PR" may be responsible for the
> missing Bugzilla comment.
> 
> The documented format - per gcc.gnu.org/codingconventions.html - is
>    PR component/12345

It's likely what happens.

> 
> Martin? (By the way, where does one best have a look at those hooks?
> .git/hooks in the main repository isn't it, it appears?)

I know that server hooks (gcc.gnu.org:/home/gccadmin/hooks-bin) do contain:
email-to-bugzilla-filtered:BUGZILLA_CMD = ("/sourceware/infra/bin/email-to-bugzilla", "-G", "gcc")

thus I guess it's /sourceware/infra/bin/email-to-bugzilla what makes the filtering of commits
to bugzilla.

Martin

> 
> Gerald


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-11 18:00           ` NightStrike
@ 2023-02-11 21:14             ` Gerald Pfeifer
  2023-02-13 12:03               ` Martin Liška
  0 siblings, 1 reply; 12+ messages in thread
From: Gerald Pfeifer @ 2023-02-11 21:14 UTC (permalink / raw)
  To: NightStrike, Martin Liska; +Cc: Jonathan Yong, i.nixman, GCC Patches

On Sat, 11 Feb 2023, NightStrike wrote:
>>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
> I would have expected the PR to have been automatically updated based on
> the commit email. Any idea why that didn't happen? Not to change the state
> to closed, but to add the commit information as a reply.

I assume the fact that the PR reference was spelt as
  PR/108350
without a slash, not a blank, after "PR" may be responsible for the 
missing Bugzilla comment.

The documented format - per gcc.gnu.org/codingconventions.html - is
  PR component/12345

Martin? (By the way, where does one best have a look at those hooks?
.git/hooks in the main repository isn't it, it appears?)

Gerald

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-11  8:52         ` Gerald Pfeifer
  2023-02-11 13:24           ` Jonathan Yong
@ 2023-02-11 18:00           ` NightStrike
  2023-02-11 21:14             ` Gerald Pfeifer
  1 sibling, 1 reply; 12+ messages in thread
From: NightStrike @ 2023-02-11 18:00 UTC (permalink / raw)
  To: Gerald Pfeifer; +Cc: Jonathan Yong, i.nixman, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 558 bytes --]

On Sat, Feb 11, 2023 at 3:52 AM Gerald Pfeifer <gerald@pfeifer.com> wrote:
>
> On Sat, 11 Feb 2023, Jonathan Yong via Gcc-patches wrote:
> >> could you please close the corresponding BR too?:
> >> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
> > I can't close it, but I put a note that it has been committed.
>
> I closed the report.
>
> Gerald

I would have expected the PR to have been automatically updated based on
the commit email. Any idea why that didn't happen? Not to change the state
to closed, but to add the commit information as a reply.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-11  8:52         ` Gerald Pfeifer
@ 2023-02-11 13:24           ` Jonathan Yong
  2023-02-11 18:00           ` NightStrike
  1 sibling, 0 replies; 12+ messages in thread
From: Jonathan Yong @ 2023-02-11 13:24 UTC (permalink / raw)
  To: Gerald Pfeifer; +Cc: i.nixman, gcc-patches

On 2/11/23 08:52, Gerald Pfeifer wrote:
> On Sat, 11 Feb 2023, Jonathan Yong via Gcc-patches wrote:
>>> could you please close the corresponding BR too?:
>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
>> I can't close it, but I put a note that it has been committed.
> 
> I closed the report.
> 
> Gerald

Thanks.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-11  8:36       ` Jonathan Yong
@ 2023-02-11  8:52         ` Gerald Pfeifer
  2023-02-11 13:24           ` Jonathan Yong
  2023-02-11 18:00           ` NightStrike
  0 siblings, 2 replies; 12+ messages in thread
From: Gerald Pfeifer @ 2023-02-11  8:52 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: i.nixman, gcc-patches

On Sat, 11 Feb 2023, Jonathan Yong via Gcc-patches wrote:
>> could you please close the corresponding BR too?:
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
> I can't close it, but I put a note that it has been committed.

I closed the report.

Gerald

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-11  7:28     ` i.nixman
@ 2023-02-11  8:36       ` Jonathan Yong
  2023-02-11  8:52         ` Gerald Pfeifer
  0 siblings, 1 reply; 12+ messages in thread
From: Jonathan Yong @ 2023-02-11  8:36 UTC (permalink / raw)
  To: i.nixman; +Cc: gcc-patches

On 2/11/23 07:28, i.nixman@autistici.org wrote:
> 
> Thank you Jonathan!
> 
> could you please close the corresponding BR too?:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
> 
> 
> 
> best!

I can't close it, but I put a note that it has been committed.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-11  6:32   ` Jonathan Yong
@ 2023-02-11  7:28     ` i.nixman
  2023-02-11  8:36       ` Jonathan Yong
  0 siblings, 1 reply; 12+ messages in thread
From: i.nixman @ 2023-02-11  7:28 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: gcc-patches, niXman

On 2023-02-11 06:32, Jonathan Yong wrote:
> On 2/6/23 06:40, Jonathan Yong wrote:
>> On 1/18/23 10:44, i.nixman--- via Gcc-patches wrote:
>>> hello again!
>>> 
>>> the final version of the path for 
>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
>>> 
>>> successfully bootstraped for x86_64-mingw32 and x86_64-linux.
>>> 
>>> could anyone apply it please?
>>> 
>>> 
>>> 
>>> best!
>> 
>> Looks good to me, please supply the appropriate changelog.
> 
> Pushed to master.


Thank you Jonathan!

could you please close the corresponding BR too?:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350



best!

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-02-06  6:40 ` Jonathan Yong
@ 2023-02-11  6:32   ` Jonathan Yong
  2023-02-11  7:28     ` i.nixman
  0 siblings, 1 reply; 12+ messages in thread
From: Jonathan Yong @ 2023-02-11  6:32 UTC (permalink / raw)
  To: gcc-patches, niXman

On 2/6/23 06:40, Jonathan Yong wrote:
> On 1/18/23 10:44, i.nixman--- via Gcc-patches wrote:
>> hello again!
>>
>> the final version of the path for 
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
>>
>> successfully bootstraped for x86_64-mingw32 and x86_64-linux.
>>
>> could anyone apply it please?
>>
>>
>>
>> best!
> 
> Looks good to me, please supply the appropriate changelog.

Pushed to master.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
  2023-01-18 10:44 i.nixman
@ 2023-02-06  6:40 ` Jonathan Yong
  2023-02-11  6:32   ` Jonathan Yong
  0 siblings, 1 reply; 12+ messages in thread
From: Jonathan Yong @ 2023-02-06  6:40 UTC (permalink / raw)
  To: gcc-patches

On 1/18/23 10:44, i.nixman--- via Gcc-patches wrote:
> hello again!
> 
> the final version of the path for 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350
> 
> successfully bootstraped for x86_64-mingw32 and x86_64-linux.
> 
> could anyone apply it please?
> 
> 
> 
> best!

Looks good to me, please supply the appropriate changelog.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: realpath() patch to fix symlinks resolution for win32
@ 2023-01-26 17:51 i.nixman
  0 siblings, 0 replies; 12+ messages in thread
From: i.nixman @ 2023-01-26 17:51 UTC (permalink / raw)
  To: Gcc Patches


hello,

could someone look at patch attached please?

https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610147.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* realpath() patch to fix symlinks resolution for win32
@ 2023-01-18 10:44 i.nixman
  2023-02-06  6:40 ` Jonathan Yong
  0 siblings, 1 reply; 12+ messages in thread
From: i.nixman @ 2023-01-18 10:44 UTC (permalink / raw)
  To: Gcc Patches

[-- Attachment #1: Type: text/plain, Size: 204 bytes --]

hello again!

the final version of the path for 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350

successfully bootstraped for x86_64-mingw32 and x86_64-linux.

could anyone apply it please?



best!

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: lrealpath-resolve-symlinks-on-win32-bug-108350.patch --]
[-- Type: text/x-diff; name=lrealpath-resolve-symlinks-on-win32-bug-108350.patch, Size: 6048 bytes --]

diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c
index 3c7053b0b70..a1ad074d00e 100644
--- a/libiberty/lrealpath.c
+++ b/libiberty/lrealpath.c
@@ -68,8 +68,135 @@ extern char *canonicalize_file_name (const char *);
   /* cygwin has realpath, so it won't get here.  */ 
 # if defined (_WIN32)
 #  define WIN32_LEAN_AND_MEAN
-#  include <windows.h> /* for GetFullPathName */
-# endif
+#  include <windows.h> /* for GetFullPathName/GetFinalPathNameByHandle/
+                          CreateFile/CloseHandle */
+#  define WIN32_REPLACE_SLASHES(_ptr, _len) \
+     for (unsigned i = 0; i != (_len); ++i) \
+       if ((_ptr)[i] == '\\') (_ptr)[i] = '/';
+
+#  define WIN32_UNC_PREFIX "//?/UNC/"
+#  define WIN32_UNC_PREFIX_LEN (sizeof(WIN32_UNC_PREFIX)-1)
+#  define WIN32_IS_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_UNC_PREFIX, WIN32_UNC_PREFIX_LEN))
+
+#  define WIN32_NON_UNC_PREFIX "//?/"
+#  define WIN32_NON_UNC_PREFIX_LEN (sizeof(WIN32_NON_UNC_PREFIX)-1)
+#  define WIN32_IS_NON_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_NON_UNC_PREFIX, WIN32_NON_UNC_PREFIX_LEN))
+
+/* Get full path name without symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_full_path_name(const char *filename) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+     from the man: `If the lpBuffer buffer is too small to contain
+     the path, the return value is the size, in TCHARs, of the buffer
+     that is required to hold the path _and_the_terminating_null_character_`
+  */
+  len = GetFullPathName(filename, 0, NULL, NULL);
+
+  if ( len == 0 )
+    return strdup(filename);
+
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFullPathName(filename, len, buf, NULL);
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+    ? (WIN32_UNC_PREFIX_LEN - 2)
+    : WIN32_IS_NON_UNC_PREFIX(buf)
+      ? WIN32_NON_UNC_PREFIX_LEN
+      : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+    ptr[0] = '/';
+    ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# if _WIN32_WINNT >= 0x0600
+
+/* Get full path name WITH symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_final_path_name(HANDLE fh) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+     from the  man: `If the function fails because lpszFilePath is too
+     small to hold the string plus the terminating null character,
+     the return value is the required buffer size, in TCHARs. This
+     value _includes_the_size_of_the_terminating_null_character_`.
+     but in my testcase I have path with 26 chars, the function
+     returns 26 also, ie without the trailing zero-char...
+  */
+  len = GetFinalPathNameByHandle(
+     fh
+    ,NULL
+    ,0
+    ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+
+  if ( len == 0 )
+    return NULL;
+
+  len += 1; /* for zero-char */
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFinalPathNameByHandle(
+     fh
+    ,buf
+    ,len
+    ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+    ? (WIN32_UNC_PREFIX_LEN - 2)
+    : WIN32_IS_NON_UNC_PREFIX(buf)
+      ? WIN32_NON_UNC_PREFIX_LEN
+      : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+    ptr[0] = '/';
+    ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# endif // _WIN32_WINNT >= 0x0600
+
+# endif // _WIN32
 #endif
 
 char *
@@ -128,30 +255,52 @@ lrealpath (const char *filename)
   }
 #endif
 
-  /* The MS Windows method.  If we don't have realpath, we assume we
-     don't have symlinks and just canonicalize to a Windows absolute
-     path.  GetFullPath converts ../ and ./ in relative paths to
-     absolute paths, filling in current drive if one is not given
-     or using the current directory of a specified drive (eg, "E:foo").
-     It also converts all forward slashes to back slashes.  */
+  /* The MS Windows method */
 #if defined (_WIN32)
   {
-    char buf[MAX_PATH];
-    char* basename;
-    DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename);
-    if (len == 0 || len > MAX_PATH - 1)
-      return strdup (filename);
-    else
-      {
-	/* The file system is case-preserving but case-insensitive,
-	   Canonicalize to lowercase, using the codepage associated
-	   with the process locale.  */
-        CharLowerBuff (buf, len);
-        return strdup (buf);
-      }
-  }
-#endif
+    char *res;
+
+    /* For Windows Vista and greater */
+#if _WIN32_WINNT >= 0x0600
+
+    /* For some reason the function receives just empty `filename`, but not NULL.
+       What should we do in that case?
+       According to `strdup()` implementation
+         (https://elixir.bootlin.com/glibc/latest/source/string/strdup.c)
+       it will alloc 1 byte even for empty but non NULL string.
+       OK, will use `strdup()` for that case.
+    */
+    if ( 0 == strlen(filename) )
+      return strdup(filename);
+
+    HANDLE fh = CreateFile(
+       filename
+      ,FILE_READ_ATTRIBUTES
+      ,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
+      ,NULL
+      ,OPEN_EXISTING
+      ,FILE_FLAG_BACKUP_SEMANTICS
+      ,NULL
+    );
+
+    if ( fh == INVALID_HANDLE_VALUE ) {
+      res = get_full_path_name(filename);
+    } else {
+      res = get_final_path_name(fh);
+      CloseHandle(fh);
 
-  /* This system is a lost cause, just duplicate the filename.  */
-  return strdup (filename);
+      if ( !res )
+        res = get_full_path_name(filename);
+    }
+
+#else
+
+    /* For Windows XP */
+    res = get_full_path_name(filename);
+
+#endif // _WIN32_WINNT >= 0x0600
+
+    return res;
+  }
+#endif // _WIN32
 }

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-02-13 12:03 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-16 17:06 realpath() patch to fix symlinks resolution for win32 i.nixman
2023-01-18 10:44 i.nixman
2023-02-06  6:40 ` Jonathan Yong
2023-02-11  6:32   ` Jonathan Yong
2023-02-11  7:28     ` i.nixman
2023-02-11  8:36       ` Jonathan Yong
2023-02-11  8:52         ` Gerald Pfeifer
2023-02-11 13:24           ` Jonathan Yong
2023-02-11 18:00           ` NightStrike
2023-02-11 21:14             ` Gerald Pfeifer
2023-02-13 12:03               ` Martin Liška
2023-01-26 17:51 i.nixman

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).