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 | Author: Anatol Belski <ab@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* This file integrates several modified parts from the libuv project, which
20 * is copyrighted to
21 *
22 * Copyright Joyent, Inc. and other Node contributors. All rights reserved.
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a copy
25 * of this software and associated documentation files (the "Software"), to
26 * deal in the Software without restriction, including without limitation the
27 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
28 * sell copies of the Software, and to permit persons to whom the Software is
29 * furnished to do so, subject to the following conditions:
30 *
31 * The above copyright notice and this permission notice shall be included in
32 * all copies or substantial portions of the Software.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
39 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
40 * IN THE SOFTWARE.
41 */
42
43 #ifndef PHP_WIN32_IOUTIL_H
44 #define PHP_WIN32_IOUTIL_H
45
46 #include <fcntl.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <io.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52
53 #include "win32/winutil.h"
54 #include "win32/codepage.h"
55
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59
60 #ifdef PHP_EXPORTS
61 # define PW32IO __declspec(dllexport)
62 #else
63 # define PW32IO __declspec(dllimport)
64 #endif
65
66 #define PHP_WIN32_IOUTIL_MAXPATHLEN 2048
67
68 #if !defined(MAXPATHLEN) || MAXPATHLEN < PHP_WIN32_IOUTIL_MAXPATHLEN
69 # undef MAXPATHLEN
70 # define MAXPATHLEN PHP_WIN32_IOUTIL_MAXPATHLEN
71 #endif
72
73 #ifndef mode_t
74 typedef unsigned short mode_t;
75 #endif
76
77 typedef struct {
78 DWORD access;
79 DWORD share;
80 DWORD disposition;
81 DWORD attributes;
82 } php_ioutil_open_opts;
83
84 typedef enum {
85 PHP_WIN32_IOUTIL_IS_ASCII,
86 PHP_WIN32_IOUTIL_IS_ANSI,
87 PHP_WIN32_IOUTIL_IS_UTF8
88 } php_win32_ioutil_encoding;
89
90 typedef enum {
91 PHP_WIN32_IOUTIL_NORM_OK,
92 PHP_WIN32_IOUTIL_NORM_PARTIAL,
93 PHP_WIN32_IOUTIL_NORM_FAIL,
94 } php_win32_ioutil_normalization_result;
95
96 #define PHP_WIN32_IOUTIL_FW_SLASHW L'/'
97 #define PHP_WIN32_IOUTIL_FW_SLASH '/'
98 #define PHP_WIN32_IOUTIL_BW_SLASHW L'\\'
99 #define PHP_WIN32_IOUTIL_BW_SLASH '\\'
100 #define PHP_WIN32_IOUTIL_DEFAULT_SLASHW PHP_WIN32_IOUTIL_BW_SLASHW
101 #define PHP_WIN32_IOUTIL_DEFAULT_SLASH PHP_WIN32_IOUTIL_BW_SLASH
102
103 #define PHP_WIN32_IOUTIL_DEFAULT_DIR_SEPARATORW L';'
104 #define PHP_WIN32_IOUTIL_IS_SLASHW(c) ((c) == PHP_WIN32_IOUTIL_BW_SLASHW || (c) == PHP_WIN32_IOUTIL_FW_SLASHW)
105 #define PHP_WIN32_IOUTIL_IS_LETTERW(c) (((c) >= L'a' && (c) <= L'z') || ((c) >= L'A' && (c) <= L'Z'))
106 #define PHP_WIN32_IOUTIL_JUNCTION_PREFIXW L"\\??\\"
107 #define PHP_WIN32_IOUTIL_JUNCTION_PREFIX_LENW 4
108 #define PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW L"\\\\?\\"
109 #define PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW 4
110 #define PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW L"\\\\?\\UNC\\"
111 #define PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW 8
112
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
124 #define PHP_WIN32_IOUTIL_INIT_W(path) \
125 wchar_t *pathw = php_win32_ioutil_any_to_w(path); \
126
127 #define PHP_WIN32_IOUTIL_CLEANUP_W() do { \
128 free(pathw); \
129 pathw = NULL; \
130 } while (0);
131
132 #define PHP_WIN32_IOUTIL_REINIT_W(path) do { \
133 PHP_WIN32_IOUTIL_CLEANUP_W() \
134 pathw = php_win32_ioutil_any_to_w(path); \
135 } while (0);
136
137 #define PHP_WIN32_IOUTIL_PATH_IS_OK_W(pathw, len) \
138 (!((len) >= 1 && L' ' == pathw[(len)-1] || \
139 (len) > 1 && !PHP_WIN32_IOUTIL_IS_SLASHW(pathw[(len)-2]) && L'.' != pathw[(len)-2] && L'.' == pathw[(len)-1]))
140
141 #define PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, ret, dealloc) do { \
142 if (!PHP_WIN32_IOUTIL_PATH_IS_OK_W(pathw, wcslen(pathw))) { \
143 if (dealloc) { \
144 free((void *)pathw); \
145 } \
146 SET_ERRNO_FROM_WIN32_CODE(ERROR_ACCESS_DENIED); \
147 return ret; \
148 } \
149 } while (0);
150
151 PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len);
152 #ifdef PHP_EXPORTS
153 /* This symbols are needed only for the DllMain, but should not be exported
154 or be available when used with PHP binaries. */
155 BOOL php_win32_ioutil_init(void);
156 #endif
157
158 /* Keep these functions aliased for case some additional handling
159 is needed later. */
php_win32_ioutil_conv_any_to_w(const char * in,size_t in_len,size_t * out_len)160 __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, size_t in_len, size_t *out_len)
161 {/*{{{*/
162 wchar_t *mb, *ret;
163 size_t mb_len;
164
165 mb = php_win32_cp_conv_any_to_w(in, in_len, &mb_len);
166 if (!mb) {
167 return NULL;
168 }
169
170 /* Only prefix with long if it's needed. */
171 if (mb_len >= _MAX_PATH) {
172 size_t new_mb_len;
173
174 ret = (wchar_t *) malloc((mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + 1) * sizeof(wchar_t));
175 if (!ret) {
176 free(mb);
177 return NULL;
178 }
179
180 if (PHP_WIN32_IOUTIL_NORM_FAIL == php_win32_ioutil_normalize_path_w(&mb, mb_len, &new_mb_len)) {
181 free(ret);
182 free(mb);
183 return NULL;
184 }
185
186 if (new_mb_len > mb_len) {
187 wchar_t *tmp = (wchar_t *) realloc(ret, (new_mb_len + 1) * sizeof(wchar_t));
188 if (!tmp) {
189 free(ret);
190 free(mb);
191 return NULL;
192 }
193 ret = tmp;
194 mb_len = new_mb_len;
195 }
196
197 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)) {
198 memmove(ret, mb, mb_len * sizeof(wchar_t));
199 ret[mb_len] = L'\0';
200 } else {
201 memmove(ret, PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW * sizeof(wchar_t));
202 memmove(ret+PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW, mb, mb_len * sizeof(wchar_t));
203 ret[mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW] = L'\0';
204
205 mb_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
206 }
207
208 free(mb);
209 } else {
210 ret = mb;
211 }
212
213 if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
214 *out_len = mb_len;
215 }
216
217 return ret;
218 }/*}}}*/
219 #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)
220
221 #define php_win32_ioutil_ascii_to_w php_win32_cp_ascii_to_w
222 #define php_win32_ioutil_utf8_to_w php_win32_cp_utf8_to_w
223 #define php_win32_ioutil_cur_to_w php_win32_cp_cur_to_w
224 #define php_win32_ioutil_w_to_any php_win32_cp_w_to_any
225 #define php_win32_ioutil_conv_w_to_any php_win32_cp_conv_w_to_any
226 /*__forceinline static char *php_win32_ioutil_w_to_any(wchar_t* w_source_ptr)
227 {
228 return php_win32_cp_w_to_any(w_source_ptr);
229 }*/
230 #define php_win32_ioutil_w_to_utf8 php_win32_cp_w_to_utf8
231 #define php_win32_ioutil_w_to_thread php_win32_cp_w_to_thread
232
233 PW32IO int php_win32_ioutil_close(int fd);
234 PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_ioutil_open_opts *opts);
235 PW32IO int php_win32_ioutil_mkdir(const char *path, mode_t mode);
236 PW32IO size_t php_win32_ioutil_dirname(char *buf, size_t len);
237
238 PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags, ...);
239 PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path);
240 PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname);
241 PW32IO wchar_t *php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len);
242
243 #if 0
244 PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode);
245 PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode);
246 #endif
247
248 #define php_win32_ioutil_access_cond(path, mode) _waccess(pathw, mode)
249 #define php_win32_ioutil_unlink_cond(path) php_win32_ioutil_unlink_w(pathw)
250 #define php_win32_ioutil_rmdir_cond(path) php_win32_ioutil_rmdir_w(pathw)
251
php_win32_ioutil_access(const char * path,mode_t mode)252 __forceinline static int php_win32_ioutil_access(const char *path, mode_t mode)
253 {/*{{{*/
254 PHP_WIN32_IOUTIL_INIT_W(path)
255 int ret, err;
256
257 if (!pathw) {
258 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
259 return -1;
260 }
261
262 PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
263
264 ret = _waccess(pathw, mode);
265 if (0 > ret) {
266 _get_errno(&err);
267 }
268 PHP_WIN32_IOUTIL_CLEANUP_W()
269
270 if (0 > ret) {
271 _set_errno(err);
272 }
273
274 return ret;
275 }/*}}}*/
276
php_win32_ioutil_open(const char * path,int flags,...)277 __forceinline static int php_win32_ioutil_open(const char *path, int flags, ...)
278 {/*{{{*/
279 mode_t mode = 0;
280 PHP_WIN32_IOUTIL_INIT_W(path)
281 int ret = -1;
282 DWORD err;
283
284 if (!pathw) {
285 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
286 return -1;
287 }
288
289 PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
290
291 if (flags & O_CREAT) {
292 va_list arg;
293
294 va_start(arg, flags);
295 mode = (mode_t) va_arg(arg, int);
296 va_end(arg);
297 }
298
299 ret = php_win32_ioutil_open_w(pathw, flags, mode);
300 if (0 > ret) {
301 err = GetLastError();
302 }
303 PHP_WIN32_IOUTIL_CLEANUP_W()
304
305 if (0 > ret) {
306 SET_ERRNO_FROM_WIN32_CODE(err);
307 }
308
309 return ret;
310 }/*}}}*/
311
php_win32_ioutil_unlink(const char * path)312 __forceinline static int php_win32_ioutil_unlink(const char *path)
313 {/*{{{*/
314 PHP_WIN32_IOUTIL_INIT_W(path)
315 int ret = 0;
316 DWORD err = 0;
317
318 if (!pathw) {
319 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
320 return -1;
321 }
322
323 PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
324
325 if (!DeleteFileW(pathw)) {
326 err = GetLastError();
327 ret = -1;
328 }
329 PHP_WIN32_IOUTIL_CLEANUP_W()
330
331 if (0 > ret) {
332 SET_ERRNO_FROM_WIN32_CODE(err);
333 }
334
335 return ret;
336 }/*}}}*/
337
php_win32_ioutil_rmdir(const char * path)338 __forceinline static int php_win32_ioutil_rmdir(const char *path)
339 {/*{{{*/
340 PHP_WIN32_IOUTIL_INIT_W(path)
341 int ret = 0;
342 DWORD err = 0;
343
344 if (!pathw) {
345 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
346 return -1;
347 }
348
349 PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
350
351 if (!RemoveDirectoryW(pathw)) {
352 err = GetLastError();
353 ret = -1;
354 }
355
356 PHP_WIN32_IOUTIL_CLEANUP_W()
357
358 if (0 > ret) {
359 SET_ERRNO_FROM_WIN32_CODE(err);
360 }
361
362 return ret;
363 }/*}}}*/
364
365 /* This needs to be improved once long path support is implemented. Use ioutil_open() and then
366 fdopen() might be the way, if we learn how to convert the mode options (maybe grab the routine
367 from the streams). That will allow to split for _a and _w. */
php_win32_ioutil_fopen(const char * patha,const char * modea)368 __forceinline static FILE *php_win32_ioutil_fopen(const char *patha, const char *modea)
369 {/*{{{*/
370 FILE *ret;
371 wchar_t *pathw;
372 wchar_t *modew;
373 int err = 0;
374
375 pathw = php_win32_ioutil_any_to_w(patha);
376 if (!pathw) {
377 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
378 return NULL;
379 }
380
381 PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, NULL, 1)
382
383 modew = php_win32_ioutil_ascii_to_w(modea);
384 if (!modew) {
385 free(pathw);
386 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
387 return NULL;
388 }
389
390 ret = _wfopen(pathw, modew);
391 if (!ret) {
392 _get_errno(&err);
393 }
394 free(pathw);
395 free(modew);
396
397 if (!ret) {
398 _set_errno(err);
399 }
400 return ret;
401 }/*}}}*/
402
php_win32_ioutil_rename(const char * oldnamea,const char * newnamea)403 __forceinline static int php_win32_ioutil_rename(const char *oldnamea, const char *newnamea)
404 {/*{{{*/
405 wchar_t *oldnamew;
406 wchar_t *newnamew;
407 int ret;
408 DWORD err = 0;
409
410 oldnamew = php_win32_ioutil_any_to_w(oldnamea);
411 if (!oldnamew) {
412 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
413 return -1;
414 }
415 PHP_WIN32_IOUTIL_CHECK_PATH_W(oldnamew, -1, 1)
416
417 newnamew = php_win32_ioutil_any_to_w(newnamea);
418 if (!newnamew) {
419 free(oldnamew);
420 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
421 return -1;
422 } else if (!PHP_WIN32_IOUTIL_PATH_IS_OK_W(newnamew, wcslen(newnamew))) {
423 free(oldnamew);
424 free(newnamew);
425 SET_ERRNO_FROM_WIN32_CODE(ERROR_ACCESS_DENIED);
426 return -1;
427 }
428
429 ret = php_win32_ioutil_rename_w(oldnamew, newnamew);
430 if (0 > ret) {
431 err = GetLastError();
432 }
433
434 free(oldnamew);
435 free(newnamew);
436
437 if (0 > ret) {
438 SET_ERRNO_FROM_WIN32_CODE(err);
439 }
440
441 return ret;
442 }/*}}}*/
443
php_win32_ioutil_chdir(const char * patha)444 __forceinline static int php_win32_ioutil_chdir(const char *patha)
445 {/*{{{*/
446 int ret;
447 wchar_t *pathw = php_win32_ioutil_any_to_w(patha);
448 DWORD err = 0;
449
450 if (!pathw) {
451 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
452 return -1;
453 }
454
455 ret = php_win32_ioutil_chdir_w(pathw);
456 if (0 > ret) {
457 err = GetLastError();
458 }
459
460 free(pathw);
461
462 if (0 > ret) {
463 SET_ERRNO_FROM_WIN32_CODE(err);
464 }
465
466 return ret;
467 }/*}}}*/
468
php_win32_ioutil_getcwd(char * buf,int len)469 __forceinline static char *php_win32_ioutil_getcwd(char *buf, int len)
470 {/*{{{*/
471 wchar_t tmp_bufw[PHP_WIN32_IOUTIL_MAXPATHLEN];
472 char *tmp_bufa = NULL;
473 size_t tmp_bufa_len;
474 DWORD err = 0;
475
476 if (php_win32_ioutil_getcwd_w(tmp_bufw, PHP_WIN32_IOUTIL_MAXPATHLEN) == NULL) {
477 err = GetLastError();
478 SET_ERRNO_FROM_WIN32_CODE(err);
479 return NULL;
480 }
481
482 tmp_bufa = php_win32_cp_conv_w_to_any(tmp_bufw, wcslen(tmp_bufw), &tmp_bufa_len);
483 if (!tmp_bufa) {
484 err = GetLastError();
485 SET_ERRNO_FROM_WIN32_CODE(err);
486 return NULL;
487 } else if (tmp_bufa_len + 1 > PHP_WIN32_IOUTIL_MAXPATHLEN) {
488 free(tmp_bufa);
489 SET_ERRNO_FROM_WIN32_CODE(ERROR_BAD_LENGTH);
490 return NULL;
491 }
492
493 if (!buf) {
494 /* If buf was NULL, the result has to be freed outside here. */
495 buf = tmp_bufa;
496 } else {
497 if (tmp_bufa_len + 1 > (size_t)len) {
498 free(tmp_bufa);
499 SET_ERRNO_FROM_WIN32_CODE(ERROR_INSUFFICIENT_BUFFER);
500 return NULL;
501 }
502 memmove(buf, tmp_bufa, tmp_bufa_len + 1);
503 free(tmp_bufa);
504 }
505
506 return buf;
507 }/*}}}*/
508
509 /* TODO improve with usage of native APIs, split for _a and _w. */
php_win32_ioutil_chmod(const char * patha,int mode)510 __forceinline static int php_win32_ioutil_chmod(const char *patha, int mode)
511 {/*{{{*/
512 wchar_t *pathw = php_win32_ioutil_any_to_w(patha);
513 int err = 0;
514 int ret;
515
516 if (!pathw) {
517 SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
518 return -1;
519 }
520
521 PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
522
523 ret = _wchmod(pathw, mode);
524 if (0 > ret) {
525 _get_errno(&err);
526 }
527
528 free(pathw);
529
530 if (0 > ret) {
531 _set_errno(err);
532 }
533
534 return ret;
535 }/*}}}*/
536
537 #ifdef __cplusplus
538 }
539 #endif
540
541 #endif /* PHP_WIN32_IOUTIL_H */
542
543 /*
544 * Local variables:
545 * tab-width: 4
546 * c-basic-offset: 4
547 * End:
548 * vim600: sw=4 ts=4 fdm=marker
549 * vim<600: sw=4 ts=4
550 */
551