diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-03-08 01:59:09 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-03-08 01:59:09 (GMT) |
commit | 35a97c0bed8af6cab7ea0fffe374c3369561c444 (patch) | |
tree | 669a8ebf7cce2246560484ae433e070e83b9b53d | |
parent | 6036e4431dbc45952550c2b730fc0d1c82e30883 (diff) | |
download | cpython-35a97c0bed8af6cab7ea0fffe374c3369561c444.zip cpython-35a97c0bed8af6cab7ea0fffe374c3369561c444.tar.gz cpython-35a97c0bed8af6cab7ea0fffe374c3369561c444.tar.bz2 |
Issue #22524: Fix os.scandir() for platforms which don't have a d_type field in
the dirent structure (ex: OpenIndiana).
-rw-r--r-- | Modules/posixmodule.c | 38 | ||||
-rwxr-xr-x | configure | 32 | ||||
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | pyconfig.h.in | 3 |
4 files changed, 82 insertions, 11 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c00113e..e47bd84 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -16364,7 +16364,9 @@ typedef struct { __int64 win32_file_index; int got_file_index; #else /* POSIX */ +#ifdef HAVE_DIRENT_D_TYPE unsigned char d_type; +#endif ino_t d_ino; #endif } DirEntry; @@ -16389,11 +16391,15 @@ DirEntry_is_symlink(DirEntry *self) { #ifdef MS_WINDOWS return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; -#else /* POSIX */ +#elif defined(HAVE_DIRENT_D_TYPE) + /* POSIX */ if (self->d_type != DT_UNKNOWN) return self->d_type == DT_LNK; else return DirEntry_test_mode(self, 0, S_IFLNK); +#else + /* POSIX without d_type */ + return DirEntry_test_mode(self, 0, S_IFLNK); #endif } @@ -16505,22 +16511,26 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits PyObject *st_mode = NULL; long mode; int result; +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) int is_symlink; int need_stat; - _Py_IDENTIFIER(st_mode); +#endif #ifdef MS_WINDOWS unsigned long dir_bits; #endif + _Py_IDENTIFIER(st_mode); #ifdef MS_WINDOWS is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; need_stat = follow_symlinks && is_symlink; -#else /* POSIX */ +#elif defined(HAVE_DIRENT_D_TYPE) is_symlink = self->d_type == DT_LNK; need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink); #endif +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) if (need_stat) { +#endif stat = DirEntry_get_stat(self, follow_symlinks); if (!stat) { if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { @@ -16541,6 +16551,7 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits Py_CLEAR(st_mode); Py_CLEAR(stat); result = (mode & S_IFMT) == mode_bits; +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) } else if (is_symlink) { assert(mode_bits != S_IFLNK); @@ -16561,6 +16572,7 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits result = self->d_type == DT_REG; #endif } +#endif return result; @@ -16812,7 +16824,11 @@ join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len) static PyObject * DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len, - unsigned char d_type, ino_t d_ino) + ino_t d_ino +#ifdef HAVE_DIRENT_D_TYPE + , unsigned char d_type +#endif + ) { DirEntry *entry; char *joined_path; @@ -16841,7 +16857,9 @@ DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len, if (!entry->name || !entry->path) goto error; +#ifdef HAVE_DIRENT_D_TYPE entry->d_type = d_type; +#endif entry->d_ino = d_ino; return (PyObject *)entry; @@ -16941,7 +16959,6 @@ ScandirIterator_iternext(ScandirIterator *iterator) struct dirent *direntp; Py_ssize_t name_len; int is_dot; - unsigned char d_type; /* Happens if the iterator is iterated twice */ if (!iterator->dirp) { @@ -16967,13 +16984,12 @@ ScandirIterator_iternext(ScandirIterator *iterator) is_dot = direntp->d_name[0] == '.' && (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2)); if (!is_dot) { -#if defined(__GLIBC__) && !defined(_DIRENT_HAVE_D_TYPE) - d_type = DT_UNKNOWN; /* System doesn't support d_type */ -#else - d_type = direntp->d_type; -#endif return DirEntry_from_posix_info(&iterator->path, direntp->d_name, - name_len, d_type, direntp->d_ino); + name_len, direntp->d_ino +#ifdef HAVE_DIRENT_D_TYPE + , direntp->d_type +#endif + ); } /* Loop till we get a non-dot directory or finish iterating */ @@ -15798,6 +15798,38 @@ esac $as_echo "$ENSUREPIP" >&6; } +# check if the dirent structure of a d_type field and DT_UNKNOWN is defined +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the dirent structure of a d_type field" >&5 +$as_echo_n "checking if the dirent structure of a d_type field... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include <dirent.h> + + int main() { + struct dirent entry; + return entry.d_type == DT_UNKNOWN; + } + + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + have_dirent_d_type=yes +else + have_dirent_d_type=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_dirent_d_type" >&5 +$as_echo "$have_dirent_d_type" >&6; } + +if test "$have_dirent_d_type" = yes; then + +$as_echo "#define HAVE_DIRENT_D_TYPE 1" >>confdefs.h + +fi + # generate output files ac_config_files="$ac_config_files Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh" diff --git a/configure.ac b/configure.ac index a2c5eb4..263ae15 100644 --- a/configure.ac +++ b/configure.ac @@ -4944,6 +4944,26 @@ AS_CASE($with_ensurepip, AC_MSG_RESULT($ENSUREPIP) AC_SUBST(ENSUREPIP) +# check if the dirent structure of a d_type field and DT_UNKNOWN is defined +AC_MSG_CHECKING(if the dirent structure of a d_type field) +AC_LINK_IFELSE( +[ + AC_LANG_SOURCE([[ + #include <dirent.h> + + int main() { + struct dirent entry; + return entry.d_type == DT_UNKNOWN; + } + ]]) +],[have_dirent_d_type=yes],[have_dirent_d_type=no]) +AC_MSG_RESULT($have_dirent_d_type) + +if test "$have_dirent_d_type" = yes; then + AC_DEFINE(HAVE_DIRENT_D_TYPE, 1, + [Define to 1 if the dirent structure has a d_type field]) +fi + # generate output files AC_CONFIG_FILES(Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh) AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 507a7ab..10426c7 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -183,6 +183,9 @@ /* Define to 1 if you have the <direct.h> header file. */ #undef HAVE_DIRECT_H +/* Define to 1 if the dirent structure has a d_type field */ +#undef HAVE_DIRENT_D_TYPE + /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H |