bpo-32890, os: Use errno instead of GetLastError() in execve() and truncate() (GH-5784)


path_error() uses GetLastError() on Windows, but some os functions
are implemented via CRT APIs which report errors via errno.
This may result in raising OSError with invalid error code (such
as zero).

Introduce posix_path_error() function and use it where appropriate.
(cherry picked from commit 834603112e6ca35944dd21105b01fca562dc3241)

Co-authored-by: Alexey Izbyshev <izbyshev@ispras.ru>
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index cef4a09..098d1d4 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -1589,6 +1589,16 @@
         with self.assertRaises(ValueError):
             os.execve(args[0], args, newenv)
 
+    @unittest.skipUnless(sys.platform == "win32", "Win32-specific test")
+    def test_execve_with_empty_path(self):
+        # bpo-32890: Check GetLastError() misuse
+        try:
+            os.execve('', ['arg'], {})
+        except OSError as e:
+            self.assertTrue(e.winerror is None or e.winerror != 0)
+        else:
+            self.fail('No OSError raised')
+
 
 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
 class Win32ErrorTests(unittest.TestCase):