Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r86392:43568988afe8
Date: 2016-08-22 10:05 +0200
http://bitbucket.org/pypy/pypy/changeset/43568988afe8/

Log:    Test and fix for rposix.fdopendir()

diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -620,6 +620,8 @@
         [rffi.CCHARP], DIRP, save_err=rffi.RFFI_SAVE_ERRNO)
     c_fdopendir = external('fdopendir',
         [rffi.INT], DIRP, save_err=rffi.RFFI_SAVE_ERRNO)
+    c_rewinddir = external('rewinddir',
+        [DIRP], lltype.Void, releasegil=False)
     # 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,
@@ -629,7 +631,7 @@
 else:
     dirent_config = {}
 
-def _listdir(dirp):
+def _listdir(dirp, rewind=False):
     result = []
     while True:
         direntp = c_readdir(dirp)
@@ -640,6 +642,8 @@
         name = rffi.charp2str(namep)
         if name != '.' and name != '..':
             result.append(name)
+    if rewind:
+        c_rewinddir(dirp)
     c_closedir(dirp)
     if error:
         raise OSError(error, "readdir failed")
@@ -650,12 +654,16 @@
     Like listdir(), except that the directory is specified as an open
     file descriptor.
 
-    Note: fdlistdir() closes the file descriptor.
+    Note: fdlistdir() closes the file descriptor.  To emulate the
+    Python 3.x 'os.opendir(dirfd)', you must first duplicate the
+    file descriptor.
     """
     dirp = c_fdopendir(dirfd)
     if not dirp:
-        raise OSError(get_saved_errno(), "opendir failed")
-    return _listdir(dirp)
+        error = get_saved_errno()
+        c_close(dirfd)
+        raise OSError(error, "opendir failed")
+    return _listdir(dirp, rewind=True)
 
 @replace_os_function('listdir')
 @specialize.argtype(0)
@@ -1799,7 +1807,7 @@
                   'fcntl.h'],
     )
     for _name in """faccessat fchdir fchmod fchmodat fchown fchownat fexecve
-            fdopendir fpathconf fstat fstatat fstatvfs ftruncate
+            fpathconf fstat fstatat fstatvfs ftruncate
             futimens futimes futimesat linkat chflags lchflags lchmod lchown
             lstat lutimes mkdirat mkfifoat mknodat openat readlinkat renameat
             symlinkat unlinkat utimensat""".split():
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
@@ -552,6 +552,14 @@
     # Note: fdlistdir() always closes dirfd
     assert result == ['file']
 
+@rposix_requires('fdlistdir')
+def test_fdlistdir_rewinddir(tmpdir):
+    tmpdir.join('file').write('text')
+    dirfd = os.open(str(tmpdir), os.O_RDONLY)
+    result1 = rposix.fdlistdir(os.dup(dirfd))
+    result2 = rposix.fdlistdir(dirfd)
+    assert result1 == result2 == ['file']
+
 @rposix_requires('symlinkat')
 def test_symlinkat(tmpdir):
     tmpdir.join('file').write('text')
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to