summaryrefslogtreecommitdiff
path: root/win32/readdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/readdir.c')
-rw-r--r--win32/readdir.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/win32/readdir.c b/win32/readdir.c
new file mode 100644
index 0000000..9525fc0
--- /dev/null
+++ b/win32/readdir.c
@@ -0,0 +1,168 @@
+#include <malloc.h>
+#include <string.h>
+#include <errno.h>
+
+#include "php.h"
+#include "readdir.h"
+#include "TSRM.h"
+/**********************************************************************
+ * Implement dirent-style opendir/readdir/rewinddir/closedir on Win32
+ *
+ * Functions defined are opendir(), readdir(), rewinddir() and
+ * closedir() with the same prototypes as the normal dirent.h
+ * implementation.
+ *
+ * Does not implement telldir(), seekdir(), or scandir(). The dirent
+ * struct is compatible with Unix, except that d_ino is always 1 and
+ * d_off is made up as we go along.
+ *
+ * The DIR typedef is not compatible with Unix.
+ **********************************************************************/
+
+DIR *opendir(const char *dir)
+{
+ DIR *dp;
+ char *filespec;
+ HANDLE handle;
+ int index;
+ char resolved_path_buff[MAXPATHLEN];
+ TSRMLS_FETCH();
+
+ if (!VCWD_REALPATH(dir, resolved_path_buff)) {
+ return NULL;
+ }
+
+ filespec = (char *)malloc(strlen(resolved_path_buff) + 2 + 1);
+ if (filespec == NULL) {
+ return NULL;
+ }
+ strcpy(filespec, resolved_path_buff);
+ index = 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) {
+ return NULL;
+ }
+ dp->offset = 0;
+ dp->finished = 0;
+
+ if ((handle = FindFirstFile(filespec, &(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);
+ return NULL;
+ }
+ }
+ dp->dir = strdup(resolved_path_buff);
+ dp->handle = handle;
+ free(filespec);
+
+ return dp;
+}
+
+struct dirent *readdir(DIR *dp)
+{
+ if (!dp || dp->finished)
+ return NULL;
+
+ if (dp->offset != 0) {
+ if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
+ dp->finished = 1;
+ return NULL;
+ }
+ }
+ dp->offset++;
+
+ strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
+ dp->dent.d_ino = 1;
+ dp->dent.d_reclen = strlen(dp->dent.d_name);
+ dp->dent.d_off = dp->offset;
+
+ return &(dp->dent);
+}
+
+int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result)
+{
+ if (!dp || dp->finished) {
+ *result = NULL;
+ return 0;
+ }
+
+ if (dp->offset != 0) {
+ if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
+ dp->finished = 1;
+ *result = NULL;
+ return 0;
+ }
+ }
+ dp->offset++;
+
+ strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
+ dp->dent.d_ino = 1;
+ dp->dent.d_reclen = strlen(dp->dent.d_name);
+ dp->dent.d_off = dp->offset;
+
+ memcpy(entry, &dp->dent, sizeof(*entry));
+
+ *result = &dp->dent;
+
+ return 0;
+}
+
+int closedir(DIR *dp)
+{
+ if (!dp)
+ return 0;
+ /* It is valid to scan an empty directory but we have an invalid
+ handle in this case (no first file found). */
+ if (dp->handle != INVALID_HANDLE_VALUE) {
+ FindClose(dp->handle);
+ }
+ if (dp->dir)
+ free(dp->dir);
+ if (dp)
+ free(dp);
+
+ return 0;
+}
+
+int rewinddir(DIR *dp)
+{
+ /* Re-set to the beginning */
+ char *filespec;
+ HANDLE handle;
+ int index;
+
+ FindClose(dp->handle);
+
+ dp->offset = 0;
+ dp->finished = 0;
+
+ filespec = (char *)malloc(strlen(dp->dir) + 2 + 1);
+ if (filespec == NULL) {
+ return -1;
+ }
+
+ strcpy(filespec, dp->dir);
+ index = strlen(filespec) - 1;
+ if (index >= 0 && (filespec[index] == '/' ||
+ (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1])))))
+ filespec[index] = '\0';
+ strcat(filespec, "/*");
+
+ if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
+ dp->finished = 1;
+ }
+
+ dp->handle = handle;
+ free(filespec);
+
+ return 0;
+}