Windows: Update tarballs to GCC 9.2 and remove MAX_PATH limit.
authorTamar Christina <tamar@zhox.com>
Sun, 8 Sep 2019 22:11:19 +0000 (23:11 +0100)
committerTamar Christina <tamar@zhox.com>
Sun, 20 Oct 2019 15:21:10 +0000 (16:21 +0100)
26 files changed:
compiler/cbits/genSym.c
configure.ac
docs/users_guide/8.10.1-notes.rst
includes/Rts.h
includes/stg/Types.h
libraries/base/cbits/inputReady.c
mk/get-win32-tarballs.sh
mk/win32-tarballs.md5sum
rts/RtsSymbols.c
rts/RtsSymbols.h
rts/linker/PEi386.c
rts/linker/PEi386.h
rts/linker/elf_plt.h
rts/linker/elf_reloc_aarch64.c
rts/linker/elf_reloc_aarch64.h
rts/win32/OSMem.c
rts/win32/OSThreads.c
testsuite/tests/ffi/should_run/T5594_c.c
testsuite/tests/ffi/should_run/ffi002_c.c
testsuite/tests/ffi/should_run/fptr01_c.c
testsuite/tests/ffi/should_run/fptrfail01_c.c
testsuite/tests/rts/linker/linker_error.c
testsuite/tests/rts/linker/linker_unload.c
utils/fs/fs.c
utils/fs/fs.h
utils/ghc-cabal/Main.hs

index 769c093..ecb318d 100644 (file)
@@ -1,5 +1,5 @@
-#include <assert.h>
 #include <Rts.h>
+#include <assert.h>
 #include "Unique.h"
 
 static HsInt GenSymCounter = 0;
index 6fddd04..f1c9269 100644 (file)
@@ -329,7 +329,7 @@ then
     if test "$HostArch" = "i386"
     then
         mingw_arch="i686"
-        tarball_dest_dir="mingw-w64/x86"
+        tarball_dest_dir="mingw-w64/i686"
         tarball_mingw_dir="mingw32"
     else
         mingw_arch="x86_64"
index 0d7be2e..eb06b02 100644 (file)
@@ -173,6 +173,10 @@ Compiler
   implemented correctly, and appears to be largely unused. This flag
   will be removed in a later version of GHC.
 
+- Windows bindist has been updated to GCC 9.2 and binutils 2.32.  These binaries have
+  been patched to no longer have have the MAX_PATH limit.  Windows users should no longer
+  have any issues with long path names.
+
 GHCi
 ~~~~
 
index dd60726..256a3e5 100644 (file)
 extern "C" {
 #endif
 
+/* get types from GHC's runtime system */
+#include "ghcconfig.h"
+/* We have to include Types.h before everything else as this defines some
+   macros that will change the behaviour of system headers.  */
+#include "stg/Types.h"
+
 /* We include windows.h very early, as on Win64 the CONTEXT type has
    fields "R8", "R9" and "R10", which goes bad if we've already
    #define'd those names for our own purposes (in stg/Regs.h) */
index f270686..08ba58c 100644 (file)
 #pragma once
 
 #if defined(mingw32_HOST_OS)
+#  if defined(__USE_MINGW_ANSI_STDIO)
+#    if __USE_MINGW_ANSI_STDIO != 1
+#       warning "Mismatch between __USE_MINGW_ANSI_STDIO definitions. \
+If using Rts.h make sure it is the first header included."
+#    endif
+#  else
 /* Inform mingw we want the ISO rather than Windows printf format specifiers. */
-#define __USE_MINGW_ANSI_STDIO 1
+#    define __USE_MINGW_ANSI_STDIO 1
+#endif
 #endif
 
 /* ISO C 99 says:
index 8d100e8..7a281d6 100644 (file)
 
 /* select and supporting types is not Posix */
 /* #include "PosixSource.h" */
+#include "Rts.h"
 #include <limits.h>
 #include <stdbool.h>
 #include "HsBase.h"
-#include "Rts.h"
 #if !defined(_WIN32)
 #include <poll.h>
 #endif
index fd47232..4732ede 100755 (executable)
@@ -2,6 +2,7 @@
 
 tarball_dir='ghc-tarballs'
 missing_files=0
+pkg_variant="phyx"
 
 # see #12502
 if test -z "$FIND"; then FIND="find"; fi
@@ -37,7 +38,7 @@ download_file() {
             return
         else
             echo "Downloading ${description} to ${dest_dir}..."
-            $curl_cmd || echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk || {
+            $curl_cmd || (echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk) || {
                 rm -f "${dest_file}"
                 fail "ERROR: Download failed."
                 exit 1
@@ -51,11 +52,11 @@ download_file() {
         echo "Downloading ${description} (signature) to ${dest_dir}..."
         local curl_cmd="curl -f -L ${file_url}.sig -o ${sig_file} --create-dirs -# ${extra_curl_opts}"
         if test -n "${backup_url}"; then
-            local curl_cmd_bnk="curl -f -L ${backup_url} -o ${sig_file} --create-dirs -# ${extra_curl_opts}"
+            local curl_cmd_bnk="curl -f -L "${backup_url}.sig" -o ${sig_file} --create-dirs -# ${extra_curl_opts}"
         else
             local curl_cmd_bnk="true"
         fi
-        $curl_cmd || echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk || {
+        $curl_cmd || (echo "Checking repo.msys2.org instead of Haskell.org..." && $curl_cmd_bnk) || {
                 rm -f "${dest_file}.sig"
                 fail "ERROR: Download failed."
                 exit 1
@@ -101,26 +102,23 @@ download_tarballs() {
     local package_prefix="mingw-w64"
     local format_url="/${mingw_arch}/${package_prefix}-${mingw_arch}"
 
-    download_mingw "${format_url}-crt-git-5.0.0.4795.e3d96cb1-1-any.pkg.tar.xz"
-    download_mingw "${format_url}-winpthreads-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz"
-    download_mingw "${format_url}-headers-git-5.0.0.4966.1eee2140-1-any.pkg.tar.xz"
-    download_mingw "${format_url}-libwinpthread-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-crt-git-7.0.0.5491.fe45801e-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-winpthreads-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-headers-git-7.0.0.5490.9ec54ed1-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-libwinpthread-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz"
     download_mingw "${format_url}-zlib-1.2.8-9-any.pkg.tar.xz"
-    download_mingw "${format_url}-isl-0.18-1-any.pkg.tar.xz"
-    download_mingw "${format_url}-mpfr-3.1.6-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-isl-0.21-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-mpfr-4.0.2-2-any.pkg.tar.xz"
     download_mingw "${format_url}-gmp-6.1.2-1-any.pkg.tar.xz"
-    download_mingw "${format_url}-binutils-2.29.1-1-any.pkg.tar.xz"
-    download_mingw "${format_url}-libidn2-2.0.4-1-any.pkg.tar.xz"
-    download_mingw "${format_url}-gcc-7.2.0-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-binutils-2.32-3-$pkg_variant.pkg.tar.xz"
+    download_mingw "${format_url}-libidn2-2.2.0-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-gcc-9.2.0-1-$pkg_variant.pkg.tar.xz"
+    download_mingw "${format_url}-mpc-1.1.0-1-any.pkg.tar.xz"
+    download_mingw "${format_url}-windows-default-manifest-6.4-3-any.pkg.tar.xz"
 
     # Upstream is unfortunately quite inconsistent in naming
     if test "$mingw_arch" != "sources"; then
-        download_mingw "${format_url}-mpc-1.0.3-2-any.pkg.tar.xz"
-        download_mingw "${format_url}-gcc-libs-7.2.0-1-any.pkg.tar.xz"
-    else
-        local format_url="${mingw_base_url}/${mingw_arch}/${package_prefix}"
-        download_mingw "${format_url}-i686-mpc-1.0.3-2.src.tar.gz"
-        download_mingw "${format_url}-x86_64-mpc-1.0.3-2.src.tar.gz"
+        download_mingw "${format_url}-gcc-libs-9.2.0-1-$pkg_variant.pkg.tar.xz"
     fi
 
     if ! test "$missing_files" = "0"
@@ -131,7 +129,7 @@ download_tarballs() {
 
 download_i386() {
     mingw_arch="i686"
-    tarball_dest_dir="mingw-w64/x86"
+    tarball_dest_dir="mingw-w64/i686"
     download_tarballs
 }
 
@@ -171,6 +169,54 @@ sync_binaries_and_sources() {
     done
 }
 
+patch_single_file () {
+    local patcher_base="$1"
+    local filename=$(readlink -f "$2")
+    local filepath=$(dirname "$filename")
+    local patcher="$patcher_base/iat-patcher.exe"
+    $patcher install "$filename" > /dev/null
+    rm -f "$filename.bak"
+    for file in $patcher_base/*.dll; do cp -f "$file" "${filepath}"; done
+    echo "Patched '$filename'"
+}
+
+patch_tarball () {
+    local tarball_name="$1"
+    local filename=$(basename "$tarball_name")
+    local filepath=$(dirname "$tarball_name")
+    local newfile=`echo "$filepath/$filename" | sed -e 's/-any/-phyx/'`
+    local arch=""
+
+    echo "=> ${filename}"
+
+    case $1 in
+        *x86_64*)
+            arch="x86_64"
+            ;;
+        *i686*)
+            arch="i686"
+            ;;
+        *)
+        echo "unknown architecture detected.  Stopping."
+        exit 1
+        ;;
+    esac
+
+    local base="$(pwd)"
+    local patcher_base="$(pwd)/ghc-tarballs/ghc-jailbreak/$arch"
+    local tmpdir="ghc-tarballs/tmpdir"
+    mkdir -p $tmpdir
+    cd $tmpdir
+    tar xJf "$base/$tarball_name"
+    find . -iname "*.exe" -exec bash -c \
+      'patch_single_file "'"${patcher_base}"'" "$0"' {} \;
+    tar cJf "$base/$newfile" .
+    cd "$base"
+    rm -rf $tmpdir
+    gpg --output "$base/${newfile}.sig" --detach-sig "$base/$newfile"
+    rm -f "$base/$tarball_name"
+}
+
 show_hashes_for_binaries() {
     $FIND ghc-tarballs/ -iname "*.*" | xargs md5sum | grep -v "\.sig" | sed -s "s/\*//"
 }
@@ -182,11 +228,13 @@ usage() {
     echo
     echo "Where <action> is one of,"
     echo ""
-    echo "    download     download the necessary tarballs for the given architecture"
-    echo "    fetch        download the necessary tarballs for the given architecture but doesn't verify their md5."
-    echo "    verify       verify the existence and correctness of the necessary tarballs"
-    echo "    hash         generate md5 hashes for inclusion in win32-tarballs.md5sum"
-    echo "    sync         upload packages downloaded with 'fetch mirror' to haskell.org"
+    echo "    download   download the necessary tarballs for the given architecture"
+    echo "    fetch      download the necessary tarballs for the given architecture but doesn't verify their md5."
+    echo "    grab       download the necessary tarballs using patched toolchains for the given architecture but doesn't verify their md5."
+    echo "    verify     verify the existence and correctness of the necessary tarballs"
+    echo "    patch      jailbreak the binaries in the tarballs and remove MAX_PATH limitations."
+    echo "    hash       generate md5 hashes for inclusion in win32-tarballs.md5sum"
+    echo "    sync       upload packages downloaded with 'fetch mirror' to haskell.org"
     echo ""
     echo "and <arch> is one of i386, x86_64,all or mirror (which includes sources)"
 }
@@ -199,7 +247,12 @@ case $1 in
         ;;
     fetch)
         download=1
+        verify=
+        ;;
+    grab)
+        download=1
         verify=0
+        pkg_variant="any"
         ;;
     verify)
         download=0
@@ -214,6 +267,28 @@ case $1 in
         show_hashes_for_binaries
         exit 1
         ;;
+    # This routine will download the latest ghc-jailbreak and unpack binutils and
+    # the ghc tarballs and patches every .exe in each.  Along with this is copies
+    # two dlls in every folder that it patches a .exe in.  Afterwards it re-creates
+    # the tarballs and generates a new signature file.
+    patch)
+        export -f patch_tarball
+        export -f patch_single_file
+
+        echo "Downloading ghc-jailbreak..."
+        curl -f -L https://mistuke.blob.core.windows.net/binaries/ghc-jailbreak-0.3.tar.gz \
+            -o ghc-tarballs/ghc-jailbreak/ghc-jailbreak.tar.gz --create-dirs -#
+        tar -C ghc-tarballs/ghc-jailbreak/ -xf ghc-tarballs/ghc-jailbreak/ghc-jailbreak.tar.gz
+
+        find ghc-tarballs/mingw-w64/ \(   -iname "*binutils*.tar.xz" \
+                                       -o -iname "*gcc*.tar.xz" \) \
+        -exec bash -c 'patch_tarball "$0"' {} \;
+
+        rm -rf ghc-tarballs/ghc-jailbreak
+
+        echo "Finished tarball generation, toolchain has been pre-patched."
+        exit 0
+        ;;
     *)
         usage
         exit 1
@@ -236,6 +311,7 @@ case $2 in
         download_i386
         download_x86_64
         verify=0
+        sigs=0
         download_sources
         show_hashes_for_binaries
         ;;
index 2c2d3df..5d23609 100644 (file)
@@ -1,39 +1,28 @@
-d0b3537c3f56b6f396b3dc23a905d186 ghc-tarballs/mingw-w64/sources/mingw-w64-crt-git-5.0.0.4795.e3d96cb1-1.src.tar.gz
-51d1006727d50a599bf30c34537bb6a9 ghc-tarballs/mingw-w64/sources/mingw-w64-binutils-2.29.1-1.src.tar.gz
-4578c232f7ed327bd6a364737cb018f5 ghc-tarballs/mingw-w64/sources/mingw-w64-gcc-7.2.0-1.src.tar.gz
-b605210c3d1b03092e3b223d1ccf4001 ghc-tarballs/mingw-w64/sources/mingw-w64-gmp-6.1.2-1.src.tar.gz
-1ad83604bb58ecf43f26843975046c1c ghc-tarballs/mingw-w64/sources/mingw-w64-headers-git-5.0.0.4966.1eee2140-1.src.tar.gz
-5c24d319656ed61e517dfa0fee7e475c ghc-tarballs/mingw-w64/sources/mingw-w64-i686-mpc-1.0.3-2.src.tar.gz
-214032557d2474f10c23c33bdaced8e5 ghc-tarballs/mingw-w64/sources/mingw-w64-isl-0.18-1.src.tar.gz
-8c7efe60059c4c80d0d1966c943b5aaa ghc-tarballs/mingw-w64/sources/mingw-w64-libidn2-2.0.4-1.src.tar.gz
-18e9d17e968773c0691c50d9ceeede34 ghc-tarballs/mingw-w64/sources/mingw-w64-mpfr-3.1.6-1.src.tar.gz
-0462bc73a8b15a68dece429f6f33ca81 ghc-tarballs/mingw-w64/sources/mingw-w64-winpthreads-git-5.0.0.4850.d1662dc7-1.src.tar.gz
-d4261042f502998006c57f0e6517998e ghc-tarballs/mingw-w64/sources/mingw-w64-x86_64-mpc-1.0.3-2.src.tar.gz
-534bb4756482f3271308576cdadfe5dc ghc-tarballs/mingw-w64/x86/mingw-w64-i686-crt-git-5.0.0.4795.e3d96cb1-1-any.pkg.tar.xz
-32078e2a67e34ff6c0b1795fe6ed9d36 ghc-tarballs/mingw-w64/sources/mingw-w64-zlib-1.2.8-9.src.tar.gz
-66e4fc3e62c0fa6723c0d27bdb832962 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-binutils-2.29.1-1-any.pkg.tar.xz
-634ad635913713abc0dbcb0ebef8c85b ghc-tarballs/mingw-w64/x86/mingw-w64-i686-gcc-7.2.0-1-any.pkg.tar.xz
-5343540bc6caa7ada564483f3a1fdff7 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-gcc-libs-7.2.0-1-any.pkg.tar.xz
-2f97e71e4ec122151c20350433268d8b ghc-tarballs/mingw-w64/x86/mingw-w64-i686-gmp-6.1.2-1-any.pkg.tar.xz
-07f374e6eb4846169921551ee73103e6 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-headers-git-5.0.0.4966.1eee2140-1-any.pkg.tar.xz
-ac7017bd5d69030cfe76e475e213b43a ghc-tarballs/mingw-w64/x86/mingw-w64-i686-isl-0.18-1-any.pkg.tar.xz
-f758e0d121619b166dbe36060c641767 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-libidn2-2.0.4-1-any.pkg.tar.xz
-3c718f86311bdd8c4438513a0f417391 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-libwinpthread-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz
-719e76fa7a54a8676d2e60af3bb13c45 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-mpc-1.0.3-2-any.pkg.tar.xz
-3780a25a6f20eef9b143f47f4b615e39 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-crt-git-5.0.0.4795.e3d96cb1-1-any.pkg.tar.xz
-9d71b5b4698310a6b961a7d9e273a204 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-mpfr-3.1.6-1-any.pkg.tar.xz
-8912539507692ecf3cebcd5405e1a526 ghc-tarballs/mingw-w64/x86/mingw-w64-i686-winpthreads-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz
-87c65e9b2930436a75dfd7d459ae98cb ghc-tarballs/mingw-w64/x86/mingw-w64-i686-zlib-1.2.8-9-any.pkg.tar.xz
-a7e26551a47ce247e432d3f3db416f2b ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-binutils-2.29.1-1-any.pkg.tar.xz
-c4ce9e9a696a76a350d6ed4222fe205e ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-7.2.0-1-any.pkg.tar.xz
-872a54d953e7d9e6f375e3712d540701 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-libs-7.2.0-1-any.pkg.tar.xz
+8af4600c30671775a1dde3b60fe75854 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-binutils-2.32-3-phyx.pkg.tar.xz
+c442f8999c10a24059a79a0a8974bc46 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-crt-git-7.0.0.5491.fe45801e-1-any.pkg.tar.xz
+dddc20e7431ab369f6e2726feb4f65d1 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-gcc-9.2.0-1-phyx.pkg.tar.xz
+64130e9d870de2292d4627a67fabee51 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-gcc-libs-9.2.0-1-phyx.pkg.tar.xz
+2f97e71e4ec122151c20350433268d8b ghc-tarballs/mingw-w64/i686/mingw-w64-i686-gmp-6.1.2-1-any.pkg.tar.xz
+192a25fe284cf8a78851a673d6ef672a ghc-tarballs/mingw-w64/i686/mingw-w64-i686-headers-git-7.0.0.5490.9ec54ed1-1-any.pkg.tar.xz
+a18983513ec46ff0716dc5742604a78b ghc-tarballs/mingw-w64/i686/mingw-w64-i686-isl-0.21-1-any.pkg.tar.xz
+c8dabb32fabe2492878e070ffad473f0 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-libidn2-2.2.0-1-any.pkg.tar.xz
+d05ca6e90126c17db19a8cd32e7347e8 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-libwinpthread-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz
+cae596bd144ad70875ef8f21e5bdb77d ghc-tarballs/mingw-w64/i686/mingw-w64-i686-mpc-1.1.0-1-any.pkg.tar.xz
+317a7a490da5c88f63638fbc5461b51e ghc-tarballs/mingw-w64/i686/mingw-w64-i686-mpfr-4.0.2-2-any.pkg.tar.xz
+15a5557d7b321bb26436dcf7adced5b7 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-windows-default-manifest-6.4-3-any.pkg.tar.xz
+beb76cd6141d11c000a1f5ff2ad34971 ghc-tarballs/mingw-w64/i686/mingw-w64-i686-winpthreads-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz
+87c65e9b2930436a75dfd7d459ae98cb ghc-tarballs/mingw-w64/i686/mingw-w64-i686-zlib-1.2.8-9-any.pkg.tar.xz
+4dca7def5591b8f999e5fa20084cc7a9 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-binutils-2.32-3-phyx.pkg.tar.xz
+d4336ca77b5edf3126a6c1358952567a ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-crt-git-7.0.0.5491.fe45801e-1-any.pkg.tar.xz
+e84e0426204b73af13752b65a035dfc2 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-9.2.0-1-phyx.pkg.tar.xz
+b6200865004cb558c8f5cd7526975602 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gcc-libs-9.2.0-1-phyx.pkg.tar.xz
 1e1f79abc9fc0534d360c2889b10a9f5 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-gmp-6.1.2-1-any.pkg.tar.xz
-8cce0779e70d5c3ef3564a11fb3bd931 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-headers-git-5.0.0.4966.1eee2140-1-any.pkg.tar.xz
-e1c25a67656e3667847be1f5eba73862 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-isl-0.18-1-any.pkg.tar.xz
-6faaa722dce8af954b30e39c4213d657 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libidn2-2.0.4-1-any.pkg.tar.xz
-df50f51f32efe8bff7a87f26c6832045 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libwinpthread-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz
-df1a7d4050568d83c265ae78c32ef30b ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpc-1.0.3-2-any.pkg.tar.xz
-d15495e807e2a87b917febedbfb3f5b3 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpfr-3.1.6-1-any.pkg.tar.xz
-c5ffd1a27eb459242b46d76b066e557e ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-winpthreads-git-5.0.0.4850.d1662dc7-1-any.pkg.tar.xz
+ef6ad2b29b92264c78d7ba6f0a875838 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-headers-git-7.0.0.5490.9ec54ed1-1-any.pkg.tar.xz
+623c059a9691ee7fc74b9e3f89b35782 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-isl-0.21-1-any.pkg.tar.xz
+29a39230c6208366b9d046fbe5bdde6f ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libidn2-2.2.0-1-any.pkg.tar.xz
+9953a82fd713f0c7ece69d9228238f4d ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-libwinpthread-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz
+c3aa7f45926edaaafe3bba988e327271 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpc-1.1.0-1-any.pkg.tar.xz
+951d8046e65768e00b6dfe1bb6e23016 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-mpfr-4.0.2-2-any.pkg.tar.xz
+8360a1dd2f6f4fd518907530f0839a48 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-windows-default-manifest-6.4-3-any.pkg.tar.xz
+e7cf8d4ac9e9b3f79c16a09413dd1322 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-winpthreads-git-7.0.0.5480.e14d23be-1-any.pkg.tar.xz
 60c3a388478f411b7a0908441ebeb537 ghc-tarballs/mingw-w64/x86_64/mingw-w64-x86_64-zlib-1.2.8-9-any.pkg.tar.xz
-b21d1681b61cf7a024e854096285b02e ghc-tarballs/perl/ghc-perl-1.tar.gz
index e34fcf0..4da4258 100644 (file)
  * https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/
  * https://sourceforge.net/p/mingw-w64/discussion/723797/thread/55520785/
  */
+/* Note [_iob_func symbol]
+ * ~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Microsoft in VS2013 to VS2015 transition made a backwards incompatible change
+ * to the stdio function __iob_func.
+ *
+ * They used to be defined as:
+ *
+ * #define stdin  (&__iob_func()[0])
+ * #define stdout (&__iob_func()[1])
+ * #define stderr (&__iob_func()[2])
+ *
+ * whereas now they're defined as:
+ *
+ * #define stdin  (__acrt_iob_func(0))
+ * #define stdout (__acrt_iob_func(1))
+ * #define stderr (__acrt_iob_func(2))
+ *
+ * Mingw-w64 followed along with the madness and so we have to deal with both
+ * version of these symbols.
+ *
+ * As such when you mix new and old libraries you get a missing symbols error
+ * for __acrt_iob_func.  It then links against the PLT for the function but that
+ * no longer exists.  Instead we forward the request for the PLT symbol to the
+ * symbol directly which is defined inline since we're using a newer compiler.
+ *
+ * See also:
+ * https://docs.microsoft.com/en-us/cpp/porting/visual-cpp-change-history-2003-2015?view=vs-2017#stdioh-and-conioh
+ */
 #define RTS_MINGW_ONLY_SYMBOLS                           \
       SymI_HasProto(stg_asyncReadzh)                     \
       SymI_HasProto(stg_asyncWritezh)                    \
       RTS_WIN64_ONLY(SymI_HasProto(__iob_func))          \
       /* see Note [Symbols for MinGW's printf] */        \
       SymI_HasProto(_lock_file)                          \
-      SymI_HasProto(_unlock_file)
+      SymI_HasProto(_unlock_file)                        \
+      /* See Note [_iob_func symbol] */                  \
+      RTS_WIN64_ONLY(SymI_HasProto_redirect(             \
+         __imp___acrt_iob_func, __rts_iob_func, true))   \
+      RTS_WIN32_ONLY(SymI_HasProto_redirect(             \
+         __imp____acrt_iob_func, __rts_iob_func, true))
 
 #define RTS_MINGW_COMPAT_SYMBOLS                         \
       SymI_HasProto_deprecated(access)                   \
 #define SymE_HasProto(vvv)    SymI_HasProto(vvv)
 #endif
 #define SymI_HasProto(vvv) /**/
-#define SymI_HasProto_redirect(vvv,xxx) /**/
+#define SymI_HasProto_redirect(vvv,xxx,weak) /**/
 #define SymI_HasProto_deprecated(vvv) /**/
 RTS_SYMBOLS
 RTS_RET_SYMBOLS
@@ -1013,9 +1047,9 @@ RTS_LIBFFI_SYMBOLS
 
 // SymI_HasProto_redirect allows us to redirect references to one symbol to
 // another symbol.  See newCAF/newRetainedCAF/newGCdCAF for an example.
-#define SymI_HasProto_redirect(vvv,xxx)   \
-    { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
-      (void*)(&(xxx)), false },
+#define SymI_HasProto_redirect(vvv,xxx,weak) \
+    { MAYBE_LEADING_UNDERSCORE_STR(#vvv),    \
+      (void*)(&(xxx)), weak },
 
 // SymI_HasProto_deprecated allows us to redirect references from their deprecated
 // names to the undeprecated ones. e.g. access -> _access.
index 650b1f5..b17c56e 100644 (file)
@@ -25,3 +25,8 @@ typedef struct _RtsSymbolVal {
 } RtsSymbolVal;
 
 extern RtsSymbolVal rtsSyms[];
+
+/* See Note [_iob_func symbol].  */
+#if defined(mingw32_HOST_OS)
+extern const void* __rts_iob_func;
+#endif
index f2c49f6..788b239 100644 (file)
@@ -275,6 +275,12 @@ const int default_alignment = 8;
 const int initHeapSizeMB    = 15;
 static HANDLE code_heap     = NULL;
 
+/* See Note [_iob_func symbol]
+   In order to emulate __iob_func the memory location needs to point the
+   location of the I/O structures in memory.  As such we need RODATA to contain
+   the pointer as a redirect.  Essentially it's a DATA DLL reference.  */
+const void* __rts_iob_func = (void*)&__acrt_iob_func;
+
 /* Low Fragmentation Heap, try to prevent heap from increasing in size when
    space can simply be reclaimed.  These are enums missing from mingw-w64's
    headers.  */
@@ -758,7 +764,7 @@ pathchar* findSystemLibrary_PEi386( pathchar* dll_name )
 HsPtr addLibrarySearchPath_PEi386(pathchar* dll_path)
 {
     HINSTANCE hDLL = LoadLibraryW(L"Kernel32.DLL");
-    LPAddDLLDirectory AddDllDirectory = (LPAddDLLDirectory)GetProcAddress((HMODULE)hDLL, "AddDllDirectory");
+    LPAddDLLDirectory AddDllDirectory = (LPAddDLLDirectory)(void*)GetProcAddress((HMODULE)hDLL, "AddDllDirectory");
 
     HsPtr result = NULL;
 
@@ -828,7 +834,7 @@ bool removeLibrarySearchPath_PEi386(HsPtr dll_path_index)
 
     if (dll_path_index != NULL) {
         HINSTANCE hDLL = LoadLibraryW(L"Kernel32.DLL");
-        LPRemoveDLLDirectory RemoveDllDirectory = (LPRemoveDLLDirectory)GetProcAddress((HMODULE)hDLL, "RemoveDllDirectory");
+        LPRemoveDLLDirectory RemoveDllDirectory = (LPRemoveDLLDirectory)(void*)GetProcAddress((HMODULE)hDLL, "RemoveDllDirectory");
 
         if (RemoveDllDirectory) {
             result = RemoveDllDirectory(dll_path_index);
index 538f132..4c33dfd 100644 (file)
@@ -172,5 +172,4 @@ because we have no stdcall convention on 64 bits.
 See #9218
 */
 
-
 #include "EndPrivate.h"
index 1995d51..0d99c7e 100644 (file)
@@ -1,10 +1,10 @@
 #pragma once
 
+#if defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)
+
 #include "ghcplatform.h"
 #include <LinkerInternals.h>
 
-#if defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)
-
 #include "elf_plt_arm.h"
 #include "elf_plt_aarch64.h"
 
index bb15576..35cc70b 100644 (file)
@@ -1,3 +1,7 @@
+#if defined(aarch64_HOST_ARCH)
+
+#if defined(OBJFORMAT_ELF)
+
 #include <stdlib.h>
 #include <assert.h>
 #include "elf_compat.h"
@@ -6,10 +10,6 @@
 #include "elf_util.h"
 #include "elf_plt.h"
 
-#if defined(aarch64_HOST_ARCH)
-
-#if defined(OBJFORMAT_ELF)
-
 #define Page(x) ((x) & ~0xFFF)
 
 typedef uint64_t addr_t;
index ac7a90e..06b41ef 100644 (file)
@@ -1,9 +1,9 @@
 #pragma once
 
-#include "LinkerInternals.h"
-
 #if defined(OBJFORMAT_ELF)
 
+#include "LinkerInternals.h"
+
 bool
 relocateObjectCodeAarch64(ObjectCode * oc);
 
index 57997b1..35fe72f 100644 (file)
@@ -41,7 +41,7 @@ static block_rec* free_blocks = NULL;
 typedef LPVOID(WINAPI *VirtualAllocExNumaProc)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD);
 
 /* Cache NUMA API call. */
-VirtualAllocExNumaProc VirtualAllocExNuma;
+VirtualAllocExNumaProc _VirtualAllocExNuma;
 
 void
 osMemInit(void)
@@ -52,8 +52,8 @@ osMemInit(void)
     /* Resolve and cache VirtualAllocExNuma. */
     if (osNumaAvailable() && RtsFlags.GcFlags.numa)
     {
-        VirtualAllocExNuma = (VirtualAllocExNumaProc)GetProcAddress(GetModuleHandleW(L"kernel32"), "VirtualAllocExNuma");
-        if (!VirtualAllocExNuma)
+        _VirtualAllocExNuma = (VirtualAllocExNumaProc)(void*)GetProcAddress(GetModuleHandleW(L"kernel32"), "VirtualAllocExNuma");
+        if (!_VirtualAllocExNuma)
         {
             sysErrorBelch(
                 "osBindMBlocksToNode: VirtualAllocExNuma does not exist. How did you get this far?");
@@ -569,7 +569,7 @@ void osBindMBlocksToNode(
                On windows also -xb is broken, it does nothing so that can't
                be used to tweak it (see #12577). So for now, just let the OS decide.
             */
-            temp = VirtualAllocExNuma(
+            temp = _VirtualAllocExNuma(
                           GetCurrentProcess(),
                           NULL, // addr? See base memory
                           size,
index c67d621..0942382 100644 (file)
@@ -111,7 +111,7 @@ createOSThread (OSThreadId* pId, char *name STG_UNUSED,
     HANDLE h;
     h = CreateThread ( NULL,  /* default security attributes */
                        0,
-                       (LPTHREAD_START_ROUTINE)startProc,
+                       (LPTHREAD_START_ROUTINE)(void*)startProc,
                        param,
                        0,
                        pId);
@@ -314,7 +314,9 @@ getNumberOfProcessorsGroups (void)
            on the API being available. So we'll have to resolve manually.  */
         HMODULE kernel = GetModuleHandleW(L"kernel32");
 
-        GetGroupCountProc GetActiveProcessorGroupCount = (GetGroupCountProc)GetProcAddress(kernel, "GetActiveProcessorGroupCount");
+        GetGroupCountProc GetActiveProcessorGroupCount
+          = (GetGroupCountProc)(void*)
+               GetProcAddress(kernel, "GetActiveProcessorGroupCount");
         n_groups = GetActiveProcessorGroupCount();
 
         IF_DEBUG(scheduler, debugBelch("[*] Number of processor groups detected: %u\n", n_groups));
@@ -348,7 +350,9 @@ getProcessorsDistribution (void)
         on the API being available. So we'll have to resolve manually.  */
         HMODULE kernel = GetModuleHandleW(L"kernel32");
 
-        GetItemCountProc  GetActiveProcessorCount = (GetItemCountProc)GetProcAddress(kernel, "GetActiveProcessorCount");
+        GetItemCountProc  GetActiveProcessorCount
+          = (GetItemCountProc)(void*)
+               GetProcAddress(kernel, "GetActiveProcessorCount");
 
         if (GetActiveProcessorCount)
         {
@@ -449,7 +453,9 @@ getNumberOfProcessors (void)
        on the API being available. So we'll have to resolve manually.  */
     HMODULE kernel = GetModuleHandleW(L"kernel32");
 
-    GetItemCountProc GetActiveProcessorCount = (GetItemCountProc)GetProcAddress(kernel, "GetActiveProcessorCount");
+    GetItemCountProc GetActiveProcessorCount
+      = (GetItemCountProc)(void*)
+          GetProcAddress(kernel, "GetActiveProcessorCount");
     if (GetActiveProcessorCount && !nproc)
     {
         nproc = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
@@ -516,7 +522,9 @@ setThreadAffinity (uint32_t n, uint32_t m) // cap N of M
        on the API being available. So we'll have to resolve manually.  */
     HMODULE kernel = GetModuleHandleW(L"kernel32");
 
-    SetThreadGroupAffinityProc SetThreadGroupAffinity = (SetThreadGroupAffinityProc)GetProcAddress(kernel, "SetThreadGroupAffinity");
+    SetThreadGroupAffinityProc SetThreadGroupAffinity
+      = (SetThreadGroupAffinityProc)(void*)
+          GetProcAddress(kernel, "SetThreadGroupAffinity");
 #endif
 
     for (i = 0; i < n_groups; i++)
@@ -564,8 +572,8 @@ interruptOSThread (OSThreadId id)
         sysErrorBelch("interruptOSThread: OpenThread");
         stg_exit(EXIT_FAILURE);
     }
-    pCSIO = (PCSIO) GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")),
-                                   "CancelSynchronousIo");
+    pCSIO = (PCSIO)(void*)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")),
+                                         "CancelSynchronousIo");
     if ( NULL != pCSIO ) {
         pCSIO(hdl);
     } else {
index 9ef22e8..bcdb226 100644 (file)
@@ -1,8 +1,8 @@
-#include <stdio.h>
 #include "T5594_stub.h"
-
 #include "HsFFI.h"
 
+#include <stdio.h>
+
 int main(int argc, char *argv[])
 {
   hs_init(&argc, &argv);
index ccf9ac9..5783fba 100644 (file)
@@ -1,8 +1,8 @@
-#include <stdio.h>
 #include "ffi002_stub.h"
-
 #include "HsFFI.h"
 
+#include <stdio.h>
+
 int main(int argc, char *argv[])
 {
   int i;
index 0a0e1ef..07197c4 100644 (file)
@@ -1,9 +1,8 @@
-#include <stdio.h>
-
 #include "HsFFI.h"
-
 #include "fptr01.h"
 
+#include <stdio.h>
+
 void f( HsInt *i )
 {
     printf( "f%d\n", (int)*i );
index 070a786..c620e75 100644 (file)
@@ -1,9 +1,8 @@
-#include <stdio.h>
-
 #include "HsFFI.h"
-
 #include "fptrfail01.h"
 
+#include <stdio.h>
+
 void f( HsInt *i )
 {
     printf( "f%d\n", (int)*i );
index 264c95d..aad8368 100644 (file)
@@ -1,7 +1,7 @@
 #include "ghcconfig.h"
+#include "Rts.h"
 #include <stdio.h>
 #include <stdlib.h>
-#include "Rts.h"
 #if defined(mingw32_HOST_OS)
 #include <malloc.h>
 #endif
index acf41cb..1595703 100644 (file)
@@ -1,7 +1,7 @@
 #include "ghcconfig.h"
+#include "Rts.h"
 #include <stdio.h>
 #include <stdlib.h>
-#include "Rts.h"
 #include <string.h>
 
 #define ITERATIONS 1000
index 6644705..4a761e5 100644 (file)
@@ -1,6 +1,6 @@
 /* -----------------------------------------------------------------------------
  *
- * (c) Tamar Christina 2018
+ * (c) Tamar Christina 2018-2019
  *
  * Windows I/O routines for file opening.
  *
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <share.h>
+#include <errno.h>
 
 /* This function converts Windows paths between namespaces. More specifically
    It converts an explorer style path into a NT or Win32 namespace.
-   This has several caveats but they are caviats that are native to Windows and
+   This has several caveats but they are caveats that are native to Windows and
    not POSIX. See
    https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx.
    Anything else such as raw device paths we leave untouched.  The main benefit
    of doing any of this is that we can break the MAX_PATH restriction and also
-   access raw handles that we couldn't before.  */
-static wchar_t* __hs_create_device_name (const wchar_t* filename) {
+   access raw handles that we couldn't before.
+
+   The resulting string is dynamically allocated and so callers are expected to
+   free this string.  */
+wchar_t* FS(create_device_name) (const wchar_t* filename) {
   const wchar_t* win32_dev_namespace  = L"\\\\.\\";
   const wchar_t* win32_file_namespace = L"\\\\?\\";
   const wchar_t* nt_device_namespace  = L"\\Device\\";
@@ -57,13 +61,31 @@ static wchar_t* __hs_create_device_name (const wchar_t* filename) {
         result[i] = L'\\';
     }
 
+  /* We need to expand dos short paths as well.  */
+  DWORD nResult = GetLongPathNameW (result, NULL, 0) + 1;
+  wchar_t* temp = NULL;
+  if (nResult > 1)
+    {
+      temp = _wcsdup (result);
+      free (result);
+      result = malloc (nResult * sizeof (wchar_t));
+      if (GetLongPathNameW (temp, result, nResult) == 0)
+        {
+          result = memcpy (result, temp, wcslen (temp));
+          goto cleanup;
+        }
+      free (temp);
+    }
+
   /* Now resolve any . and .. in the path or subsequent API calls may fail since
      Win32 will no longer resolve them.  */
-  DWORD nResult = GetFullPathNameW (result, 0, NULL, NULL) + 1;
-  wchar_t *temp = _wcsdup (result);
+  nResult = GetFullPathNameW (result, 0, NULL, NULL) + 1;
+  temp = _wcsdup (result);
+  free (result);
   result = malloc (nResult * sizeof (wchar_t));
   if (GetFullPathNameW (temp, nResult, result, NULL) == 0)
     {
+      result = memcpy (result, temp, wcslen (temp));
       goto cleanup;
     }
 
@@ -84,6 +106,7 @@ static wchar_t* __hs_create_device_name (const wchar_t* filename) {
   /* Create new string.  */
   int bLen = wcslen (result) + wcslen (ns) + 1;
   temp = _wcsdup (result);
+  free (result);
   result = malloc (bLen * sizeof (wchar_t));
   if (swprintf (result, bLen, L"%ls%ls", ns, temp) <= 0)
     {
@@ -100,23 +123,64 @@ cleanup:
   return NULL;
 }
 
-#define HAS_FLAG(a,b) ((a & b) == b)
+static int setErrNoFromWin32Error (void);
+/* Sets errno to the right error value and returns -1 to indicate the failure.
+   This function should only be called when the creation of the fd actually
+   failed and you want to return -1 for the fd.  */
+static
+int setErrNoFromWin32Error () {
+  switch (GetLastError()) {
+    case ERROR_SUCCESS:
+      errno = 0;
+      break;
+    case ERROR_ACCESS_DENIED:
+    case ERROR_FILE_READ_ONLY:
+      errno = EACCES;
+      break;
+    case ERROR_FILE_NOT_FOUND:
+    case ERROR_PATH_NOT_FOUND:
+      errno = ENOENT;
+      break;
+    case ERROR_FILE_EXISTS:
+      errno = EEXIST;
+      break;
+    case ERROR_NOT_ENOUGH_MEMORY:
+    case ERROR_OUTOFMEMORY:
+      errno = ENOMEM;
+      break;
+    case ERROR_INVALID_HANDLE:
+      errno = EBADF;
+      break;
+    case ERROR_INVALID_FUNCTION:
+      errno = EFAULT;
+      break;
+    default:
+      errno = EINVAL;
+      break;
+  }
+  return -1;
+}
+
+
+#define HAS_FLAG(a,b) (((a) & (b)) == (b))
 
 int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode)
 {
   /* Construct access mode.  */
+  /* https://docs.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants  */
   DWORD dwDesiredAccess = 0;
   if (HAS_FLAG (oflag, _O_RDONLY))
-    dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES;
+    dwDesiredAccess |= GENERIC_READ;
   if (HAS_FLAG (oflag, _O_RDWR))
-    dwDesiredAccess |= GENERIC_WRITE | GENERIC_READ | FILE_READ_DATA |
-                       FILE_WRITE_DATA | FILE_READ_ATTRIBUTES |
-                       FILE_WRITE_ATTRIBUTES;
-  if (HAS_FLAG (oflag,  _O_WRONLY))
-    dwDesiredAccess|= GENERIC_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES;
+    dwDesiredAccess |= GENERIC_WRITE | GENERIC_READ;
+  if (HAS_FLAG (oflag, _O_WRONLY))
+    dwDesiredAccess |= GENERIC_WRITE;
+  if (HAS_FLAG (oflag, _O_APPEND))
+    dwDesiredAccess |= FILE_APPEND_DATA;
 
   /* Construct shared mode.  */
-  DWORD dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
+  /* https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants */
+  DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
   if (HAS_FLAG (shflag, _SH_DENYRW))
     dwShareMode &= ~(FILE_SHARE_READ | FILE_SHARE_WRITE);
   if (HAS_FLAG (shflag, _SH_DENYWR))
@@ -138,21 +202,33 @@ int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode)
     }
 
   /* Create file disposition.  */
-  DWORD dwCreationDisposition = OPEN_EXISTING;
-  if (HAS_FLAG (oflag, _O_CREAT))
-    dwCreationDisposition = OPEN_ALWAYS;
+  /* https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea */
+  DWORD dwCreationDisposition = 0;
   if (HAS_FLAG (oflag, (_O_CREAT | _O_EXCL)))
-    dwCreationDisposition = CREATE_NEW;
-  if (HAS_FLAG (oflag, _O_TRUNC) && !HAS_FLAG (oflag, _O_CREAT))
-    dwCreationDisposition = TRUNCATE_EXISTING;
+    dwCreationDisposition |= CREATE_NEW;
+  else if (HAS_FLAG (oflag, _O_TRUNC | _O_CREAT))
+    dwCreationDisposition |= CREATE_ALWAYS;
+  else if (HAS_FLAG (oflag, _O_TRUNC) && !HAS_FLAG (oflag, O_RDONLY))
+    dwCreationDisposition |= TRUNCATE_EXISTING;
+  else if (HAS_FLAG (oflag, _O_APPEND | _O_CREAT))
+    dwCreationDisposition |= OPEN_ALWAYS;
+  else if (HAS_FLAG (oflag, _O_APPEND))
+    dwCreationDisposition |= OPEN_EXISTING;
+  else if (HAS_FLAG (oflag, _O_CREAT))
+    dwCreationDisposition |= OPEN_ALWAYS;
+  else
+    dwCreationDisposition |= OPEN_EXISTING;
 
   /* Set file access attributes.  */
   DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
   if (HAS_FLAG (oflag, _O_RDONLY))
     dwFlagsAndAttributes |= 0; /* No special attribute.  */
-  if (HAS_FLAG (oflag, (_O_CREAT | _O_TEMPORARY)))
-    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
-  if (HAS_FLAG (oflag, (_O_CREAT | _O_SHORT_LIVED)))
+  if (HAS_FLAG (oflag, _O_TEMPORARY))
+    {
+      dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+      dwShareMode |= FILE_SHARE_DELETE;
+    }
+  if (HAS_FLAG (oflag, _O_SHORT_LIVED))
     dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
   if (HAS_FLAG (oflag, _O_RANDOM))
     dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
@@ -162,6 +238,11 @@ int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode)
   if (dwFlagsAndAttributes != FILE_ATTRIBUTE_NORMAL)
     dwFlagsAndAttributes &= ~FILE_ATTRIBUTE_NORMAL;
 
+  /* Ensure we have shared read for files which are opened read-only. */
+  if (HAS_FLAG (dwCreationDisposition, OPEN_EXISTING)
+      && ((dwDesiredAccess & (GENERIC_WRITE|GENERIC_READ)) == GENERIC_READ))
+    dwShareMode |= FILE_SHARE_READ;
+
   /* Set security attributes.  */
   SECURITY_ATTRIBUTES securityAttributes;
   ZeroMemory (&securityAttributes, sizeof(SECURITY_ATTRIBUTES));
@@ -169,41 +250,39 @@ int FS(swopen) (const wchar_t* filename, int oflag, int shflag, int pmode)
   securityAttributes.lpSecurityDescriptor = NULL;
   securityAttributes.nLength              = sizeof(SECURITY_ATTRIBUTES);
 
-  wchar_t* _filename = __hs_create_device_name (filename);
+  wchar_t* _filename = FS(create_device_name) (filename);
   if (!_filename)
     return -1;
 
   HANDLE hResult
     = CreateFileW (_filename, dwDesiredAccess, dwShareMode, &securityAttributes,
                    dwCreationDisposition, dwFlagsAndAttributes, NULL);
+
   free (_filename);
   if (INVALID_HANDLE_VALUE == hResult)
-    return -1;
+    return setErrNoFromWin32Error ();
 
   /* Now we have a Windows handle, we have to convert it to an FD and apply
      the remaining flags.  */
   const int flag_mask = _O_APPEND | _O_RDONLY | _O_TEXT | _O_WTEXT;
   int fd = _open_osfhandle ((intptr_t)hResult, oflag & flag_mask);
   if (-1 == fd)
-    return -1;
+    return setErrNoFromWin32Error ();
 
   /* Finally we can change the mode to the requested one.  */
   const int mode_mask = _O_TEXT | _O_BINARY | _O_U16TEXT | _O_U8TEXT | _O_WTEXT;
   if ((oflag & mode_mask) && (-1 == _setmode (fd, oflag & mode_mask)))
-    return -1;
+    return setErrNoFromWin32Error ();
 
   return fd;
 }
 
-FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode)
+int FS(translate_mode) (const wchar_t* mode)
 {
-  int shflag = 0;
-  int pmode  = 0;
-  int oflag  = 0;
-
+  int oflag = 0;
   int len = wcslen (mode);
   int i;
-  #define IS_EXT(X) ((i < (len - 1)) && mode[i] == X)
+  #define IS_EXT(X) ((i < (len - 1)) && mode[i+1] == X)
 
   for (i = 0; i < len; i++)
     {
@@ -261,7 +340,19 @@ FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode)
     }
   #undef IS_EXT
 
+  return oflag;
+}
+
+FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode)
+{
+  int shflag = 0;
+  int pmode  = 0;
+  int oflag  = FS(translate_mode) (mode);
+
   int fd = FS(swopen) (filename, oflag, shflag, pmode);
+  if (fd < 0)
+    return NULL;
+
   FILE* file = _wfdopen (fd, mode);
   return file;
 }
@@ -281,8 +372,150 @@ FILE *FS(fopen) (const char* filename, const char* mode)
   FILE *result = FS(fwopen) (w_filename, w_mode);
   free (w_filename);
   free (w_mode);
+
+  return result;
+}
+
+int FS(sopen) (const char* filename, int oflag, int shflag, int pmode)
+{
+  size_t len = mbstowcs (NULL, filename, 0);
+  wchar_t *w_filename = malloc (sizeof (wchar_t) * (len + 1));
+  mbstowcs (w_filename, filename, len);
+  w_filename[len] = L'\0';
+
+  int result = FS(swopen) (w_filename, oflag, shflag, pmode);
+  free (w_filename);
+
+  return result;
+}
+
+int FS(_stat) (const char *path, struct _stat *buffer)
+{
+  size_t len = mbstowcs (NULL, path, 0);
+  wchar_t *w_path = malloc (sizeof (wchar_t) * (len + 1));
+  mbstowcs (w_path, path, len);
+  w_path[len] = L'\0';
+
+  int result = FS(_wstat) (w_path, buffer);
+  free (w_path);
+
   return result;
 }
+
+int FS(_stat64) (const char *path, struct __stat64 *buffer)
+{
+  size_t len = mbstowcs (NULL, path, 0);
+  wchar_t *w_path = malloc (sizeof (wchar_t) * (len + 1));
+  mbstowcs (w_path, path, len);
+  w_path[len] = L'\0';
+
+  int result = FS(_wstat64) (w_path, buffer);
+  free (w_path);
+
+  return result;
+}
+
+static __time64_t ftToPosix(FILETIME ft)
+{
+  /* takes the last modified date.  */
+  LARGE_INTEGER date, adjust;
+  date.HighPart = ft.dwHighDateTime;
+  date.LowPart = ft.dwLowDateTime;
+
+  /* 100-nanoseconds = milliseconds * 10000.  */
+  /* A UNIX timestamp contains the number of seconds from Jan 1, 1970, while the
+     FILETIME documentation says: Contains a 64-bit value representing the
+     number of 100-nanosecond intervals since January 1, 1601 (UTC).
+
+     Between Jan 1, 1601 and Jan 1, 1970 there are 11644473600 seconds */
+  adjust.QuadPart = 11644473600000 * 10000;
+
+  /* removes the diff between 1970 and 1601.  */
+  date.QuadPart -= adjust.QuadPart;
+
+  /* converts back from 100-nanoseconds to seconds.  */
+  return (__time64_t)date.QuadPart / 10000000;
+}
+
+int FS(_wstat) (const wchar_t *path, struct _stat *buffer)
+{
+  ZeroMemory (buffer, sizeof (struct _stat));
+  wchar_t* _path = FS(create_device_name) (path);
+  if (!_path)
+    return -1;
+
+    /* Construct shared mode.  */
+  DWORD dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
+  DWORD dwDesiredAccess = FILE_READ_ATTRIBUTES;
+  DWORD dwFlagsAndAttributes = FILE_FLAG_BACKUP_SEMANTICS;
+  DWORD dwCreationDisposition = OPEN_EXISTING;
+
+  SECURITY_ATTRIBUTES securityAttributes;
+  ZeroMemory (&securityAttributes, sizeof(SECURITY_ATTRIBUTES));
+  securityAttributes.bInheritHandle       = false;
+  securityAttributes.lpSecurityDescriptor = NULL;
+  securityAttributes.nLength              = sizeof(SECURITY_ATTRIBUTES);
+
+  HANDLE hResult
+    = CreateFileW (_path, dwDesiredAccess, dwShareMode, &securityAttributes,
+                   dwCreationDisposition, dwFlagsAndAttributes, NULL);
+
+  if (INVALID_HANDLE_VALUE == hResult)
+    {
+      free (_path);
+      return setErrNoFromWin32Error ();
+    }
+
+  WIN32_FILE_ATTRIBUTE_DATA finfo;
+  ZeroMemory (&finfo, sizeof (WIN32_FILE_ATTRIBUTE_DATA));
+  if(!GetFileAttributesExW (_path, GetFileExInfoStandard, &finfo))
+    {
+      free (_path);
+      CloseHandle (hResult);
+      return setErrNoFromWin32Error ();
+    }
+
+  unsigned short mode = _S_IREAD;
+
+  if (finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+    mode |= (_S_IFDIR | _S_IEXEC);
+  else
+  {
+    mode |= _S_IFREG;
+    DWORD type;
+    if (GetBinaryTypeW (_path, &type))
+      mode |= _S_IEXEC;
+  }
+
+  if (!(finfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+    mode |= _S_IWRITE;
+
+  buffer->st_mode  = mode;
+  buffer->st_nlink = 1;
+  buffer->st_size  = ((uint64_t)finfo.nFileSizeHigh << 32) + finfo.nFileSizeLow;
+  buffer->st_atime = ftToPosix (finfo.ftLastAccessTime);
+  buffer->st_mtime = buffer->st_ctime = ftToPosix (finfo.ftLastWriteTime);
+  free (_path);
+  CloseHandle (hResult);
+  return 0;
+}
+
+int FS(_wstat64) (const wchar_t *path, struct __stat64 *buffer)
+{
+  struct _stat buf;
+  ZeroMemory (buffer, sizeof (struct __stat64));
+
+  int result = FS(_wstat) (path, &buf);
+
+  buffer->st_mode = buf.st_mode;
+  buffer->st_nlink = 1;
+  buffer->st_size = buf.st_size;
+  buffer->st_atime = buf.st_atime;
+  buffer->st_mtime = buf.st_mtime;
+
+  return result;
+}
+
 #else
 FILE *FS(fopen) (const char* filename, const char* mode)
 {
index ab2eded..3931e6e 100644 (file)
@@ -1,6 +1,6 @@
 /* -----------------------------------------------------------------------------
  *
- * (c) Tamar Christina 2018
+ * (c) Tamar Christina 2018-2019
  *
  * Windows I/O routines for file opening.
  *
 
 #if defined(_WIN32)
 #include <wchar.h>
-
+wchar_t* FS(create_device_name) (const wchar_t*);
+int FS(translate_mode) (const wchar_t*);
 int FS(swopen) (const wchar_t* filename, int oflag,
                 int shflag, int pmode);
+int FS(sopen) (const char* filename, int oflag,
+               int shflag, int pmode);
 FILE *FS(fwopen) (const wchar_t* filename, const wchar_t* mode);
 FILE *FS(fopen) (const char* filename, const char* mode);
+int FS(_stat) (const char *path, struct _stat *buffer);
+int FS(_stat64) (const char *path, struct __stat64 *buffer);
+int FS(_wstat) (const wchar_t *path, struct _stat *buffer);
+int FS(_wstat64) (const wchar_t *path, struct __stat64 *buffer);
 #else
 
 FILE *FS(fopen) (const char* filename, const char* mode);
index 5827331..0962f9c 100644 (file)
@@ -385,7 +385,23 @@ generate directory distdir config_args
           fixupRtsLibName x = x
           transitiveDepNames = map (display . packageName) transitive_dep_ids
 
-          libraryDirs = forDeps Installed.libraryDirs
+          -- Note [Msys2 path translation bug].
+          -- Msys2 has an annoying bug in their path conversion code.
+          -- Officially anything starting with a drive letter should not be
+          -- subjected to path translations, however it seems to only consider
+          -- E:\\ and E:// to be Windows paths.  Mixed mode paths such as E:/
+          -- that are produced here get corrupted.
+          --
+          -- Tamar@Rage /t/translate> ./a.exe -optc-I"E://ghc-dev/msys64/"
+          -- path: -optc-IE://ghc-dev/msys64/
+          -- Tamar@Rage /t/translate> ./a.exe -optc-I"E:ghc-dev/msys64/"
+          -- path: -optc-IE:ghc-dev/msys64/
+          -- Tamar@Rage /t/translate> ./a.exe -optc-I"E:\ghc-dev/msys64/"
+          -- path: -optc-IE:\ghc-dev/msys64/
+          --
+          -- As such, let's just normalize the filepaths which is a good thing
+          -- to do anyway.
+          libraryDirs = map normalise $ forDeps Installed.libraryDirs
           -- The mkLibraryRelDir function is a bit of a hack.
           -- Ideally it should be handled in the makefiles instead.
           mkLibraryRelDir "rts"        = "rts/dist/build"
@@ -402,7 +418,8 @@ generate directory distdir config_args
           injectDistInstall x | takeBaseName x == "include" = [x, takeDirectory x ++ "/dist-install/build/" ++ takeBaseName x]
           injectDistInstall x = [x]
 
-      wrappedIncludeDirs <- wrap $ concatMap injectDistInstall $ forDeps Installed.includeDirs
+      -- See Note [Msys2 path translation bug].
+      wrappedIncludeDirs <- wrap $ map normalise $ concatMap injectDistInstall $ forDeps Installed.includeDirs
 
       let variablePrefix = directory ++ '_':distdir
           mods      = map display modules