This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Win32: try to make the new stat pre-Vista compatible
authorTony Cook <tony@develop-help.com>
Tue, 20 Oct 2020 05:12:09 +0000 (16:12 +1100)
committerTony Cook <tony@develop-help.com>
Tue, 1 Dec 2020 04:29:33 +0000 (15:29 +1100)
Skips the win32\stat.t execute flag test for handles pre-Vista

This is intended mostly for allowing the Win2000 smoker to build and
test.  If we end up dropping pre-Vista support this commit can be
removed (or reverted if it ends up in blead)

t/win32/stat.t
win32/win32.c

index 09f52ad..b2dccb8 100644 (file)
@@ -12,6 +12,10 @@ use Fcntl ":seek";
 Win32::FsType() eq 'NTFS'
     or skip_all("need NTFS");
 
+my (undef, $maj, $min) = Win32::GetOSVersion();
+
+my $vista_or_later = $maj >= 6;
+
 my $tmpfile1 = tempfile();
 
 # test some of the win32 specific stat code, since we
@@ -71,7 +75,11 @@ unlink($tmpfile1); # no more hard link
 
 if (open my $fh, ">", "$tmpfile1.bat") {
     ok(-x "$tmpfile1.bat", 'batch file is "executable"');
-    ok(-x $fh, 'batch file handle is "executable"');
+    SKIP: {
+        skip "executable bit for handles needs vista or later", 1
+            unless $vista_or_later;
+        ok(-x $fh, 'batch file handle is "executable"');
+    }
     close $fh;
     unlink "$tmpfile1.bat";
 }
index f18223d..7ea15e4 100644 (file)
@@ -1494,6 +1494,8 @@ translate_ft_to_time_t(FILETIME ft) {
     return mktime(&pt);
 }
 
+typedef DWORD (__stdcall *pGetFinalPathNameByHandleA_t)(HANDLE, LPSTR, DWORD, DWORD);
+
 static int
 win32_stat_low(HANDLE handle, const char *path, STRLEN len, Stat_t *sbuf) {
     DWORD type = GetFileType(handle);
@@ -1536,7 +1538,15 @@ win32_stat_low(HANDLE handle, const char *path, STRLEN len, Stat_t *sbuf) {
                 sbuf->st_mode = _S_IFREG;
 
                 if (!path) {
-                    len = GetFinalPathNameByHandleA(handle, path_buf, sizeof(path_buf), 0);
+                    pGetFinalPathNameByHandleA_t pGetFinalPathNameByHandleA =
+                        (pGetFinalPathNameByHandleA_t)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetFinalPathNameByHandleA");
+                    if (pGetFinalPathNameByHandleA) {
+                        len = pGetFinalPathNameByHandleA(handle, path_buf, sizeof(path_buf), 0);
+                    }
+                    else {
+                        len = 0;
+                    }
+
                     /* < to ensure there's space for the \0 */
                     if (len && len < sizeof(path_buf)) {
                         path = path_buf;
@@ -1695,6 +1705,10 @@ typedef struct {
   } Data;
 } MY_REPARSE_DATA_BUFFER, *PMY_REPARSE_DATA_BUFFER;
 
+#ifndef IO_REPARSE_TAG_SYMLINK
+#  define IO_REPARSE_TAG_SYMLINK                  (0xA000000CL)
+#endif
+
 static BOOL
 is_symlink(HANDLE h) {
     MY_REPARSE_DATA_BUFFER linkdata;