[pypy-svn] r64596 - in pypy/trunk/pypy: module/posix rlib

afa at codespeak.net afa at codespeak.net
Thu Apr 23 16:20:10 CEST 2009


Author: afa
Date: Thu Apr 23 16:20:07 2009
New Revision: 64596

Modified:
   pypy/trunk/pypy/module/posix/__init__.py
   pypy/trunk/pypy/module/posix/interp_posix.py
   pypy/trunk/pypy/rlib/rwin32.py
Log:
Implement nt.urandom for Windows.

This fixes test_threaded_import
(Yes: test_threaded_import tests that tempfile.TemporaryFile does not need the import lock;
TemporaryFile uses random(), which tried to use os.urandom, then defaulted to some code that 
"import time")


Modified: pypy/trunk/pypy/module/posix/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/posix/__init__.py	(original)
+++ pypy/trunk/pypy/module/posix/__init__.py	Thu Apr 23 16:20:07 2009
@@ -61,6 +61,10 @@
     'utime'     : 'interp_posix.utime',
     '_statfields': 'interp_posix.getstatfields(space)',
     }
+
+    if os.name == 'nt':
+        interpleveldefs['urandom'] = 'interp_posix.win32_urandom'
+
     if hasattr(os, 'chown'):
         interpleveldefs['chown'] = 'interp_posix.chown'
     if hasattr(os, 'ftruncate'):

Modified: pypy/trunk/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/trunk/pypy/module/posix/interp_posix.py	(original)
+++ pypy/trunk/pypy/module/posix/interp_posix.py	Thu Apr 23 16:20:07 2009
@@ -5,11 +5,13 @@
 from pypy.interpreter.error import OperationError, wrap_oserror
 from pypy.rpython.module.ll_os import RegisterOs
 from pypy.rpython.module import ll_os_stat
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.tool import rffi_platform
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
 import os, sys
 _WIN = sys.platform == 'win32'
-                          
+
 def open(space, fname, flag, mode=0777):
     """Open a file (for low level IO).
 Return a file descriptor (a small integer)."""
@@ -349,11 +351,16 @@
     def __init__(self, space): 
         self.space = space
         self.w_environ = space.newdict()
+        if _WIN:
+            self.cryptProviderPtr = lltype.malloc(
+                rffi.CArray(HCRYPTPROV), 1, zero=True, flavor='raw')
     def startup(self, space):
         _convertenviron(space, self.w_environ)
     def _freeze_(self):
         # don't capture the environment in the translated pypy
         self.space.call_method(self.w_environ, 'clear')
+        if _WIN:
+            self.cryptProviderPtr[0] = HCRYPTPROV._default
         return True
 
 def get(space): 
@@ -817,3 +824,73 @@
         raise wrap_oserror(space, e)
     return space.w_None
 chown.unwrap_spec = [ObjSpace, str, int, int]
+
+if _WIN:
+    from pypy.rlib import rwin32
+
+    eci = ExternalCompilationInfo(
+        includes = ['windows.h'],
+        libraries = ['advapi32'],
+        )
+
+    class CConfig:
+        _compilation_info_ = eci
+        PROV_RSA_FULL = rffi_platform.ConstantInteger(
+            "PROV_RSA_FULL")
+        CRYPT_VERIFYCONTEXT = rffi_platform.ConstantInteger(
+            "CRYPT_VERIFYCONTEXT")
+
+    globals().update(rffi_platform.configure(CConfig))
+
+    HCRYPTPROV = rwin32.ULONG_PTR
+
+    CryptAcquireContext = rffi.llexternal(
+        'CryptAcquireContextA',
+        [rffi.CArrayPtr(HCRYPTPROV),
+         rwin32.LPCSTR, rwin32.LPCSTR, rwin32.DWORD, rwin32.DWORD],
+        rwin32.BOOL,
+        calling_conv='win',
+        compilation_info=eci)
+
+    CryptGenRandom = rffi.llexternal(
+        'CryptGenRandom',
+        [HCRYPTPROV, rwin32.DWORD, rffi.CArrayPtr(rwin32.BYTE)],
+        rwin32.BOOL,
+        calling_conv='win',
+        compilation_info=eci)
+
+    def win32_urandom(space, n):
+        """urandom(n) -> str
+
+        Return a string of n random bytes suitable for cryptographic use.
+        """
+
+        if n < 0:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("negative argument not allowed"))
+
+        provider = get(space).cryptProviderPtr[0]
+        if not provider:
+            # Acquire context.
+            # This handle is never explicitly released. The operating
+            # system will release it when the process terminates.
+            if not CryptAcquireContext(
+                get(space).cryptProviderPtr, None, None,
+                PROV_RSA_FULL, CRYPT_VERIFYCONTEXT):
+                raise rwin32.lastWindowsError("CryptAcquireContext")
+
+            provider = get(space).cryptProviderPtr[0]
+
+        # Get random data
+        buf = lltype.malloc(rffi.CArray(rwin32.BYTE), n,
+                            zero=True, # zero seed
+                            flavor='raw')
+        try:
+            if not CryptGenRandom(provider, n, buf):
+                raise rwin32.lastWindowsError("CryptGenRandom")
+
+            return space.wrap(
+                rffi.charpsize2str(rffi.cast(rffi.CCHARP, buf), n))
+        finally:
+            lltype.free(buf, flavor='raw')
+    win32_urandom.unwrap_spec = [ObjSpace, int]

Modified: pypy/trunk/pypy/rlib/rwin32.py
==============================================================================
--- pypy/trunk/pypy/rlib/rwin32.py	(original)
+++ pypy/trunk/pypy/rlib/rwin32.py	Thu Apr 23 16:20:07 2009
@@ -27,6 +27,7 @@
         WORD = rffi_platform.SimpleType("WORD", rffi.UINT)
         DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT)
         BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG)
+        BYTE = rffi_platform.SimpleType("BYTE", rffi.UCHAR)
         INT = rffi_platform.SimpleType("INT", rffi.INT)
         LONG = rffi_platform.SimpleType("LONG", rffi.LONG)
         PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP)
@@ -36,6 +37,7 @@
         LPCSTR = rffi_platform.SimpleType("LPCSTR", rffi.CCHARP)
         LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP)
         SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T)
+        ULONG_PTR = rffi_platform.SimpleType("ULONG_PTR", rffi.ULONG)
 
         HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG)
         HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP)
@@ -71,6 +73,7 @@
     PFILETIME = rffi.CArrayPtr(FILETIME)
 
     GetLastError = winexternal('GetLastError', [], DWORD)
+    SetLastError = winexternal('SetLastError', [DWORD], lltype.Void)
 
     LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP)
     GetProcAddress = winexternal('GetProcAddress',
@@ -109,7 +112,7 @@
         LocalFree(buf[0])
         return result
 
-    def lastWindowsError():
+    def lastWindowsError(context=None):
         code = GetLastError()
         message = FormatError(code)
         return WindowsError(code, message)



More information about the Pypy-commit mailing list