ioutil.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Anatol Belski <ab@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. /* This file integrates several modified parts from the libuv project, which
  17. * is copyrighted to
  18. *
  19. * Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  20. *
  21. * Permission is hereby granted, free of charge, to any person obtaining a copy
  22. * of this software and associated documentation files (the "Software"), to
  23. * deal in the Software without restriction, including without limitation the
  24. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  25. * sell copies of the Software, and to permit persons to whom the Software is
  26. * furnished to do so, subject to the following conditions:
  27. *
  28. * The above copyright notice and this permission notice shall be included in
  29. * all copies or substantial portions of the Software.
  30. *
  31. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  32. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  33. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  34. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  35. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  36. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  37. * IN THE SOFTWARE.
  38. */
  39. #ifndef PHP_WIN32_IOUTIL_H
  40. #define PHP_WIN32_IOUTIL_H
  41. #include <fcntl.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #include <io.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include "win32/winutil.h"
  48. #include "win32/codepage.h"
  49. #ifdef __cplusplus
  50. extern "C" {
  51. #endif
  52. #ifdef PHP_EXPORTS
  53. # define PW32IO __declspec(dllexport)
  54. #else
  55. # define PW32IO __declspec(dllimport)
  56. #endif
  57. #define PHP_WIN32_IOUTIL_MAXPATHLEN 2048
  58. #if !defined(MAXPATHLEN) || MAXPATHLEN < PHP_WIN32_IOUTIL_MAXPATHLEN
  59. # undef MAXPATHLEN
  60. # define MAXPATHLEN PHP_WIN32_IOUTIL_MAXPATHLEN
  61. #endif
  62. #ifndef mode_t
  63. typedef unsigned short mode_t;
  64. #endif
  65. /* these are not defined in win32 headers */
  66. #ifndef W_OK
  67. #define W_OK 0x02
  68. #endif
  69. #ifndef R_OK
  70. #define R_OK 0x04
  71. #endif
  72. #ifndef X_OK
  73. #define X_OK 0x01
  74. #endif
  75. #ifndef F_OK
  76. #define F_OK 0x00
  77. #endif
  78. /* from ntifs.h */
  79. #ifndef SYMLINK_FLAG_RELATIVE
  80. #define SYMLINK_FLAG_RELATIVE 0x01
  81. #endif
  82. typedef struct {
  83. DWORD access;
  84. DWORD share;
  85. DWORD disposition;
  86. DWORD attributes;
  87. } php_ioutil_open_opts;
  88. typedef enum {
  89. PHP_WIN32_IOUTIL_IS_ASCII,
  90. PHP_WIN32_IOUTIL_IS_ANSI,
  91. PHP_WIN32_IOUTIL_IS_UTF8
  92. } php_win32_ioutil_encoding;
  93. typedef enum {
  94. PHP_WIN32_IOUTIL_NORM_OK,
  95. PHP_WIN32_IOUTIL_NORM_PARTIAL,
  96. PHP_WIN32_IOUTIL_NORM_FAIL,
  97. } php_win32_ioutil_normalization_result;
  98. #define PHP_WIN32_IOUTIL_FW_SLASHW L'/'
  99. #define PHP_WIN32_IOUTIL_FW_SLASH '/'
  100. #define PHP_WIN32_IOUTIL_BW_SLASHW L'\\'
  101. #define PHP_WIN32_IOUTIL_BW_SLASH '\\'
  102. #define PHP_WIN32_IOUTIL_DEFAULT_SLASHW PHP_WIN32_IOUTIL_BW_SLASHW
  103. #define PHP_WIN32_IOUTIL_DEFAULT_SLASH PHP_WIN32_IOUTIL_BW_SLASH
  104. #define PHP_WIN32_IOUTIL_DEFAULT_DIR_SEPARATORW L';'
  105. #define PHP_WIN32_IOUTIL_IS_SLASHW(c) ((c) == PHP_WIN32_IOUTIL_BW_SLASHW || (c) == PHP_WIN32_IOUTIL_FW_SLASHW)
  106. #define PHP_WIN32_IOUTIL_IS_LETTERW(c) (((c) >= L'a' && (c) <= L'z') || ((c) >= L'A' && (c) <= L'Z'))
  107. #define PHP_WIN32_IOUTIL_JUNCTION_PREFIXW L"\\??\\"
  108. #define PHP_WIN32_IOUTIL_JUNCTION_PREFIX_LENW 4
  109. #define PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW L"\\\\?\\"
  110. #define PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW 4
  111. #define PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW L"\\\\?\\UNC\\"
  112. #define PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW 8
  113. #define PHP_WIN32_IOUTIL_IS_LONG_PATHW(pathw, path_lenw) (path_lenw >= PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW \
  114. && 0 == wcsncmp((pathw), PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW))
  115. #define PHP_WIN32_IOUTIL_IS_UNC_PATHW(pathw, path_lenw) (path_lenw >= PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW \
  116. && 0 == wcsncmp((pathw), PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW, PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW))
  117. #define PHP_WIN32_IOUTIL_IS_JUNCTION_PATHW(pathw, path_lenw) (path_lenw >= PHP_WIN32_IOUTIL_JUNCTION_PREFIX_LENW \
  118. && 0 == wcsncmp((pathw), PHP_WIN32_IOUTIL_JUNCTION_PREFIXW, PHP_WIN32_IOUTIL_JUNCTION_PREFIX_LENW))
  119. #define PHP_WIN32_IOUTIL_IS_ABSOLUTEW(pathw, path_lenw) (PHP_WIN32_IOUTIL_IS_LONG_PATHW(pathw, path_lenw) \
  120. || path_lenw >= 3 && PHP_WIN32_IOUTIL_IS_LETTERW(pathw[0]) && L':' == pathw[1] && PHP_WIN32_IOUTIL_IS_SLASHW(pathw[2]))
  121. #define PHP_WIN32_IOUTIL_IS_UNC(pathw, path_lenw) (path_lenw >= 2 && PHP_WIN32_IOUTIL_IS_SLASHW(pathw[0]) && PHP_WIN32_IOUTIL_IS_SLASHW(pathw[1]) \
  122. || path_lenw >= PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW && 0 == wcsncmp((pathw), PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW, PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW))
  123. #define PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
  124. #define PHP_WIN32_IOUTIL_INIT_W(path) \
  125. wchar_t *pathw = php_win32_ioutil_any_to_w(path); \
  126. #define PHP_WIN32_IOUTIL_CLEANUP_W() do { \
  127. free(pathw); \
  128. pathw = NULL; \
  129. } while (0);
  130. #define PHP_WIN32_IOUTIL_REINIT_W(path) do { \
  131. PHP_WIN32_IOUTIL_CLEANUP_W() \
  132. pathw = php_win32_ioutil_any_to_w(path); \
  133. } while (0);
  134. #define PHP_WIN32_IOUTIL_PATH_IS_OK_W(pathw, len) \
  135. (!((len) >= 1 && L' ' == pathw[(len)-1] || \
  136. (len) > 1 && !PHP_WIN32_IOUTIL_IS_SLASHW(pathw[(len)-2]) && L'.' != pathw[(len)-2] && L'.' == pathw[(len)-1]))
  137. #define PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, ret, dealloc) do { \
  138. size_t _len = wcslen(pathw); \
  139. if (!PHP_WIN32_IOUTIL_PATH_IS_OK_W(pathw, _len)) { \
  140. if (dealloc) { \
  141. free((void *)pathw); \
  142. } \
  143. SET_ERRNO_FROM_WIN32_CODE(ERROR_ACCESS_DENIED); \
  144. return ret; \
  145. } \
  146. } while (0);
  147. PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len);
  148. #ifdef PHP_EXPORTS
  149. /* This symbols are needed only for the DllMain, but should not be exported
  150. or be available when used with PHP binaries. */
  151. BOOL php_win32_ioutil_init(void);
  152. #endif
  153. /* Keep these functions aliased for case some additional handling
  154. is needed later. */
  155. __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, size_t in_len, size_t *out_len)
  156. {/*{{{*/
  157. wchar_t *mb, *ret;
  158. size_t mb_len;
  159. mb = php_win32_cp_conv_any_to_w(in, in_len, &mb_len);
  160. if (!mb) {
  161. return NULL;
  162. }
  163. /* Only prefix with long if it's needed. */
  164. if (mb_len >= _MAX_PATH) {
  165. size_t new_mb_len;
  166. ret = (wchar_t *) malloc((mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + 1) * sizeof(wchar_t));
  167. if (!ret) {
  168. free(mb);
  169. return NULL;
  170. }
  171. if (PHP_WIN32_IOUTIL_NORM_FAIL == php_win32_ioutil_normalize_path_w(&mb, mb_len, &new_mb_len)) {
  172. free(ret);
  173. free(mb);
  174. return NULL;
  175. }
  176. if (new_mb_len > mb_len) {
  177. wchar_t *tmp = (wchar_t *) realloc(ret, (new_mb_len + 1) * sizeof(wchar_t));
  178. if (!tmp) {
  179. free(ret);
  180. free(mb);
  181. return NULL;
  182. }
  183. ret = tmp;
  184. mb_len = new_mb_len;
  185. }
  186. if (PHP_WIN32_IOUTIL_IS_LONG_PATHW(mb, mb_len) || PHP_WIN32_IOUTIL_IS_JUNCTION_PATHW(mb, mb_len) || PHP_WIN32_IOUTIL_IS_UNC_PATHW(mb, mb_len)) {
  187. memmove(ret, mb, mb_len * sizeof(wchar_t));
  188. ret[mb_len] = L'\0';
  189. } else {
  190. wchar_t *src = mb, *dst = ret + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
  191. memmove(ret, PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW * sizeof(wchar_t));
  192. while (src < mb + mb_len) {
  193. if (*src == PHP_WIN32_IOUTIL_FW_SLASHW) {
  194. *dst++ = PHP_WIN32_IOUTIL_DEFAULT_SLASHW;
  195. src++;
  196. } else {
  197. *dst++ = *src++;
  198. }
  199. }
  200. ret[mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW] = L'\0';
  201. mb_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
  202. }
  203. free(mb);
  204. } else {
  205. ret = mb;
  206. }
  207. if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
  208. *out_len = mb_len;
  209. }
  210. return ret;
  211. }/*}}}*/
  212. #define php_win32_ioutil_any_to_w(in) php_win32_ioutil_conv_any_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  213. #define php_win32_ioutil_ascii_to_w php_win32_cp_ascii_to_w
  214. #define php_win32_ioutil_utf8_to_w php_win32_cp_utf8_to_w
  215. #define php_win32_ioutil_cur_to_w php_win32_cp_cur_to_w
  216. #define php_win32_ioutil_w_to_any php_win32_cp_w_to_any
  217. #define php_win32_ioutil_conv_w_to_any php_win32_cp_conv_w_to_any
  218. /*__forceinline static char *php_win32_ioutil_w_to_any(wchar_t* w_source_ptr)
  219. {
  220. return php_win32_cp_w_to_any(w_source_ptr);
  221. }*/
  222. #define php_win32_ioutil_w_to_utf8 php_win32_cp_w_to_utf8
  223. #define php_win32_ioutil_w_to_thread php_win32_cp_w_to_thread
  224. PW32IO int php_win32_ioutil_close(int fd);
  225. PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_ioutil_open_opts *opts);
  226. PW32IO size_t php_win32_ioutil_dirname(char *buf, size_t len);
  227. PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags, ...);
  228. PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path);
  229. PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname);
  230. PW32IO wchar_t *php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len);
  231. PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path);
  232. PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode);
  233. PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode);
  234. PW32IO FILE *php_win32_ioutil_fopen_w(const wchar_t *path, const wchar_t *mode);
  235. PW32IO wchar_t *php_win32_ioutil_realpath_w(const wchar_t *path, wchar_t *resolved);
  236. PW32IO wchar_t *php_win32_ioutil_realpath_w_ex0(const wchar_t *path, wchar_t *resolved, PBY_HANDLE_FILE_INFORMATION info);
  237. PW32IO int php_win32_ioutil_symlink_w(const wchar_t *target, const wchar_t *link);
  238. PW32IO int php_win32_ioutil_link_w(const wchar_t *target, const wchar_t *link);
  239. __forceinline static int php_win32_ioutil_access(const char *path, mode_t mode)
  240. {/*{{{*/
  241. PHP_WIN32_IOUTIL_INIT_W(path)
  242. int ret, err;
  243. if (!pathw) {
  244. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  245. return -1;
  246. }
  247. PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
  248. ret = php_win32_ioutil_access_w(pathw, mode);
  249. if (0 > ret) {
  250. err = GetLastError();
  251. }
  252. PHP_WIN32_IOUTIL_CLEANUP_W()
  253. if (0 > ret) {
  254. SET_ERRNO_FROM_WIN32_CODE(err);
  255. }
  256. return ret;
  257. }/*}}}*/
  258. __forceinline static int php_win32_ioutil_open(const char *path, int flags, ...)
  259. {/*{{{*/
  260. mode_t mode = 0;
  261. PHP_WIN32_IOUTIL_INIT_W(path)
  262. int ret = -1;
  263. DWORD err;
  264. if (!pathw) {
  265. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  266. return -1;
  267. }
  268. PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
  269. if (flags & O_CREAT) {
  270. va_list arg;
  271. va_start(arg, flags);
  272. mode = (mode_t) va_arg(arg, int);
  273. va_end(arg);
  274. }
  275. ret = php_win32_ioutil_open_w(pathw, flags, mode);
  276. if (0 > ret) {
  277. err = GetLastError();
  278. }
  279. PHP_WIN32_IOUTIL_CLEANUP_W()
  280. if (0 > ret) {
  281. SET_ERRNO_FROM_WIN32_CODE(err);
  282. }
  283. return ret;
  284. }/*}}}*/
  285. __forceinline static int php_win32_ioutil_unlink(const char *path)
  286. {/*{{{*/
  287. PHP_WIN32_IOUTIL_INIT_W(path)
  288. int ret = -1;
  289. DWORD err;
  290. if (!pathw) {
  291. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  292. return -1;
  293. }
  294. ret = php_win32_ioutil_unlink_w(pathw);
  295. if (0 > ret) {
  296. err = GetLastError();
  297. }
  298. PHP_WIN32_IOUTIL_CLEANUP_W()
  299. if (0 > ret) {
  300. SET_ERRNO_FROM_WIN32_CODE(err);
  301. }
  302. return ret;
  303. }/*}}}*/
  304. __forceinline static int php_win32_ioutil_rmdir(const char *path)
  305. {/*{{{*/
  306. PHP_WIN32_IOUTIL_INIT_W(path)
  307. int ret = 0;
  308. DWORD err = 0;
  309. if (!pathw) {
  310. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  311. return -1;
  312. }
  313. PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
  314. if (!RemoveDirectoryW(pathw)) {
  315. err = GetLastError();
  316. ret = -1;
  317. }
  318. PHP_WIN32_IOUTIL_CLEANUP_W()
  319. if (0 > ret) {
  320. SET_ERRNO_FROM_WIN32_CODE(err);
  321. }
  322. return ret;
  323. }/*}}}*/
  324. __forceinline static FILE *php_win32_ioutil_fopen(const char *patha, const char *modea)
  325. {/*{{{*/
  326. FILE *ret;
  327. wchar_t modew[16] = {0};
  328. int i = 0;
  329. PHP_WIN32_IOUTIL_INIT_W(patha)
  330. if (!pathw) {
  331. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  332. return NULL;
  333. }
  334. PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, NULL, 1)
  335. while (i < (sizeof(modew)-1)/sizeof(wchar_t) && modea[i]) {
  336. modew[i] = (wchar_t)modea[i];
  337. i++;
  338. }
  339. ret = php_win32_ioutil_fopen_w(pathw, modew);
  340. if (!ret) {
  341. int err = GetLastError();
  342. PHP_WIN32_IOUTIL_CLEANUP_W()
  343. SET_ERRNO_FROM_WIN32_CODE(err);
  344. return NULL;
  345. }
  346. PHP_WIN32_IOUTIL_CLEANUP_W()
  347. return ret;
  348. }/*}}}*/
  349. __forceinline static int php_win32_ioutil_rename(const char *oldnamea, const char *newnamea)
  350. {/*{{{*/
  351. wchar_t *oldnamew;
  352. wchar_t *newnamew;
  353. int ret;
  354. DWORD err = 0;
  355. oldnamew = php_win32_ioutil_any_to_w(oldnamea);
  356. if (!oldnamew) {
  357. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  358. return -1;
  359. }
  360. PHP_WIN32_IOUTIL_CHECK_PATH_W(oldnamew, -1, 1)
  361. newnamew = php_win32_ioutil_any_to_w(newnamea);
  362. if (!newnamew) {
  363. free(oldnamew);
  364. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  365. return -1;
  366. } else {
  367. size_t newnamew_len = wcslen(newnamew);
  368. if (!PHP_WIN32_IOUTIL_PATH_IS_OK_W(newnamew, newnamew_len)) {
  369. free(oldnamew);
  370. free(newnamew);
  371. SET_ERRNO_FROM_WIN32_CODE(ERROR_ACCESS_DENIED);
  372. return -1;
  373. }
  374. }
  375. ret = php_win32_ioutil_rename_w(oldnamew, newnamew);
  376. if (0 > ret) {
  377. err = GetLastError();
  378. }
  379. free(oldnamew);
  380. free(newnamew);
  381. if (0 > ret) {
  382. SET_ERRNO_FROM_WIN32_CODE(err);
  383. }
  384. return ret;
  385. }/*}}}*/
  386. __forceinline static int php_win32_ioutil_chdir(const char *patha)
  387. {/*{{{*/
  388. int ret;
  389. wchar_t *pathw = php_win32_ioutil_any_to_w(patha);
  390. DWORD err = 0;
  391. if (!pathw) {
  392. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  393. return -1;
  394. }
  395. ret = php_win32_ioutil_chdir_w(pathw);
  396. if (0 > ret) {
  397. err = GetLastError();
  398. }
  399. free(pathw);
  400. if (0 > ret) {
  401. SET_ERRNO_FROM_WIN32_CODE(err);
  402. }
  403. return ret;
  404. }/*}}}*/
  405. __forceinline static char *php_win32_ioutil_getcwd(char *buf, size_t len)
  406. {/*{{{*/
  407. wchar_t tmp_bufw[PHP_WIN32_IOUTIL_MAXPATHLEN];
  408. char *tmp_bufa = NULL;
  409. size_t tmp_bufa_len;
  410. DWORD err = 0;
  411. if (php_win32_ioutil_getcwd_w(tmp_bufw, len ? len : PHP_WIN32_IOUTIL_MAXPATHLEN) == NULL) {
  412. err = GetLastError();
  413. SET_ERRNO_FROM_WIN32_CODE(err);
  414. return NULL;
  415. }
  416. tmp_bufa = php_win32_cp_conv_w_to_any(tmp_bufw, wcslen(tmp_bufw), &tmp_bufa_len);
  417. if (!tmp_bufa) {
  418. err = GetLastError();
  419. SET_ERRNO_FROM_WIN32_CODE(err);
  420. return NULL;
  421. } else if (tmp_bufa_len + 1 > PHP_WIN32_IOUTIL_MAXPATHLEN) {
  422. free(tmp_bufa);
  423. SET_ERRNO_FROM_WIN32_CODE(ERROR_BAD_LENGTH);
  424. return NULL;
  425. } else if (tmp_bufa_len + 1 > len) {
  426. free(tmp_bufa);
  427. SET_ERRNO_FROM_WIN32_CODE(ERROR_INSUFFICIENT_BUFFER);
  428. return NULL;
  429. }
  430. if (!buf && !len) {
  431. /* If buf was NULL, the result has to be freed outside here. */
  432. buf = tmp_bufa;
  433. } else {
  434. memmove(buf, tmp_bufa, tmp_bufa_len + 1);
  435. free(tmp_bufa);
  436. }
  437. return buf;
  438. }/*}}}*/
  439. /* TODO improve with usage of native APIs, split for _a and _w. */
  440. __forceinline static int php_win32_ioutil_chmod(const char *patha, int mode)
  441. {/*{{{*/
  442. wchar_t *pathw = php_win32_ioutil_any_to_w(patha);
  443. int err = 0;
  444. int ret;
  445. if (!pathw) {
  446. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  447. return -1;
  448. }
  449. PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
  450. ret = _wchmod(pathw, mode);
  451. if (0 > ret) {
  452. _get_errno(&err);
  453. }
  454. free(pathw);
  455. if (0 > ret) {
  456. _set_errno(err);
  457. }
  458. return ret;
  459. }/*}}}*/
  460. __forceinline static int php_win32_ioutil_mkdir(const char *path, mode_t mode)
  461. {/*{{{*/
  462. int ret;
  463. DWORD err = 0;
  464. PHP_WIN32_IOUTIL_INIT_W(path)
  465. if (!pathw) {
  466. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  467. return -1;
  468. }
  469. ret = php_win32_ioutil_mkdir_w(pathw, mode);
  470. if (0 > ret) {
  471. err = GetLastError();
  472. }
  473. PHP_WIN32_IOUTIL_CLEANUP_W()
  474. if (0 > ret) {
  475. SET_ERRNO_FROM_WIN32_CODE(err);
  476. }
  477. return ret;
  478. }/*}}}*/
  479. __forceinline static int php_win32_ioutil_symlink(const char *target, const char *link)
  480. {/*{{{*/
  481. wchar_t *targetw, *linkw;
  482. int ret;
  483. targetw = php_win32_ioutil_any_to_w(target);
  484. if (!targetw) {
  485. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  486. return -1;
  487. }
  488. linkw = php_win32_ioutil_any_to_w(link);
  489. if (!linkw) {
  490. free(targetw);
  491. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  492. return -1;
  493. }
  494. ret = php_win32_ioutil_symlink_w(targetw, linkw);
  495. free(targetw);
  496. free(linkw);
  497. return ret;
  498. }/*}}}*/
  499. __forceinline static int php_win32_ioutil_link(const char *target, const char *link)
  500. {/*{{{*/
  501. wchar_t *targetw, *linkw;
  502. int ret;
  503. targetw = php_win32_ioutil_any_to_w(target);
  504. if (!targetw) {
  505. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  506. return -1;
  507. }
  508. linkw = php_win32_ioutil_any_to_w(link);
  509. if (!linkw) {
  510. free(targetw);
  511. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  512. return -1;
  513. }
  514. ret = php_win32_ioutil_link_w(targetw, linkw);
  515. free(targetw);
  516. free(linkw);
  517. return ret;
  518. }/*}}}*/
  519. PW32IO char *realpath(const char *path, char *resolved);
  520. __forceinline static char *php_win32_ioutil_realpath_ex0(const char *path, char *resolved, PBY_HANDLE_FILE_INFORMATION info)
  521. {/*{{{*/
  522. wchar_t retw[PHP_WIN32_IOUTIL_MAXPATHLEN];
  523. char *reta;
  524. size_t reta_len;
  525. PHP_WIN32_IOUTIL_INIT_W(path)
  526. if (!pathw) {
  527. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  528. return NULL;
  529. }
  530. if (NULL == php_win32_ioutil_realpath_w_ex0(pathw, retw, info)) {
  531. DWORD err = GetLastError();
  532. PHP_WIN32_IOUTIL_CLEANUP_W()
  533. SET_ERRNO_FROM_WIN32_CODE(err);
  534. return NULL;
  535. }
  536. reta = php_win32_cp_conv_w_to_any(retw, PHP_WIN32_CP_IGNORE_LEN, &reta_len);
  537. if (!reta || reta_len > PHP_WIN32_IOUTIL_MAXPATHLEN) {
  538. DWORD err = GetLastError();
  539. PHP_WIN32_IOUTIL_CLEANUP_W()
  540. SET_ERRNO_FROM_WIN32_CODE(err);
  541. return NULL;
  542. }
  543. if (NULL == resolved) {
  544. /* ret is expected to be either NULL or a buffer of capable size. */
  545. resolved = (char *) malloc(reta_len + 1);
  546. if (!resolved) {
  547. free(reta);
  548. PHP_WIN32_IOUTIL_CLEANUP_W()
  549. SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_ENOUGH_MEMORY);
  550. return NULL;
  551. }
  552. }
  553. memmove(resolved, reta, reta_len+1);
  554. PHP_WIN32_IOUTIL_CLEANUP_W()
  555. free(reta);
  556. return resolved;
  557. }/*}}}*/
  558. __forceinline static char *php_win32_ioutil_realpath(const char *path, char *resolved)
  559. {/*{{{*/
  560. return php_win32_ioutil_realpath_ex0(path, resolved, NULL);
  561. }/*}}}*/
  562. #include <sys/stat.h>
  563. #if _WIN64
  564. typedef unsigned __int64 php_win32_ioutil_dev_t;
  565. typedef unsigned __int64 php_win32_ioutil_ino_t;
  566. typedef __time64_t php_win32_ioutil_time_t;
  567. typedef __int64 php_win32_ioutil_size_t;
  568. #else
  569. typedef unsigned __int32 php_win32_ioutil_dev_t;
  570. typedef unsigned __int32 php_win32_ioutil_ino_t;
  571. typedef __time32_t php_win32_ioutil_time_t;
  572. typedef __int32 php_win32_ioutil_size_t;
  573. #endif
  574. typedef struct {
  575. php_win32_ioutil_dev_t st_dev;
  576. php_win32_ioutil_ino_t st_ino;
  577. unsigned __int32 st_mode;
  578. unsigned __int32 st_nlink;
  579. unsigned short st_uid;
  580. unsigned short st_gid;
  581. php_win32_ioutil_dev_t st_rdev;
  582. php_win32_ioutil_size_t st_size;
  583. #if 0
  584. __int32 st_blksize;
  585. __int32 st_blocks;
  586. #endif
  587. php_win32_ioutil_time_t st_atime;
  588. php_win32_ioutil_time_t st_mtime;
  589. php_win32_ioutil_time_t st_ctime;
  590. } php_win32_ioutil_stat_t;
  591. typedef struct {
  592. unsigned long ReparseTag;
  593. unsigned short ReparseDataLength;
  594. unsigned short Reserved;
  595. union {
  596. struct {
  597. unsigned short SubstituteNameOffset;
  598. unsigned short SubstituteNameLength;
  599. unsigned short PrintNameOffset;
  600. unsigned short PrintNameLength;
  601. unsigned long Flags;
  602. wchar_t ReparseTarget[1];
  603. } SymbolicLinkReparseBuffer;
  604. struct {
  605. unsigned short SubstituteNameOffset;
  606. unsigned short SubstituteNameLength;
  607. unsigned short PrintNameOffset;
  608. unsigned short PrintNameLength;
  609. wchar_t ReparseTarget[1];
  610. } MountPointReparseBuffer;
  611. struct {
  612. unsigned char ReparseTarget[1];
  613. } GenericReparseBuffer;
  614. };
  615. } PHP_WIN32_IOUTIL_REPARSE_DATA_BUFFER, *PHP_WIN32_IOUTIL_PREPARSE_DATA_BUFFER;
  616. PW32IO int php_win32_ioutil_stat_ex_w(const wchar_t *path, size_t path_len, php_win32_ioutil_stat_t *buf, int lstat);
  617. PW32IO int php_win32_ioutil_fstat(int fd, php_win32_ioutil_stat_t *buf);
  618. __forceinline static int php_win32_ioutil_stat_ex(const char *path, php_win32_ioutil_stat_t *buf, int lstat)
  619. {/*{{{*/
  620. size_t pathw_len;
  621. wchar_t *pathw = php_win32_ioutil_conv_any_to_w(path, PHP_WIN32_CP_IGNORE_LEN, &pathw_len);
  622. int ret;
  623. if (!pathw) {
  624. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  625. return -1;
  626. }
  627. ret = php_win32_ioutil_stat_ex_w(pathw, pathw_len, buf, lstat);
  628. free(pathw);
  629. return ret;
  630. }/*}}}*/
  631. #define php_win32_ioutil_stat(path, buf) php_win32_ioutil_stat_ex(path, buf, 0)
  632. #define php_win32_ioutil_lstat(path, buf) php_win32_ioutil_stat_ex(path, buf, 1)
  633. PW32IO ssize_t php_win32_ioutil_readlink_w(const wchar_t *path, wchar_t *buf, size_t buf_len);
  634. __forceinline static ssize_t php_win32_ioutil_readlink(const char *path, char *buf, size_t buf_len)
  635. {/*{{{*/
  636. size_t pathw_len, ret_buf_len;
  637. wchar_t *pathw = php_win32_ioutil_conv_any_to_w(path, PHP_WIN32_CP_IGNORE_LEN, &pathw_len);
  638. wchar_t retw[PHP_WIN32_IOUTIL_MAXPATHLEN];
  639. char *ret_buf;
  640. ssize_t ret;
  641. if (!pathw) {
  642. SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
  643. return -1;
  644. }
  645. ret = php_win32_ioutil_readlink_w(pathw, retw, sizeof(retw)-1);
  646. if (ret < 0) {
  647. DWORD _err = GetLastError();
  648. free(pathw);
  649. SET_ERRNO_FROM_WIN32_CODE(_err);
  650. return ret;
  651. }
  652. ret_buf = php_win32_ioutil_conv_w_to_any(retw, ret, &ret_buf_len);
  653. if (!ret_buf || ret_buf_len >= buf_len || ret_buf_len >= MAXPATHLEN) {
  654. free(ret_buf);
  655. free(pathw);
  656. SET_ERRNO_FROM_WIN32_CODE(ERROR_BAD_PATHNAME);
  657. return -1;
  658. }
  659. memcpy(buf, ret_buf, ret_buf_len + 1);
  660. free(ret_buf);
  661. free(pathw);
  662. return ret_buf_len;
  663. }/*}}}*/
  664. #ifdef __cplusplus
  665. }
  666. #endif
  667. #endif /* PHP_WIN32_IOUTIL_H */