summaryrefslogtreecommitdiff
path: root/win32/readdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/readdir.c')
-rw-r--r--win32/readdir.c126
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