ruby-changes:19332
From: usa <ko1@a...>
Date: Thu, 28 Apr 2011 16:22:27 +0900 (JST)
Subject: [ruby-changes:19332] Ruby:r31372 (trunk): * win32/{win32.c,dir.h} (rb_w32_uopendir): new API to pass UTF-8 path.
usa 2011-04-28 16:22:18 +0900 (Thu, 28 Apr 2011) New Revision: 31372 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31372 Log: * win32/{win32.c,dir.h} (rb_w32_uopendir): new API to pass UTF-8 path. * win32/win32.c (opendir_internal, rb_w32_opendir): extract and merge common part of rb_w32_opendir() and rb_w32_uopendir(). * dir.c (do_opendir, glob_helper): encoding. * dir.c (dir_initialize, do_opendir): convert path to UTF-8 and call rb_w32_uopendir() instead of rb_w32_opendir() on Windows. fixes #4491, reported by Joey Zhou. Modified files: trunk/ChangeLog trunk/dir.c trunk/win32/dir.h trunk/win32/win32.c Index: ChangeLog =================================================================== --- ChangeLog (revision 31371) +++ ChangeLog (revision 31372) @@ -1,3 +1,16 @@ +Thu Apr 28 16:15:49 2011 NAKAMURA Usaku <usa@r...> + + * win32/{win32.c,dir.h} (rb_w32_uopendir): new API to pass UTF-8 path. + + * win32/win32.c (opendir_internal, rb_w32_opendir): extract and merge + common part of rb_w32_opendir() and rb_w32_uopendir(). + + * dir.c (do_opendir, glob_helper): encoding. + + * dir.c (dir_initialize, do_opendir): convert path to UTF-8 and call + rb_w32_uopendir() instead of rb_w32_opendir() on Windows. + fixes #4491, reported by Joey Zhou. + Thu Apr 28 15:32:53 2011 NAKAMURA Usaku <usa@r...> * test/dl/test_base.rb (DL::LIBC_SO): its always msvc*.dll on Index: dir.c =================================================================== --- dir.c (revision 31371) +++ dir.c (revision 31372) @@ -75,6 +75,8 @@ #define mkdir(p, m) rb_w32_umkdir((p), (m)) #undef rmdir #define rmdir(p) rb_w32_urmdir(p) +#undef opendir +#define opendir(p) rb_w32_uopendir(p) #endif #define FNM_NOESCAPE 0x01 @@ -402,6 +404,7 @@ } GlobPathValue(dirname, FALSE); + dirname = rb_str_encode_ospath(dirname); TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp); if (dp->dir) closedir(dp->dir); @@ -1033,9 +1036,20 @@ } static DIR * -do_opendir(const char *path, int flags) +do_opendir(const char *path, int flags, rb_encoding *enc) { - DIR *dirp = opendir(path); + DIR *dirp; +#ifdef _WIN32 + volatile VALUE tmp; + if (enc != rb_usascii_encoding() && + enc != rb_ascii8bit_encoding() && + enc != rb_utf8_encoding()) { + tmp = rb_enc_str_new(path, strlen(path), enc); + tmp = rb_str_encode_ospath(tmp); + path = RSTRING_PTR(tmp); + } +#endif + dirp = opendir(path); if (dirp == NULL && !to_be_ignored(errno)) sys_warning(path); @@ -1354,7 +1368,7 @@ struct dirent *dp; DIR *dirp; IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry); - dirp = do_opendir(*path ? path : ".", flags); + dirp = do_opendir(*path ? path : ".", flags, enc); if (dirp == NULL) return 0; while (READDIR(dirp, enc, &STRUCT_DIRENT(entry), dp)) { Index: win32/win32.c =================================================================== --- win32/win32.c (revision 31371) +++ win32/win32.c (revision 31372) @@ -1690,14 +1690,30 @@ } static DIR * -opendir_internal(HANDLE fh, WIN32_FIND_DATAW *fd) +opendir_internal(WCHAR *wpath, const char *filename) { + struct stati64 sbuf; + WIN32_FIND_DATAW fd; + HANDLE fh; DIR *p; long len; long idx; WCHAR *tmpW; char *tmp; + // + // check to see if we've got a directory + // + if (wstati64(wpath, &sbuf) < 0) { + return NULL; + } + if (!(sbuf.st_mode & S_IFDIR) && + (!ISALPHA(filename[0]) || filename[1] != ':' || filename[2] != '\0' || + ((1 << ((filename[0] & 0x5f) - 'A')) & GetLogicalDrives()) == 0)) { + errno = ENOTDIR; + return NULL; + } + fh = open_dir_handle(wpath, &fd); if (fh == INVALID_HANDLE_VALUE) { return NULL; } @@ -1718,7 +1734,7 @@ // of the previous string found. // do { - len = lstrlenW(fd->cFileName) + 1; + len = lstrlenW(fd.cFileName) + 1; // // bump the string table size by enough for the @@ -1734,7 +1750,7 @@ } p->start = tmpW; - memcpy(&p->start[idx], fd->cFileName, len * sizeof(WCHAR)); + memcpy(&p->start[idx], fd.cFileName, len * sizeof(WCHAR)); if (p->nfiles % DIRENT_PER_CHAR == 0) { tmp = realloc(p->bits, p->nfiles / DIRENT_PER_CHAR + 1); @@ -1743,14 +1759,14 @@ p->bits = tmp; p->bits[p->nfiles / DIRENT_PER_CHAR] = 0; } - if (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) SetBit(p->bits, BitOfIsDir(p->nfiles)); - if (fd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) SetBit(p->bits, BitOfIsRep(p->nfiles)); p->nfiles++; idx += len; - } while (FindNextFileW(fh, fd)); + } while (FindNextFileW(fh, &fd)); FindClose(fh); p->size = idx; p->curr = p->start; @@ -1789,31 +1805,25 @@ DIR * rb_w32_opendir(const char *filename) { - struct stati64 sbuf; - WIN32_FIND_DATAW fd; - HANDLE fh; - WCHAR *wpath; - - if (!(wpath = filecp_to_wstr(filename, NULL))) + DIR *ret; + WCHAR *wpath = filecp_to_wstr(filename, NULL); + if (!wpath) return NULL; + ret = opendir_internal(wpath, filename); + free(wpath); + return ret; +} - // - // check to see if we've got a directory - // - if (wstati64(wpath, &sbuf) < 0) { - free(wpath); +DIR * +rb_w32_uopendir(const char *filename) +{ + DIR *ret; + WCHAR *wpath = utf8_to_wstr(filename, NULL); + if (!wpath) return NULL; - } - if (!(sbuf.st_mode & S_IFDIR) && - (!ISALPHA(filename[0]) || filename[1] != ':' || filename[2] != '\0' || - ((1 << ((filename[0] & 0x5f) - 'A')) & GetLogicalDrives()) == 0)) { - free(wpath); - errno = ENOTDIR; - return NULL; - } - fh = open_dir_handle(wpath, &fd); + ret = opendir_internal(wpath, filename); free(wpath); - return opendir_internal(fh, &fd); + return ret; } // Index: win32/dir.h =================================================================== --- win32/dir.h (revision 31371) +++ win32/dir.h (revision 31372) @@ -28,6 +28,7 @@ DIR* rb_w32_opendir(const char*); +DIR* rb_w32_uopendir(const char*); struct direct* rb_w32_readdir(DIR *); struct direct* rb_w32_readdir_with_enc(DIR *, rb_encoding *); long rb_w32_telldir(DIR *); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/