glob_wrapper.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Marcus Boerger <helly@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "php_streams_int.h"
  20. #ifdef HAVE_GLOB
  21. # ifndef PHP_WIN32
  22. # include <glob.h>
  23. # else
  24. # include "win32/glob.h"
  25. # endif
  26. #endif
  27. #ifdef HAVE_GLOB
  28. #ifndef GLOB_ONLYDIR
  29. #define GLOB_ONLYDIR (1<<30)
  30. #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
  31. #else
  32. #define GLOB_FLAGMASK (~0)
  33. #endif
  34. typedef struct {
  35. glob_t glob;
  36. size_t index;
  37. int flags;
  38. char *path;
  39. size_t path_len;
  40. char *pattern;
  41. size_t pattern_len;
  42. } glob_s_t;
  43. PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, size_t *plen STREAMS_DC) /* {{{ */
  44. {
  45. glob_s_t *pglob = (glob_s_t *)stream->abstract;
  46. if (pglob && pglob->path) {
  47. if (plen) {
  48. *plen = pglob->path_len;
  49. }
  50. if (copy) {
  51. return estrndup(pglob->path, pglob->path_len);
  52. } else {
  53. return pglob->path;
  54. }
  55. } else {
  56. if (plen) {
  57. *plen = 0;
  58. }
  59. return NULL;
  60. }
  61. }
  62. /* }}} */
  63. PHPAPI char* _php_glob_stream_get_pattern(php_stream *stream, int copy, size_t *plen STREAMS_DC) /* {{{ */
  64. {
  65. glob_s_t *pglob = (glob_s_t *)stream->abstract;
  66. if (pglob && pglob->pattern) {
  67. if (plen) {
  68. *plen = pglob->pattern_len;
  69. }
  70. if (copy) {
  71. return estrndup(pglob->pattern, pglob->pattern_len);
  72. } else {
  73. return pglob->pattern;
  74. }
  75. } else {
  76. if (plen) {
  77. *plen = 0;
  78. }
  79. return NULL;
  80. }
  81. }
  82. /* }}} */
  83. PHPAPI int _php_glob_stream_get_count(php_stream *stream, int *pflags STREAMS_DC) /* {{{ */
  84. {
  85. glob_s_t *pglob = (glob_s_t *)stream->abstract;
  86. if (pglob) {
  87. if (pflags) {
  88. *pflags = pglob->flags;
  89. }
  90. return pglob->glob.gl_pathc;
  91. } else {
  92. if (pflags) {
  93. *pflags = 0;
  94. }
  95. return 0;
  96. }
  97. }
  98. /* }}} */
  99. static void php_glob_stream_path_split(glob_s_t *pglob, const char *path, int get_path, const char **p_file) /* {{{ */
  100. {
  101. const char *pos, *gpath = path;
  102. if ((pos = strrchr(path, '/')) != NULL) {
  103. path = pos+1;
  104. }
  105. #ifdef PHP_WIN32
  106. if ((pos = strrchr(path, '\\')) != NULL) {
  107. path = pos+1;
  108. }
  109. #endif
  110. *p_file = path;
  111. if (get_path) {
  112. if (pglob->path) {
  113. efree(pglob->path);
  114. }
  115. if ((path - gpath) > 1) {
  116. path--;
  117. }
  118. pglob->path_len = path - gpath;
  119. pglob->path = estrndup(gpath, pglob->path_len);
  120. }
  121. }
  122. /* }}} */
  123. static size_t php_glob_stream_read(php_stream *stream, char *buf, size_t count) /* {{{ */
  124. {
  125. glob_s_t *pglob = (glob_s_t *)stream->abstract;
  126. php_stream_dirent *ent = (php_stream_dirent*)buf;
  127. const char *path;
  128. /* avoid problems if someone mis-uses the stream */
  129. if (count == sizeof(php_stream_dirent) && pglob) {
  130. if (pglob->index < (size_t)pglob->glob.gl_pathc) {
  131. php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index++], pglob->flags & GLOB_APPEND, &path);
  132. PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
  133. return sizeof(php_stream_dirent);
  134. }
  135. pglob->index = pglob->glob.gl_pathc;
  136. if (pglob->path) {
  137. efree(pglob->path);
  138. pglob->path = NULL;
  139. }
  140. }
  141. return 0;
  142. }
  143. /* }}} */
  144. static int php_glob_stream_close(php_stream *stream, int close_handle) /* {{{ */
  145. {
  146. glob_s_t *pglob = (glob_s_t *)stream->abstract;
  147. if (pglob) {
  148. pglob->index = 0;
  149. globfree(&pglob->glob);
  150. if (pglob->path) {
  151. efree(pglob->path);
  152. }
  153. if (pglob->pattern) {
  154. efree(pglob->pattern);
  155. }
  156. }
  157. efree(stream->abstract);
  158. return 0;
  159. }
  160. /* {{{ */
  161. static int php_glob_stream_rewind(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) /* {{{ */
  162. {
  163. glob_s_t *pglob = (glob_s_t *)stream->abstract;
  164. if (pglob) {
  165. pglob->index = 0;
  166. if (pglob->path) {
  167. efree(pglob->path);
  168. pglob->path = NULL;
  169. }
  170. }
  171. return 0;
  172. }
  173. /* }}} */
  174. const php_stream_ops php_glob_stream_ops = {
  175. NULL, php_glob_stream_read,
  176. php_glob_stream_close, NULL,
  177. "glob",
  178. php_glob_stream_rewind,
  179. NULL, /* cast */
  180. NULL, /* stat */
  181. NULL /* set_option */
  182. };
  183. /* {{{ php_glob_stream_opener */
  184. static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, const char *path, const char *mode,
  185. int options, zend_string **opened_path, php_stream_context *context STREAMS_DC)
  186. {
  187. glob_s_t *pglob;
  188. int ret;
  189. const char *tmp, *pos;
  190. if (!strncmp(path, "glob://", sizeof("glob://")-1)) {
  191. path += sizeof("glob://")-1;
  192. if (opened_path) {
  193. *opened_path = zend_string_init(path, strlen(path), 0);
  194. }
  195. }
  196. if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path)) {
  197. return NULL;
  198. }
  199. pglob = ecalloc(sizeof(*pglob), 1);
  200. if (0 != (ret = glob(path, pglob->flags & GLOB_FLAGMASK, NULL, &pglob->glob))) {
  201. #ifdef GLOB_NOMATCH
  202. if (GLOB_NOMATCH != ret)
  203. #endif
  204. {
  205. efree(pglob);
  206. return NULL;
  207. }
  208. }
  209. pos = path;
  210. if ((tmp = strrchr(pos, '/')) != NULL) {
  211. pos = tmp+1;
  212. }
  213. #ifdef PHP_WIN32
  214. if ((tmp = strrchr(pos, '\\')) != NULL) {
  215. pos = tmp+1;
  216. }
  217. #endif
  218. pglob->pattern_len = strlen(pos);
  219. pglob->pattern = estrndup(pos, pglob->pattern_len);
  220. pglob->flags |= GLOB_APPEND;
  221. if (pglob->glob.gl_pathc) {
  222. php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[0], 1, &tmp);
  223. } else {
  224. php_glob_stream_path_split(pglob, path, 1, &tmp);
  225. }
  226. return php_stream_alloc(&php_glob_stream_ops, pglob, 0, mode);
  227. }
  228. /* }}} */
  229. static const php_stream_wrapper_ops php_glob_stream_wrapper_ops = {
  230. NULL,
  231. NULL,
  232. NULL,
  233. NULL,
  234. php_glob_stream_opener,
  235. "glob",
  236. NULL,
  237. NULL,
  238. NULL,
  239. NULL,
  240. NULL
  241. };
  242. const php_stream_wrapper php_glob_stream_wrapper = {
  243. &php_glob_stream_wrapper_ops,
  244. NULL,
  245. 0
  246. };
  247. #endif /* HAVE_GLOB */
  248. /*
  249. * Local variables:
  250. * tab-width: 4
  251. * c-basic-offset: 4
  252. * End:
  253. * vim600: noet sw=4 ts=4 fdm=marker
  254. * vim<600: noet sw=4 ts=4
  255. */