[pypy-commit] pypy missing-os-functions: Correctly detects the presence of fchmod and fchown.

amauryfa noreply at buildbot.pypy.org
Fri Feb 22 16:57:53 CET 2013


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: missing-os-functions
Changeset: r61614:5e890c5dac82
Date: 2013-02-22 16:57 +0100
http://bitbucket.org/pypy/pypy/changeset/5e890c5dac82/

Log:	Correctly detects the presence of fchmod and fchown. Tests run and
	pass even with an old pypy which does (yet) not provide the
	functions.

	os.fchmod and os.fchown are not used anymore, they could probably be
	removed from ll_os.py

diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -1,6 +1,7 @@
 # Package initialisation
 from pypy.interpreter.mixedmodule import MixedModule
 from rpython.rtyper.module.ll_os import RegisterOs
+from rpython.rlib import rposix
 
 import os, sys
 exec 'import %s as posix' % os.name
@@ -95,7 +96,7 @@
         }
 
     for name in '''
-            wait wait3 wait4 chown lchown fchown fchmod ftruncate
+            wait wait3 wait4 chown lchown ftruncate
             fsync fdatasync fchdir putenv unsetenv killpg getpid
             link symlink readlink
             fork openpty forkpty waitpid execv execve uname sysconf fpathconf
@@ -108,6 +109,12 @@
         if hasattr(posix, name):
             interpleveldefs[name] = 'interp_posix.%s' % (name,)
 
+    for name in '''fchmod fchown
+                '''.split():
+        symbol = 'HAS_' + name.upper()
+        if getattr(rposix, symbol):
+            interpleveldefs[name] = 'interp_posix.%s' % (name,)
+
     for constant in '''
             F_OK R_OK W_OK X_OK NGROUPS_MAX TMP_MAX
             WNOHANG WCONTINUED WUNTRACED
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -20,6 +20,10 @@
     
 c_int = "c_int"
 
+def oserror_from_errno(space):
+    errno = rposix.get_errno()
+    return wrap_oserror(space, OSError(errno, "OSError"))
+
 # CPython 2.7 semantics are too messy to follow exactly,
 # e.g. setuid(-2) works on 32-bit but not on 64-bit.  As a result,
 # we decided to just accept any 'int', i.e. any C signed long, and
@@ -586,10 +590,9 @@
     """Change the access permissions of the file given by file
 descriptor fd."""
     fd = space.c_filedescriptor_w(w_fd)
-    try:
-        os.fchmod(fd, mode)
-    except OSError, e:
-        raise wrap_oserror(space, e)
+    res = rposix.c_fchmod(fd, mode)
+    if res == -1:
+        raise oserror_from_errno(space)
 
 def rename(space, w_old, w_new):
     "Rename a file or directory."
@@ -1153,10 +1156,9 @@
     fd = space.c_filedescriptor_w(w_fd)
     check_uid_range(space, uid)
     check_uid_range(space, gid)
-    try:
-        os.fchown(fd, uid, gid)
-    except OSError, e:
-        raise wrap_oserror(space, e)
+    res = rposix.c_fchown(fd, uid, gid)
+    if res == -1:
+        raise oserror_from_errno(space)
 
 def getloadavg(space):
     try:
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -6,6 +6,7 @@
 from rpython.tool.udir import udir
 from pypy.tool.pytest.objspace import gettestobjspace
 from pypy.conftest import pypydir
+from rpython.rlib import rposix
 from rpython.rtyper.module.ll_os import RegisterOs
 from rpython.translator.c.test.test_extfunc import need_sparse_files
 import os
@@ -833,7 +834,7 @@
             os.symlink('foobar', self.path)
             os.lchown(self.path, os.getuid(), os.getgid())
 
-    if hasattr(os, 'fchown'):
+    if rposix.HAS_FCHOWN:
         def test_fchown(self):
             os = self.posix
             f = open(self.path, "w")
@@ -856,7 +857,7 @@
                 os.chmod(self.path, 0200)
                 assert (os.stat(self.path).st_mode & 0777) == 0200
 
-    if hasattr(os, 'fchmod'):
+    if rposix.HAS_FCHMOD:
         def test_fchmod(self):
             os = self.posix
             f = open(self.path, "w")
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1,6 +1,7 @@
 import os
 from rpython.rtyper.lltypesystem.rffi import CConstant, CExternVariable, INT
 from rpython.rtyper.lltypesystem import ll2ctypes, rffi
+from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib.objectmodel import specialize
@@ -83,14 +84,23 @@
 else:
     separate_module_sources = []
     export_symbols = []
-    includes=['errno.h','stdio.h']
-errno_eci = ExternalCompilationInfo(
+    includes=['errno.h', 'stdio.h', 'unistd.h', 'sys/stat.h']
+rposix_eci = ExternalCompilationInfo(
     includes=includes,
     separate_module_sources=separate_module_sources,
     export_symbols=export_symbols,
 )
 
-_get_errno, _set_errno = CExternVariable(INT, 'errno', errno_eci,
+class CConfig:
+    _compilation_info_ = rposix_eci
+
+    HAS_FCHMOD = rffi_platform.Has("fchmod")
+    HAS_FCHOWN = rffi_platform.Has("fchown")
+
+globals().update(rffi_platform.configure(CConfig))
+
+
+_get_errno, _set_errno = CExternVariable(INT, 'errno', rposix_eci,
                                          CConstantErrno, sandboxsafe=True,
                                          _nowrapper=True, c_type='int')
 # the default wrapper for set_errno is not suitable for use in critical places
@@ -105,7 +115,7 @@
 if os.name == 'nt':
     is_valid_fd = rffi.llexternal(
         "_PyVerify_fd", [rffi.INT], rffi.INT,
-        compilation_info=errno_eci,
+        compilation_info=rposix_eci,
         )
     @jit.dont_look_inside
     def validate_fd(fd):
@@ -127,6 +137,15 @@
         except OSError:
             pass
 
+# Expose posix functions
+def external(name, args, result):
+    return rffi.llexternal(name, args, result,
+                           compilation_info=CConfig._compilation_info_)
+
+c_fchmod = external('fchmod', [rffi.INT, rffi.MODE_T], rffi.INT)
+c_fchown = external('fchown', [rffi.INT, rffi.INT, rffi.INT], rffi.INT)
+
+
 #___________________________________________________________________
 # Wrappers around posix functions, that accept either strings, or
 # instances with a "as_bytes()" method.


More information about the pypy-commit mailing list