Author: Ronan Lamy <[email protected]>
Branch: rposix-for-3
Changeset: r83471:42e156eb8e2c
Date: 2016-03-31 18:12 +0100
http://bitbucket.org/pypy/pypy/changeset/42e156eb8e2c/
Log: Add rposix.fdlistdir(): variant of rposix.listdir() using
fdopendir()
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)
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
@@ -528,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)
@@ -537,7 +545,6 @@
finally:
os.close(dirfd)
-
def test_renameat(tmpdir):
tmpdir.join('file').write('text')
dirfd = os.open(str(tmpdir), os.O_RDONLY)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit