70typedef HRESULT (__stdcall *
MyPathCchCanonicalizeEx)(
wchar_t *pszPathOut,
size_t cchPathOut,
const wchar_t *pszPathIn,
unsigned long dwFlags);
82 current_umask =
umask(0);
86 switch (
flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
88 opts->
access = FILE_GENERIC_READ;
93 opts->
access = FILE_GENERIC_WRITE;
96 opts->
access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
102 if (
flags & _O_APPEND) {
105 opts->
access |= FILE_APPEND_DATA;
106 opts->
attributes &= ~FILE_FLAG_BACKUP_SEMANTICS;
117 switch (
flags & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
125 case _O_CREAT | _O_EXCL:
126 case _O_CREAT | _O_TRUNC | _O_EXCL:
130 case _O_TRUNC | _O_EXCL:
133 case _O_CREAT | _O_TRUNC:
141 if (
flags & _O_CREAT) {
142 if (!((
mode & ~current_umask) & _S_IWRITE)) {
147 if (
flags & _O_TEMPORARY ) {
148 opts->
attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
152 if (
flags & _O_SHORT_LIVED) {
156 switch (
flags & (_O_SEQUENTIAL | _O_RANDOM)) {
160 opts->
attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
196 if (
flags & O_CREAT) {
209 file = CreateFileW(path,
217 if (
file == INVALID_HANDLE_VALUE) {
220 if (
error == ERROR_FILE_EXISTS && (
flags & _O_CREAT) &&
221 !(
flags & _O_EXCL)) {
239 if (
errno == EMFILE) {
241 }
else if (
error != ERROR_SUCCESS) {
248 if (
flags & _O_TEXT) {
249 _setmode(
fd, _O_TEXT);
250 }
else if (
flags & _O_BINARY) {
251 _setmode(
fd, _O_BINARY);
289 const wchar_t *my_path;
298 path_len = wcslen(path);
299 if (path_len < _MAX_PATH && path_len >= _MAX_PATH - 12) {
309 wchar_t *tmp = (
wchar_t *) malloc((path_len + 1) *
sizeof(
wchar_t));
314 memmove(tmp, path, (path_len + 1) *
sizeof(
wchar_t));
332 while (src < tmp + path_len) {
341 _tmp[path_len] = L
'\0';
352 if (!CreateDirectoryW(my_path,
NULL)) {
354 if (my_path != path) {
355 free((
void *)my_path);
361 if (my_path != path) {
362 free((
void *)my_path);
372 BY_HANDLE_FILE_INFORMATION info;
373 FILE_DISPOSITION_INFO disposition;
378 h = CreateFileW(path,
379 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE,
383 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
386 if (INVALID_HANDLE_VALUE == h) {
387 err = GetLastError();
392 if (!GetFileInformationByHandle(h, &info)) {
393 err = GetLastError();
399 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
408 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
410 FILE_BASIC_INFO basic = { 0 };
412 basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY);
414 status = SetFileInformationByHandle(h, FileBasicInfo, &basic,
sizeof basic);
416 err = GetLastError();
425 disposition.DeleteFile =
TRUE;
426 status = SetFileInformationByHandle(h, FileDispositionInfo, &disposition,
sizeof disposition);
428 err = GetLastError();
445 if (!RemoveDirectoryW(path)) {
458 if (!SetCurrentDirectoryW(path)) {
475 if (!MoveFileExW(oldname, newname, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED)) {
487 wchar_t *tmp_buf =
NULL;
492 tmp_len = GetCurrentDirectoryW(0,
NULL) + 1;
494 err = GetLastError();
497 }
else if (tmp_len >
len) {
502 tmp_buf = (
wchar_t *)malloc((tmp_len)*
sizeof(
wchar_t));
510 if (!GetCurrentDirectoryW(tmp_len,
buf)) {
511 err = GetLastError();
517 return (
wchar_t *)
buf;
524 size_t ret_len, len_adjust = 0, pathw_len;
525 wchar_t *endw, *pathw, *startw;
534 startw = pathw = php_win32_cp_conv_any_to_w(path,
len, &pathw_len);
539 endw = pathw + pathw_len - 1;
541 if ((2 <= pathw_len) && iswalpha((wint_t)(pathw)[0]) && (L
':' == pathw[1])) {
560 return 1 + len_adjust;
571 return 1 + len_adjust;
582 return 1 + len_adjust;
586 ret_len = (endw + 1 - startw);
604 size_t ret_len =
len;
612 for (; (size_t)(idx - *
buf) <=
len; idx++,
pos++) {
622 if (S_OK != canonicalize_path_w(canonicalw,
MAXPATHLEN, _tmp, PATHCCH_ALLOW_LONG_PATHS)) {
627 ret_len = wcslen(canonicalw);
628 if (ret_len !=
len) {
630 wchar_t *tmp = realloc(*
buf, (ret_len + 1) *
sizeof(
wchar_t));
639 memmove(*
buf, canonicalw, (ret_len + 1) *
sizeof(
wchar_t));
646static HRESULT __stdcall MyPathCchCanonicalizeExFallback(
wchar_t *pszPathOut,
size_t cchPathOut,
const wchar_t *pszPathIn,
unsigned long dwFlags)
653 HMODULE hMod = GetModuleHandle(
"api-ms-win-core-path-l1-1-0");
657 if (!canonicalize_path_w) {
673 return GetBinaryTypeW(path, &
type) ? 0 : -1;
676 attr = GetFileAttributesW(path);
677 if (
attr == INVALID_FILE_ATTRIBUTES) {
687 if ((
mode &
W_OK) ==
W_OK && (
attr & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
698 char modea[16] = {0};
704 while (i <
sizeof(modea)-1 &&
mode[i]) {
705 modea[i] = (char)
mode[i];
715 err = GetLastError();
722 err = GetLastError();
731static size_t php_win32_ioutil_realpath_h(HANDLE *h,
wchar_t **resolved)
734 DWORD ret_len, ret_real_len;
746 if (
NULL == *resolved) {
748 *resolved = (
wchar_t *) malloc((ret_len + 1)*
sizeof(
wchar_t));
756 ret_real_len = ret_len;
765 memmove(*resolved, ret_real, (ret_real_len+1)*
sizeof(
wchar_t));
782 h = CreateFileW(path,
787 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
789 if (INVALID_HANDLE_VALUE == h) {
795 ret_len = php_win32_ioutil_realpath_h(h, &resolved);
796 if ((
size_t)-1 == ret_len) {
803 if (
NULL != info && !GetFileInformationByHandle(h, info)) {
817 return php_win32_ioutil_realpath(path, resolved);
825 if ((
attr = GetFileAttributesW(target)) == INVALID_FILE_ATTRIBUTES) {
830 res = CreateSymbolicLinkW(
link, target, (
attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0));
852#define FILETIME_TO_UINT(filetime) \
853 (*((uint64_t*) &(filetime)) - 116444736000000000ULL)
855#define FILETIME_TO_TIME_T(filetime) \
856 (time_t)(FILETIME_TO_UINT(filetime) / 10000000ULL)
858static int php_win32_ioutil_fstat_int(HANDLE h,
php_win32_ioutil_stat_t *
buf,
const wchar_t *pathw,
size_t pathw_len, PBY_HANDLE_FILE_INFORMATION dp)
860 BY_HANDLE_FILE_INFORMATION d;
861 PBY_HANDLE_FILE_INFORMATION
data;
865 data = !dp ? &d : dp;
867 if(!GetFileInformationByHandle(h,
data)) {
868 if (INVALID_HANDLE_VALUE != h) {
870 struct __stat64 _buf;
871 if (_fstat64(_open_osfhandle((intptr_t)h, 0), &_buf)) {
874 buf->st_dev = _buf.st_dev;
875 buf->st_ino = _buf.st_ino;
876 buf->st_mode = _buf.st_mode;
877 buf->st_nlink = _buf.st_nlink;
878 buf->st_uid = _buf.st_uid;
879 buf->st_gid = _buf.st_gid;
880 buf->st_rdev = _buf.st_rdev;
881 buf->st_size = _buf.st_size;
882 buf->st_atime = _buf.st_atime;
883 buf->st_mtime = _buf.st_mtime;
884 buf->st_ctime = _buf.st_ctime;
886 }
else if(h == INVALID_HANDLE_VALUE && pathw_len > 0) {
891 WIN32_FILE_ATTRIBUTE_DATA _data;
892 if (!GetFileAttributesExW(pathw, GetFileExInfoStandard, &_data)) {
897 data->dwFileAttributes = _data.dwFileAttributes;
898 data->ftCreationTime = _data.ftCreationTime;
899 data->ftLastAccessTime = _data.ftLastAccessTime;
900 data->ftLastWriteTime = _data.ftLastWriteTime;
901 data->nFileSizeHigh = _data.nFileSizeHigh;
902 data->nFileSizeLow = _data.nFileSizeLow;
903 data->dwVolumeSerialNumber = 0;
904 data->nNumberOfLinks = 1;
905 data->nFileIndexHigh = 0;
906 data->nFileIndexLow = 0;
914 is_dir = (
data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
916 buf->st_dev =
data->dwVolumeSerialNumber;
918 buf->st_rdev =
buf->st_uid =
buf->st_gid = 0;
920 buf->st_ino = (((uint64_t)
data->nFileIndexHigh) << 32) +
data->nFileIndexLow;
925 if (pathw_len >= 4 &&
926 pathw[pathw_len-4] == L
'.') {
927 if (_wcsnicmp(pathw+pathw_len-3, L
"exe", 3) == 0 ||
928 _wcsnicmp(pathw+pathw_len-3, L
"com", 3) == 0) {
930 if (GetBinaryTypeW(pathw, &
type)) {
931 buf->st_mode |= (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
934 }
else if (_wcsnicmp(pathw+pathw_len-3, L
"bat", 3) == 0 ||
935 _wcsnicmp(pathw+pathw_len-3, L
"cmd", 3) == 0) {
936 buf->st_mode |= (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
941 if ((
data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
943 buf->st_mode |= (S_IFDIR|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
945 switch (GetFileType(h)) {
947 buf->st_mode |= S_IFCHR;
953 buf->st_mode |= S_IFREG;
956 buf->st_mode |= (
data->dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)) : (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)|S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6));
959 buf->st_nlink =
data->nNumberOfLinks;
960 t.HighPart =
data->nFileSizeHigh;
961 t.LowPart =
data->nFileSizeLow;
974 BY_HANDLE_FILE_INFORMATION
data;
976 DWORD flags_and_attrs =
lstat ? FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT : FILE_FLAG_BACKUP_SEMANTICS;
980 hLink = CreateFileW(path,
981 FILE_READ_ATTRIBUTES,
989 ret = php_win32_ioutil_fstat_int(hLink,
buf, path, path_len, &
data);
991 if (
lstat &&
data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
997 if(!DeviceIoControl(hLink, FSCTL_GET_REPARSE_POINT,
NULL, 0, pbuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &retlength,
NULL)) {
1003 if(pbuffer->
ReparseTag == IO_REPARSE_TAG_SYMLINK) {
1005 buf->st_mode |= (
data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)) : (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)|S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6));
1009 else if(pbuffer->
ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
1024 return php_win32_ioutil_fstat_int((HANDLE)_get_osfhandle(
fd),
buf,
NULL, 0,
NULL);
1027static ssize_t php_win32_ioutil_readlink_int(HANDLE h,
wchar_t *
buf,
size_t buf_len)
1029 char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1031 wchar_t* reparse_target;
1032 DWORD reparse_target_len;
1035 if (!DeviceIoControl(h,
1036 FSCTL_GET_REPARSE_POINT,
1047 if (reparse_data->
ReparseTag == IO_REPARSE_TAG_SYMLINK) {
1059 reparse_target_len =
1068 if (reparse_target_len >= 4 &&
1069 reparse_target[0] == L
'\\' &&
1070 reparse_target[1] == L
'?' &&
1071 reparse_target[2] == L
'?' &&
1072 reparse_target[3] == L
'\\') {
1074 if (reparse_target_len >= 6 &&
1075 ((reparse_target[4] >= L
'A' && reparse_target[4] <= L
'Z') ||
1076 (reparse_target[4] >= L
'a' && reparse_target[4] <= L
'z')) &&
1077 reparse_target[5] == L
':' &&
1078 (reparse_target_len == 6 || reparse_target[6] == L
'\\')) {
1080 reparse_target += 4;
1081 reparse_target_len -= 4;
1083 }
else if (reparse_target_len >= 8 &&
1084 (reparse_target[4] == L
'U' || reparse_target[4] == L
'u') &&
1085 (reparse_target[5] == L
'N' || reparse_target[5] == L
'n') &&
1086 (reparse_target[6] == L
'C' || reparse_target[6] == L
'c') &&
1087 reparse_target[7] == L
'\\') {
1090 reparse_target += 6;
1091 reparse_target[0] = L
'\\';
1092 reparse_target_len -= 6;
1096 }
else if (reparse_data->
ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
1108 if (!(reparse_target_len >= 6 &&
1109 reparse_target[0] == L
'\\' &&
1110 reparse_target[1] == L
'?' &&
1111 reparse_target[2] == L
'?' &&
1112 reparse_target[3] == L
'\\' &&
1113 ((reparse_target[4] >= L
'A' && reparse_target[4] <= L
'Z') ||
1114 (reparse_target[4] >= L
'a' && reparse_target[4] <= L
'z')) &&
1115 reparse_target[5] == L
':' &&
1116 (reparse_target_len == 6 || reparse_target[6] == L
'\\'))) {
1122 reparse_target += 4;
1123 reparse_target_len -= 4;
1131 if (reparse_target_len >= buf_len) {
1136 memcpy(
buf, reparse_target, reparse_target_len*
sizeof(
wchar_t));
1137 buf[reparse_target_len] = L
'\0';
1139 return reparse_target_len;
1148 h = CreateFileW(path,
1153 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
1156 if (h == INVALID_HANDLE_VALUE) {
1161 ret = php_win32_ioutil_readlink_int(h,
buf, buf_len);
1170 h = CreateFileW(path,
1175 FILE_FLAG_BACKUP_SEMANTICS,
1178 if (h == INVALID_HANDLE_VALUE) {
1190 if(target_len > 4) {
1192 if(target[0] == L
'\\' && target[1] == L
'\\' && target[2] == L
'?' && target[3] == L
'\\') {
1196 if (target_len > 7 && target[4] == L
'U' && target[5] == L
'N' && target[6] == L
'C') {
file(string $filename, int $flags=0, $context=null)
assert(mixed $assertion, Throwable|string|null $description=null)
link(string $target, string $link)
zend_ffi_ctype_name_buf buf
PW32IO int php_win32_ioutil_link_w(const wchar_t *target, const wchar_t *link)
PW32IO int php_win32_ioutil_rmdir_w(const wchar_t *path)
PW32IO ssize_t php_win32_ioutil_readlink_w(const wchar_t *path, wchar_t *buf, size_t buf_len)
PW32IO int php_win32_ioutil_symlink_w(const wchar_t *target, const wchar_t *link)
BOOL php_win32_ioutil_init(void)
PW32IO size_t php_win32_ioutil_dirname(char *path, size_t len)
PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags,...)
PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len)
HRESULT(__stdcall * MyPathCchCanonicalizeEx)(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags)
PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode)
PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode)
PW32IO int php_win32_ioutil_close(int fd)
PW32IO char * realpath(const char *path, char *resolved)
PW32IO wchar_t * php_win32_ioutil_realpath_w_ex0(const wchar_t *path, wchar_t *resolved, PBY_HANDLE_FILE_INFORMATION info)
PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname)
PW32IO int php_win32_ioutil_stat_ex_w(const wchar_t *path, size_t path_len, php_win32_ioutil_stat_t *buf, int lstat)
PW32IO wchar_t * php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len)
#define FILETIME_TO_TIME_T(filetime)
PW32IO int php_win32_ioutil_fstat(int fd, php_win32_ioutil_stat_t *buf)
PW32IO wchar_t * php_win32_ioutil_realpath_w(const wchar_t *path, wchar_t *resolved)
PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path)
PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path)
PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_ioutil_open_opts *opts)
PW32IO FILE * php_win32_ioutil_fopen_w(const wchar_t *path, const wchar_t *mode)
#define PHP_WIN32_IOUTIL_FW_SLASHW
#define PHP_WIN32_IOUTIL_IS_SLASHW(c)
#define PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW
#define PHP_WIN32_IOUTIL_DEFAULT_SLASH
#define SYMLINK_FLAG_RELATIVE
#define PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, ret, dealloc)
#define PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW
#define PHP_WIN32_IOUTIL_IS_LONG_PATHW(pathw, path_lenw)
#define PHP_WIN32_IOUTIL_DEFAULT_SLASHW
php_win32_ioutil_normalization_result
@ PHP_WIN32_IOUTIL_NORM_PARTIAL
@ PHP_WIN32_IOUTIL_NORM_OK
@ PHP_WIN32_IOUTIL_NORM_FAIL
#define PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE
#define PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW
#define PHP_WIN32_IOUTIL_MAXPATHLEN
#define PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW
#define php_win32_ioutil_conv_w_to_any
unsigned const char * pos
PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
unsigned short SubstituteNameOffset
struct PHP_WIN32_IOUTIL_REPARSE_DATA_BUFFER::@075116064036122104134040077213306127064052270261::@332270134025003203317152004221326066051376202346 SymbolicLinkReparseBuffer
unsigned short SubstituteNameLength
struct PHP_WIN32_IOUTIL_REPARSE_DATA_BUFFER::@075116064036122104134040077213306127064052270261::@322264331303223015276004312373161151004310266064 MountPointReparseBuffer
#define SET_ERRNO_FROM_WIN32_CODE(err)
#define ALLOCA_FLAG(name)
#define do_alloca(p, use_heap)
#define free_alloca(p, use_heap)