[pypy-commit] pypy default: add validate_fd for windows and test it
mattip
noreply at buildbot.pypy.org
Thu Apr 26 20:26:20 CEST 2012
Author: Matti Picus <matti.picus at gmail.com>
Branch:
Changeset: r54766:31add8845fcc
Date: 2012-04-26 19:21 +0300
http://bitbucket.org/pypy/pypy/changeset/31add8845fcc/
Log: add validate_fd for windows and test it
diff --git a/pypy/rlib/rposix.py b/pypy/rlib/rposix.py
--- a/pypy/rlib/rposix.py
+++ b/pypy/rlib/rposix.py
@@ -1,9 +1,11 @@
import os
-from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT
+from pypy.rpython.lltypesystem.rffi import (CConstant, CExternVariable,
+ INT, CCHARPP)
from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import specialize
+from pypy.rlib import jit
class CConstantErrno(CConstant):
# these accessors are used when calling get_errno() or set_errno()
@@ -18,9 +20,69 @@
def __setitem__(self, index, value):
assert index == 0
ll2ctypes.TLS.errno = value
+if os.name == 'nt':
+ separate_module_sources =['''
+ /* Lifted completely from CPython 3.3 Modules/posix_module.c */
+ #include <malloc.h> /* for _msize */
+ typedef struct {
+ intptr_t osfhnd;
+ char osfile;
+ } my_ioinfo;
+ extern __declspec(dllimport) char * __pioinfo[];
+ #define IOINFO_L2E 5
+ #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
+ #define IOINFO_ARRAYS 64
+ #define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
+ #define FOPEN 0x01
+ #define _NO_CONSOLE_FILENO (intptr_t)-2
+ /* This function emulates what the windows CRT
+ does to validate file handles */
+ int
+ _PyVerify_fd(int fd)
+ {
+ const int i1 = fd >> IOINFO_L2E;
+ const int i2 = fd & ((1 << IOINFO_L2E) - 1);
+
+ static size_t sizeof_ioinfo = 0;
+
+ /* Determine the actual size of the ioinfo structure,
+ * as used by the CRT loaded in memory
+ */
+ if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
+ sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
+ }
+ if (sizeof_ioinfo == 0) {
+ /* This should not happen... */
+ goto fail;
+ }
+
+ /* See that it isn't a special CLEAR fileno */
+ if (fd != _NO_CONSOLE_FILENO) {
+ /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that. Instead
+ * we check pointer validity and other info
+ */
+ if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
+ /* finally, check that the file is open */
+ my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
+ if (info->osfile & FOPEN) {
+ return 1;
+ }
+ }
+ }
+ fail:
+ errno = EBADF;
+ return 0;
+ }
+ ''',]
+ export_symbols = ['_PyVerify_fd']
+else:
+ separate_module_sources = []
+ export_symbols = []
errno_eci = ExternalCompilationInfo(
- includes=['errno.h']
+ includes=['errno.h','stdio.h'],
+ separate_module_sources = separate_module_sources,
+ export_symbols = export_symbols,
)
_get_errno, _set_errno = CExternVariable(INT, 'errno', errno_eci,
@@ -35,6 +97,21 @@
def set_errno(errno):
_set_errno(rffi.cast(INT, errno))
+if os.name == 'nt':
+ _validate_fd = rffi.llexternal(
+ "_PyVerify_fd", [rffi.INT], rffi.INT,
+ compilation_info=errno_eci,
+ )
+ @jit.dont_look_inside
+ def validate_fd(fd):
+ if not _validate_fd(fd):
+ raise OSError(get_errno(), 'Bad file descriptor')
+else:
+ def _validate_fd(fd):
+ return 1
+
+ def validate_fd(fd):
+ return 1
def closerange(fd_low, fd_high):
# this behaves like os.closerange() from Python 2.6.
diff --git a/pypy/rlib/test/test_rposix.py b/pypy/rlib/test/test_rposix.py
--- a/pypy/rlib/test/test_rposix.py
+++ b/pypy/rlib/test/test_rposix.py
@@ -131,3 +131,13 @@
os.rmdir(self.ufilename)
except Exception:
pass
+
+ def test_validate_fd(self):
+ assert rposix._validate_fd(0) == 1
+ fid = open(str(udir.join('validate_test.txt')), 'w')
+ fd = fid.fileno()
+ assert rposix._validate_fd(fd) == 1
+ fid.close()
+ assert rposix._validate_fd(fd) == 0
+
+
More information about the pypy-commit
mailing list