[pypy-commit] pypy follow_symlinks: hg merge rposix-for-3

rlamy pypy.commits at gmail.com
Fri Apr 1 15:36:42 EDT 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: follow_symlinks
Changeset: r83503:1ca73c09051e
Date: 2016-03-31 21:08 +0100
http://bitbucket.org/pypy/pypy/changeset/1ca73c09051e/

Log:	hg merge rposix-for-3

diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -603,14 +603,44 @@
     config = rffi_platform.configure(CConfig)
     DIRENT = config['DIRENT']
     DIRENTP = lltype.Ptr(DIRENT)
-    c_opendir = external('opendir', [rffi.CCHARP], DIRP,
-                         save_err=rffi.RFFI_SAVE_ERRNO)
+    c_opendir = external('opendir',
+        [rffi.CCHARP], DIRP, save_err=rffi.RFFI_SAVE_ERRNO)
+    c_fdopendir = external('fdopendir',
+        [rffi.INT], DIRP, save_err=rffi.RFFI_SAVE_ERRNO)
     # XXX macro=True is hack to make sure we get the correct kind of
     # dirent struct (which depends on defines)
     c_readdir = external('readdir', [DIRP], DIRENTP,
                          macro=True, save_err=rffi.RFFI_FULL_ERRNO_ZERO)
     c_closedir = external('closedir', [DIRP], rffi.INT)
 
+def _listdir(dirp):
+    result = []
+    while True:
+        direntp = c_readdir(dirp)
+        if not direntp:
+            error = get_saved_errno()
+            break
+        namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
+        name = rffi.charp2str(namep)
+        if name != '.' and name != '..':
+            result.append(name)
+    c_closedir(dirp)
+    if error:
+        raise OSError(error, "readdir failed")
+    return result
+
+def fdlistdir(dirfd):
+    """
+    Like listdir(), except that the directory is specified as an open
+    file descriptor.
+
+    Note: fdlistdir() closes the file descriptor.
+    """
+    dirp = c_fdopendir(dirfd)
+    if not dirp:
+        raise OSError(get_saved_errno(), "opendir failed")
+    return _listdir(dirp)
+
 @replace_os_function('listdir')
 @specialize.argtype(0)
 def listdir(path):
@@ -619,20 +649,7 @@
         dirp = c_opendir(path)
         if not dirp:
             raise OSError(get_saved_errno(), "opendir failed")
-        result = []
-        while True:
-            direntp = c_readdir(dirp)
-            if not direntp:
-                error = get_saved_errno()
-                break
-            namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
-            name = rffi.charp2str(namep)
-            if name != '.' and name != '..':
-                result.append(name)
-        c_closedir(dirp)
-        if error:
-            raise OSError(error, "readdir failed")
-        return result
+        return _listdir(dirp)
     else:  # _WIN32 case
         traits = _preferred_traits(path)
         win32traits = make_win32_traits(traits)
@@ -1801,6 +1818,26 @@
         error = c_fchownat(dir_fd, path, owner, group, flag)
         handle_posix_error('fchownat', error)
 
+if HAVE_FEXECVE:
+    c_fexecve = external('fexecve',
+        [rffi.INT, rffi.CCHARPP, rffi.CCHARPP], rffi.INT,
+        save_err=rffi.RFFI_SAVE_ERRNO)
+
+    def fexecve(fd, args, env):
+        envstrs = []
+        for item in env.iteritems():
+            envstr = "%s=%s" % item
+            envstrs.append(envstr)
+
+        # This list conversion already takes care of NUL bytes.
+        l_args = rffi.ll_liststr2charpp(args)
+        l_env = rffi.ll_liststr2charpp(envstrs)
+        c_fexecve(fd, l_args, l_env)
+
+        rffi.free_charpp(l_env)
+        rffi.free_charpp(l_args)
+        raise OSError(get_saved_errno(), "execve failed")
+
 if HAVE_LINKAT:
     c_linkat = external('linkat',
         [rffi.INT, rffi.CCHARP, rffi.INT, rffi.CCHARP, rffi.INT], rffi.INT)
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
--- a/rpython/rlib/test/test_rposix.py
+++ b/rpython/rlib/test/test_rposix.py
@@ -11,6 +11,8 @@
     return py.test.mark.skipif(not hasattr(rposix, funcname),
         reason="Requires rposix.%s()" % funcname)
 
+win_only = py.test.mark.skipif("os.name != 'nt'")
+
 class TestPosixFunction:
     def test_access(self):
         filename = str(udir.join('test_access.txt'))
@@ -33,9 +35,8 @@
         for value in times:
             assert isinstance(value, float)
 
+    @py.test.mark.skipif("not hasattr(os, 'getlogin')")
     def test_getlogin(self):
-        if not hasattr(os, 'getlogin'):
-            py.test.skip('posix specific function')
         try:
             expected = os.getlogin()
         except OSError, e:
@@ -43,9 +44,8 @@
         data = rposix.getlogin()
         assert data == expected
 
+    @win_only
     def test_utimes(self):
-        if os.name != 'nt':
-            py.test.skip('Windows specific feature')
         # Windows support centiseconds
         def f(fname, t1):
             os.utime(fname, (t1, t1))
@@ -55,15 +55,12 @@
         t1 = 1159195039.25
         compile(f, (str, float))(str(fname), t1)
         assert t1 == os.stat(str(fname)).st_mtime
-        if sys.version_info < (2, 7):
-            py.test.skip('requires Python 2.7')
         t1 = 5000000000.0
         compile(f, (str, float))(str(fname), t1)
         assert t1 == os.stat(str(fname)).st_mtime
 
+    @win_only
     def test__getfullpathname(self):
-        if os.name != 'nt':
-            py.test.skip('nt specific function')
         posix = __import__(os.name)
         sysdrv = os.getenv('SystemDrive', 'C:')
         stuff = sysdrv + 'stuff'
@@ -134,10 +131,8 @@
         os.unlink(filename)
 
 
+    @py.test.mark.skipif("os.name != 'posix'")
     def test_execve(self):
-        if os.name != 'posix':
-            py.test.skip('posix specific function')
-
         EXECVE_ENV = {"foo": "bar", "baz": "quux"}
 
         def run_execve(program, args=None, env=None, do_path_lookup=False):
@@ -276,11 +271,8 @@
         assert rposix.isatty(-1) is False
 
 
+ at py.test.mark.skipif("not hasattr(os, 'ttyname')")
 class TestOsExpect(ExpectTest):
-    def setup_class(cls):
-        if not hasattr(os, 'ttyname'):
-            py.test.skip("no ttyname")
-
     def test_ttyname(self):
         def f():
             import os
@@ -444,9 +436,8 @@
             except Exception:
                 pass
 
+    @win_only
     def test_is_valid_fd(self):
-        if os.name != 'nt':
-            py.test.skip('relevant for windows only')
         assert rposix.is_valid_fd(0) == 1
         fid = open(str(udir.join('validate_test.txt')), 'w')
         fd = fid.fileno()
@@ -537,6 +528,14 @@
             os.open(u'/tmp/t', 0, 0)
         compile(f, ())
 
+
+def test_fdlistdir(tmpdir):
+    tmpdir.join('file').write('text')
+    dirfd = os.open(str(tmpdir), os.O_RDONLY)
+    result = rposix.fdlistdir(dirfd)
+    # Note: fdlistdir() always closes dirfd
+    assert result == ['file']
+
 def test_symlinkat(tmpdir):
     tmpdir.join('file').write('text')
     dirfd = os.open(str(tmpdir), os.O_RDONLY)
@@ -546,7 +545,6 @@
     finally:
         os.close(dirfd)
 
-
 def test_renameat(tmpdir):
     tmpdir.join('file').write('text')
     dirfd = os.open(str(tmpdir), os.O_RDONLY)


More information about the pypy-commit mailing list