Index: configure =================================================================== --- configure (revision 87436) +++ configure (working copy) @@ -9240,7 +9240,7 @@ # checks for library functions for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ - clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ + clock confstr ctermid execv fchmod fchown fdopendir fork fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ initgroups kill killpg lchmod lchown lstat mbrtowc mkfifo mknod mktime \ Index: configure.in =================================================================== --- configure.in (revision 87436) +++ configure.in (working copy) @@ -2525,7 +2525,7 @@ # checks for library functions AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ - clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ + clock confstr ctermid execv fchmod fchown fdopendir fork fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ initgroups kill killpg lchmod lchown lstat mbrtowc mkfifo mknod mktime \ Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 87436) +++ Misc/NEWS (working copy) @@ -2,6 +2,8 @@ Python News +++++++++++ +- Issue #XXXXX: Add the function posix.fdlistdir. Patch by Ross Lagerwall. + What's New in Python 3.2 Release Candidate 1 ============================================ Index: Doc/library/os.rst =================================================================== --- Doc/library/os.rst (revision 87436) +++ Doc/library/os.rst (working copy) @@ -637,6 +637,15 @@ This function is not available on MacOS. +.. function:: fdlistdir(fd) + + Like :func:`listdir`, but uses a file descriptor instead and always returns + byte strings. + After execution of this function, *fd* will be closed. + + Availability: Unix. + + .. function:: fpathconf(fd, name) Return system configuration information relevant to an open file. *name* Index: Lib/test/test_posix.py =================================================================== --- Lib/test/test_posix.py (revision 87436) +++ Lib/test/test_posix.py (working copy) @@ -285,6 +285,11 @@ if hasattr(posix, 'listdir'): self.assertTrue(support.TESTFN in posix.listdir()) + @unittest.skipUnless(hasattr(posix, 'fdlistdir'), "test needs posix.fdlistdir()") + def test_fdlistdir(self): + self.assertEqual(posix.listdir(b'.'), + posix.fdlistdir(posix.open(posix.getcwd(), posix.O_RDONLY))) + def test_access(self): if hasattr(posix, 'access'): self.assertTrue(posix.access(support.TESTFN, os.R_OK)) Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 87436) +++ Modules/posixmodule.c (working copy) @@ -2648,6 +2648,76 @@ #endif /* which OS */ } /* end of posix_listdir */ +#ifdef HAVE_FDOPENDIR +PyDoc_STRVAR(posix_fdlistdir__doc__, +"fdlistdir(fd) -> list_of_byte_strings\n\n\ +Like listdir(), but uses a file descriptor instead.\n\ +After execution of this function, fd will be closed."); + +static PyObject * +posix_fdlistdir(PyObject *self, PyObject *args) +{ + PyObject *d, *v; + DIR *dirp; + struct dirent *ep; + int fd; + + errno = 0; + if (!PyArg_ParseTuple(args, "i:fdlistdir", &fd)) + return NULL; + Py_BEGIN_ALLOW_THREADS + dirp = fdopendir(fd); + Py_END_ALLOW_THREADS + if (dirp == NULL) { + close(fd); + return posix_error(); + } + if ((d = PyList_New(0)) == NULL) { + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + return NULL; + } + for (;;) { + errno = 0; + Py_BEGIN_ALLOW_THREADS + ep = readdir(dirp); + Py_END_ALLOW_THREADS + if (ep == NULL) { + if (errno == 0) { + break; + } else { + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + Py_DECREF(d); + return posix_error(); + } + } + if (ep->d_name[0] == '.' && + (NAMLEN(ep) == 1 || + (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) + continue; + v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); + if (v == NULL) { + Py_CLEAR(d); + break; + } + if (PyList_Append(d, v) != 0) { + Py_DECREF(v); + Py_CLEAR(d); + break; + } + Py_DECREF(v); + } + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + + return d; +} +#endif + #ifdef MS_WINDOWS /* A helper function for abspath on win32 */ static PyObject * @@ -7782,6 +7852,9 @@ {"link", posix_link, METH_VARARGS, posix_link__doc__}, #endif /* HAVE_LINK */ {"listdir", posix_listdir, METH_VARARGS, posix_listdir__doc__}, +#ifdef HAVE_FDOPENDIR + {"fdlistdir", posix_fdlistdir, METH_VARARGS, posix_fdlistdir__doc__}, +#endif {"lstat", posix_lstat, METH_VARARGS, posix_lstat__doc__}, {"mkdir", posix_mkdir, METH_VARARGS, posix_mkdir__doc__}, #ifdef HAVE_NICE Index: pyconfig.h.in =================================================================== --- pyconfig.h.in (revision 87436) +++ pyconfig.h.in (working copy) @@ -220,6 +220,9 @@ /* Define if you have the 'fdatasync' function. */ #undef HAVE_FDATASYNC +/* Define to 1 if you have the `fdopendir' function. */ +#undef HAVE_FDOPENDIR + /* Define to 1 if you have the `finite' function. */ #undef HAVE_FINITE @@ -497,6 +500,9 @@ /* Define to 1 if you have the `pause' function. */ #undef HAVE_PAUSE +/* Define if the OS supports pipe2() */ +#undef HAVE_PIPE2 + /* Define to 1 if you have the `plock' function. */ #undef HAVE_PLOCK