summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-03-08 01:59:09 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2015-03-08 01:59:09 (GMT)
commit35a97c0bed8af6cab7ea0fffe374c3369561c444 (patch)
tree669a8ebf7cce2246560484ae433e070e83b9b53d
parent6036e4431dbc45952550c2b730fc0d1c82e30883 (diff)
downloadcpython-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.c38
-rwxr-xr-xconfigure32
-rw-r--r--configure.ac20
-rw-r--r--pyconfig.h.in3
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 */
diff --git a/configure b/configure
index 35a31bb..799c6c4 100755
--- a/configure
+++ b/configure
@@ -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