diff options
Diffstat (limited to 'win32/readdir.c')
-rw-r--r-- | win32/readdir.c | 126 |
1 files changed, 88 insertions, 38 deletions
diff --git a/win32/readdir.c b/win32/readdir.c index fc2c4357ff..35afea429b 100644 --- a/win32/readdir.c +++ b/win32/readdir.c @@ -4,7 +4,8 @@ #include "php.h" #include "readdir.h" -#include "TSRM.h" +#include "win32/ioutil.h" + /********************************************************************** * Implement dirent-style opendir/readdir/rewinddir/closedir on Win32 * @@ -19,70 +20,104 @@ * The DIR typedef is not compatible with Unix. **********************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* typedef DIR - not the same as Unix */ +struct DIR_W32 { + HANDLE handle; /* _findfirst/_findnext handle */ + int offset; /* offset into directory */ + short finished; /* 1 if there are not more files */ + WIN32_FIND_DATAW fileinfo; /* from _findfirst/_findnext */ + wchar_t *dirw; /* the dir we are reading */ + struct dirent dent; /* the dirent to return */ +}; + DIR *opendir(const char *dir) { DIR *dp; - char *filespec; + wchar_t *filespecw, *resolvedw; HANDLE handle; int index; char resolved_path_buff[MAXPATHLEN]; + size_t resolvedw_len, filespecw_len; if (!VCWD_REALPATH(dir, resolved_path_buff)) { return NULL; } - filespec = (char *)malloc(strlen(resolved_path_buff) + 2 + 1); - if (filespec == NULL) { + dp = (DIR *) malloc(sizeof(DIR)); + if (dp == NULL) { return NULL; } - strcpy(filespec, resolved_path_buff); - index = (int)strlen(filespec) - 1; - if (index >= 0 && (filespec[index] == '/' || - (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1]))))) - filespec[index] = '\0'; - strcat(filespec, "\\*"); - dp = (DIR *) malloc(sizeof(DIR)); - if (dp == NULL) { - free(filespec); + resolvedw = php_win32_ioutil_conv_any_to_w(resolved_path_buff, PHP_WIN32_CP_IGNORE_LEN, &resolvedw_len); + if (!resolvedw) { + return NULL; + } + + filespecw_len = resolvedw_len + 2; + filespecw = (wchar_t *)malloc((filespecw_len + 1)*sizeof(wchar_t)); + if (filespecw == NULL) { + free(resolvedw); return NULL; } - dp->offset = 0; - dp->finished = 0; - if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) { + wcscpy(filespecw, resolvedw); + index = (int)filespecw_len - 1; + if (index >= 0 && filespecw[index] == L'/' || index == 0 && filespecw[index] == L'\\') + filespecw[index] = L'\0'; + wcscat(filespecw, L"\\*"); + + if ((handle = FindFirstFileW(filespecw, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if (err == ERROR_NO_MORE_FILES || err == ERROR_FILE_NOT_FOUND) { dp->finished = 1; } else { free(dp); - free(filespec); + free(filespecw); + free(resolvedw); return NULL; } } - dp->dir = strdup(resolved_path_buff); + dp->dirw = _wcsdup(resolvedw); dp->handle = handle; - free(filespec); + dp->offset = 0; + dp->finished = 0; + + free(filespecw); + free(resolvedw); return dp; } struct dirent *readdir(DIR *dp) { + char *_tmp; + if (!dp || dp->finished) return NULL; if (dp->offset != 0) { - if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) { + if (FindNextFileW(dp->handle, &(dp->fileinfo)) == 0) { dp->finished = 1; return NULL; } } + + _tmp = php_win32_ioutil_w_to_any(dp->fileinfo.cFileName); + if (!_tmp) { + /* wide to utf8 failed, should never happen. */ + return NULL; + } + strlcpy(dp->dent.d_name, _tmp, _MAX_FNAME+1); + dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name); + free(_tmp); + dp->offset++; - strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1); dp->dent.d_ino = 1; - dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name); dp->dent.d_off = dp->offset; return &(dp->dent); @@ -90,23 +125,34 @@ struct dirent *readdir(DIR *dp) int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result) { + char *_tmp; + if (!dp || dp->finished) { *result = NULL; return 0; } if (dp->offset != 0) { - if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) { + if (FindNextFileW(dp->handle, &(dp->fileinfo)) == 0) { dp->finished = 1; *result = NULL; return 0; } } + + _tmp = php_win32_ioutil_w_to_any(dp->fileinfo.cFileName); + if (!_tmp) { + /* wide to utf8 failed, should never happen. */ + result = NULL; + return 0; + } + strlcpy(dp->dent.d_name, _tmp, _MAX_FNAME+1); + dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name); + free(_tmp); + dp->offset++; - strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1); dp->dent.d_ino = 1; - dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name); dp->dent.d_off = dp->offset; memcpy(entry, &dp->dent, sizeof(*entry)); @@ -125,8 +171,8 @@ int closedir(DIR *dp) if (dp->handle != INVALID_HANDLE_VALUE) { FindClose(dp->handle); } - if (dp->dir) - free(dp->dir); + if (dp->dirw) + free(dp->dirw); if (dp) free(dp); @@ -136,7 +182,7 @@ int closedir(DIR *dp) int rewinddir(DIR *dp) { /* Re-set to the beginning */ - char *filespec; + wchar_t *filespecw; HANDLE handle; int index; @@ -145,28 +191,32 @@ int rewinddir(DIR *dp) dp->offset = 0; dp->finished = 0; - filespec = (char *)malloc(strlen(dp->dir) + 2 + 1); - if (filespec == NULL) { + filespecw = (wchar_t *)malloc((wcslen((wchar_t *)dp->dirw) + 2 + 1)*sizeof(wchar_t)); + if (filespecw == NULL) { return -1; } - strcpy(filespec, dp->dir); - index = (int)strlen(filespec) - 1; - if (index >= 0 && (filespec[index] == '/' || - (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1]))))) - filespec[index] = '\0'; - strcat(filespec, "/*"); + wcscpy(filespecw, (wchar_t *)dp->dirw); + index = (int)wcslen(filespecw) - 1; + if (index >= 0 && (filespecw[index] == L'/' || + (filespecw[index] == L'\\' && index == 0))) + filespecw[index] = L'\0'; + wcscat(filespecw, L"/*"); - if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) { + if ((handle = FindFirstFileW(filespecw, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) { dp->finished = 1; } + free(filespecw); dp->handle = handle; - free(filespec); return 0; } +#ifdef __cplusplus +} +#endif + /* * Local variables: * tab-width: 4 |