readdir.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include <malloc.h>
  2. #include <string.h>
  3. #include <errno.h>
  4. #include "php.h"
  5. #include "readdir.h"
  6. #include "TSRM.h"
  7. /**********************************************************************
  8. * Implement dirent-style opendir/readdir/rewinddir/closedir on Win32
  9. *
  10. * Functions defined are opendir(), readdir(), rewinddir() and
  11. * closedir() with the same prototypes as the normal dirent.h
  12. * implementation.
  13. *
  14. * Does not implement telldir(), seekdir(), or scandir(). The dirent
  15. * struct is compatible with Unix, except that d_ino is always 1 and
  16. * d_off is made up as we go along.
  17. *
  18. * The DIR typedef is not compatible with Unix.
  19. **********************************************************************/
  20. DIR *opendir(const char *dir)
  21. {
  22. DIR *dp;
  23. char *filespec;
  24. HANDLE handle;
  25. int index;
  26. char resolved_path_buff[MAXPATHLEN];
  27. TSRMLS_FETCH();
  28. if (!VCWD_REALPATH(dir, resolved_path_buff)) {
  29. return NULL;
  30. }
  31. filespec = (char *)malloc(strlen(resolved_path_buff) + 2 + 1);
  32. if (filespec == NULL) {
  33. return NULL;
  34. }
  35. strcpy(filespec, resolved_path_buff);
  36. index = strlen(filespec) - 1;
  37. if (index >= 0 && (filespec[index] == '/' ||
  38. (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1])))))
  39. filespec[index] = '\0';
  40. strcat(filespec, "\\*");
  41. dp = (DIR *) malloc(sizeof(DIR));
  42. if (dp == NULL) {
  43. free(filespec);
  44. return NULL;
  45. }
  46. dp->offset = 0;
  47. dp->finished = 0;
  48. if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
  49. DWORD err = GetLastError();
  50. if (err == ERROR_NO_MORE_FILES || err == ERROR_FILE_NOT_FOUND) {
  51. dp->finished = 1;
  52. } else {
  53. free(dp);
  54. free(filespec);
  55. return NULL;
  56. }
  57. }
  58. dp->dir = strdup(resolved_path_buff);
  59. dp->handle = handle;
  60. free(filespec);
  61. return dp;
  62. }
  63. struct dirent *readdir(DIR *dp)
  64. {
  65. if (!dp || dp->finished)
  66. return NULL;
  67. if (dp->offset != 0) {
  68. if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
  69. dp->finished = 1;
  70. return NULL;
  71. }
  72. }
  73. dp->offset++;
  74. strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
  75. dp->dent.d_ino = 1;
  76. dp->dent.d_reclen = strlen(dp->dent.d_name);
  77. dp->dent.d_off = dp->offset;
  78. return &(dp->dent);
  79. }
  80. int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result)
  81. {
  82. if (!dp || dp->finished) {
  83. *result = NULL;
  84. return 0;
  85. }
  86. if (dp->offset != 0) {
  87. if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
  88. dp->finished = 1;
  89. *result = NULL;
  90. return 0;
  91. }
  92. }
  93. dp->offset++;
  94. strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
  95. dp->dent.d_ino = 1;
  96. dp->dent.d_reclen = strlen(dp->dent.d_name);
  97. dp->dent.d_off = dp->offset;
  98. memcpy(entry, &dp->dent, sizeof(*entry));
  99. *result = &dp->dent;
  100. return 0;
  101. }
  102. int closedir(DIR *dp)
  103. {
  104. if (!dp)
  105. return 0;
  106. /* It is valid to scan an empty directory but we have an invalid
  107. handle in this case (no first file found). */
  108. if (dp->handle != INVALID_HANDLE_VALUE) {
  109. FindClose(dp->handle);
  110. }
  111. if (dp->dir)
  112. free(dp->dir);
  113. if (dp)
  114. free(dp);
  115. return 0;
  116. }
  117. int rewinddir(DIR *dp)
  118. {
  119. /* Re-set to the beginning */
  120. char *filespec;
  121. HANDLE handle;
  122. int index;
  123. FindClose(dp->handle);
  124. dp->offset = 0;
  125. dp->finished = 0;
  126. filespec = (char *)malloc(strlen(dp->dir) + 2 + 1);
  127. if (filespec == NULL) {
  128. return -1;
  129. }
  130. strcpy(filespec, dp->dir);
  131. index = strlen(filespec) - 1;
  132. if (index >= 0 && (filespec[index] == '/' ||
  133. (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1])))))
  134. filespec[index] = '\0';
  135. strcat(filespec, "/*");
  136. if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
  137. dp->finished = 1;
  138. }
  139. dp->handle = handle;
  140. free(filespec);
  141. return 0;
  142. }