diff --git a/ChangeLog b/ChangeLog index 1632f1edcd..55f0dcb426 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Thu Aug 20 01:06:48 2009 Yukihiro Matsumoto + + * dir.c (DEFINE_STRUCT_DIRENT): use union to allocate sufficient + memory space for Solaris. a patch from Naohisa GOTO + in [ruby-dev:39132]. + [ruby-dev:39062] + + * configure.in (SIZEOF_STRUCT_DIRENT_TOO_SMALL): Solaris dirent + check. + Wed Aug 19 11:32:43 2009 Nobuyoshi Nakada * enc/unicode.c (CodeRanges): initialized statically. diff --git a/configure.in b/configure.in index f881cd82f1..1e32b7db9c 100644 --- a/configure.in +++ b/configure.in @@ -750,6 +750,10 @@ when(*) esac case "$target_os" in +when(solaris*) + AC_DEFINE(SIZEOF_STRUCT_DIRENT_TOO_SMALL, 1) + LIBS="-lm $LIBS" + ;; when(nextstep*) ;; when(openstep*) ;; when(rhapsody*) ;; diff --git a/dir.c b/dir.c index c97c702dac..8d3c57f0f3 100644 --- a/dir.c +++ b/dir.c @@ -491,6 +491,39 @@ dir_path(VALUE dir) # define IF_HAVE_READDIR_R(something) /* nothing */ #endif +#if defined SIZEOF_STRUCT_DIRENT_TOO_SMALL +# include +# define NAME_MAX_FOR_STRUCT_DIRENT 255 +# if defined NAME_MAX +# if NAME_MAX_FOR_STRUCT_DIRENT < NAME_MAX +# undef NAME_MAX_FOR_STRUCT_DIRENT +# define NAME_MAX_FOR_STRUCT_DIRENT NAME_MAX +# endif +# endif +# if defined _POSIX_NAME_MAX +# if NAME_MAX_FOR_STRUCT_DIRENT < _POSIX_NAME_MAX +# undef NAME_MAX_FOR_STRUCT_DIRENT +# define NAME_MAX_FOR_STRUCT_DIRENT _POSIX_NAME_MAX +# endif +# endif +# if defined _XOPEN_NAME_MAX +# if NAME_MAX_FOR_STRUCT_DIRENT < _XOPEN_NAME_MAX +# undef NAME_MAX_FOR_STRUCT_DIRENT +# define NAME_MAX_FOR_STRUCT_DIRENT _XOPEN_NAME_MAX +# endif +# endif +# define DEFINE_STRUCT_DIRENT \ + union { \ + struct dirent dirent; \ + char dummy[offsetof(struct dirent, d_name) + \ + NAME_MAX_FOR_STRUCT_DIRENT + 1]; \ + } +# define STRUCT_DIRENT(entry) ((entry).dirent) +#else +# define DEFINE_STRUCT_DIRENT struct dirent +# define STRUCT_DIRENT(entry) (entry) +#endif + /* * call-seq: * dir.read => string or nil @@ -508,11 +541,11 @@ dir_read(VALUE dir) { struct dir_data *dirp; struct dirent *dp; - IF_HAVE_READDIR_R(struct dirent entry); + IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry); GetDIR(dir, dirp); errno = 0; - if (READDIR(dirp->dir, dirp->enc, &entry, dp)) { + if (READDIR(dirp->dir, dirp->enc, &STRUCT_DIRENT(entry), dp)) { return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc); } else if (errno == 0) { /* end of stream */ @@ -546,12 +579,12 @@ dir_each(VALUE dir) { struct dir_data *dirp; struct dirent *dp; - IF_HAVE_READDIR_R(struct dirent entry); + IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry); RETURN_ENUMERATOR(dir, 0, 0); GetDIR(dir, dirp); rewinddir(dirp->dir); - while (READDIR(dirp->dir, dirp->enc, &entry, dp)) { + while (READDIR(dirp->dir, dirp->enc, &STRUCT_DIRENT(entry), dp)) { rb_yield(rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc)); if (dirp->dir == NULL) dir_closed(); } @@ -1270,11 +1303,11 @@ glob_helper( if (magical || recursive) { struct dirent *dp; DIR *dirp; - IF_HAVE_READDIR_R(struct dirent entry); + IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry); dirp = do_opendir(*path ? path : ".", flags); if (dirp == NULL) return 0; - while (READDIR(dirp, enc, &entry, dp)) { + while (READDIR(dirp, enc, &STRUCT_DIRENT(entry), dp)) { char *buf = join_path(path, dirsep, dp->d_name); enum answer new_isdir = UNKNOWN;