59#define isdirsep(x) ((x) == '/' || (x) == '\\')
61#if defined _MSC_VER && _MSC_VER <= 1200
62# define CharNextExA(cp, p, flags) CharNextExA((WORD)(cp), (p), (flags))
65static int w32_wopen(
const WCHAR *file,
int oflag,
int perm);
67static char *w32_getenv(
const char *
name, UINT cp);
70#define DLN_FIND_EXTRA_ARG_DECL ,UINT cp
71#define DLN_FIND_EXTRA_ARG ,cp
72#define rb_w32_stati128(path, st) w32_stati128(path, st, cp, FALSE)
73#define getenv(name) w32_getenv(name, cp)
75#define CharNext(p) CharNextExA(cp, (p), 0)
76#define dln_find_exe_r rb_w32_udln_find_exe_r
77#define dln_find_file_r rb_w32_udln_find_file_r
84#define dln_find_exe_r(fname, path, buf, size) rb_w32_udln_find_exe_r(fname, path, buf, size, cp)
85#define dln_find_file_r(fname, path, buf, size) rb_w32_udln_find_file_r(fname, path, buf, size, cp)
90# define PATH_MAX MAX_PATH
91# elif defined HAVE_SYS_PARAM_H
92# include <sys/param.h>
93# define PATH_MAX MAXPATHLEN
105#if RUBY_MSVCRT_VERSION >= 140
106# define _filbuf _fgetc_nolock
107# define _flsbuf _fputc_nolock
109#define enough_to_get(n) (--(n) >= 0)
110#define enough_to_put(n) (--(n) >= 0)
113#define Debug(something) something
115#define Debug(something)
118#define TO_SOCKET(x) _get_osfhandle(x)
122static int has_redirection(
const char *, UINT);
124static int rb_w32_open_osfhandle(
intptr_t osfhandle,
int flags);
128static FARPROC get_proc_address(
const char *module,
const char *func, HANDLE *mh);
130#define RUBY_CRITICAL if (0) {} else
137 { ERROR_INVALID_FUNCTION,
EINVAL },
138 { ERROR_FILE_NOT_FOUND,
ENOENT },
139 { ERROR_PATH_NOT_FOUND,
ENOENT },
140 { ERROR_TOO_MANY_OPEN_FILES,
EMFILE },
141 { ERROR_ACCESS_DENIED,
EACCES },
142 { ERROR_INVALID_HANDLE,
EBADF },
143 { ERROR_ARENA_TRASHED,
ENOMEM },
144 { ERROR_NOT_ENOUGH_MEMORY,
ENOMEM },
145 { ERROR_INVALID_BLOCK,
ENOMEM },
146 { ERROR_BAD_ENVIRONMENT,
E2BIG },
148 { ERROR_INVALID_ACCESS,
EINVAL },
149 { ERROR_INVALID_DATA,
EINVAL },
150 { ERROR_INVALID_DRIVE,
ENOENT },
151 { ERROR_CURRENT_DIRECTORY,
EACCES },
152 { ERROR_NOT_SAME_DEVICE,
EXDEV },
153 { ERROR_NO_MORE_FILES,
ENOENT },
154 { ERROR_WRITE_PROTECT,
EROFS },
155 { ERROR_BAD_UNIT,
ENODEV },
156 { ERROR_NOT_READY,
ENXIO },
157 { ERROR_BAD_COMMAND,
EACCES },
159 { ERROR_BAD_LENGTH,
EACCES },
161 { ERROR_NOT_DOS_DISK,
EACCES },
162 { ERROR_SECTOR_NOT_FOUND,
EACCES },
163 { ERROR_OUT_OF_PAPER,
EACCES },
164 { ERROR_WRITE_FAULT,
EIO },
165 { ERROR_READ_FAULT,
EIO },
166 { ERROR_GEN_FAILURE,
EACCES },
167 { ERROR_LOCK_VIOLATION,
EACCES },
168 { ERROR_SHARING_VIOLATION,
EACCES },
169 { ERROR_WRONG_DISK,
EACCES },
170 { ERROR_SHARING_BUFFER_EXCEEDED,
EACCES },
171 { ERROR_BAD_NETPATH,
ENOENT },
172 { ERROR_NETWORK_ACCESS_DENIED,
EACCES },
173 { ERROR_BAD_NET_NAME,
ENOENT },
174 { ERROR_FILE_EXISTS,
EEXIST },
175 { ERROR_CANNOT_MAKE,
EACCES },
176 { ERROR_FAIL_I24,
EACCES },
177 { ERROR_INVALID_PARAMETER,
EINVAL },
178 { ERROR_NO_PROC_SLOTS,
EAGAIN },
179 { ERROR_DRIVE_LOCKED,
EACCES },
180 { ERROR_BROKEN_PIPE,
EPIPE },
181 { ERROR_DISK_FULL,
ENOSPC },
182 { ERROR_INVALID_TARGET_HANDLE,
EBADF },
183 { ERROR_INVALID_HANDLE,
EINVAL },
184 { ERROR_WAIT_NO_CHILDREN,
ECHILD },
185 { ERROR_CHILD_NOT_COMPLETE,
ECHILD },
186 { ERROR_DIRECT_ACCESS_HANDLE,
EBADF },
187 { ERROR_NEGATIVE_SEEK,
EINVAL },
188 { ERROR_SEEK_ON_DEVICE,
EACCES },
191 { ERROR_NOT_LOCKED,
EACCES },
192 { ERROR_BAD_PATHNAME,
ENOENT },
193 { ERROR_MAX_THRDS_REACHED,
EAGAIN },
194 { ERROR_LOCK_FAILED,
EACCES },
195 { ERROR_ALREADY_EXISTS,
EEXIST },
196 { ERROR_INVALID_STARTING_CODESEG,
ENOEXEC },
197 { ERROR_INVALID_STACKSEG,
ENOEXEC },
198 { ERROR_INVALID_MODULETYPE,
ENOEXEC },
199 { ERROR_INVALID_EXE_SIGNATURE,
ENOEXEC },
200 { ERROR_EXE_MARKED_INVALID,
ENOEXEC },
201 { ERROR_BAD_EXE_FORMAT,
ENOEXEC },
202 { ERROR_ITERATED_DATA_EXCEEDS_64k,
ENOEXEC },
203 { ERROR_INVALID_MINALLOCSIZE,
ENOEXEC },
204 { ERROR_DYNLINK_FROM_INVALID_RING,
ENOEXEC },
205 { ERROR_IOPL_NOT_ENABLED,
ENOEXEC },
206 { ERROR_INVALID_SEGDPL,
ENOEXEC },
207 { ERROR_AUTODATASEG_EXCEEDS_64k,
ENOEXEC },
208 { ERROR_RING2SEG_MUST_BE_MOVABLE,
ENOEXEC },
209 { ERROR_RELOC_CHAIN_XEEDS_SEGLIM,
ENOEXEC },
210 { ERROR_INFLOOP_IN_RELOC_CHAIN,
ENOEXEC },
211 { ERROR_FILENAME_EXCED_RANGE,
ENOENT },
212 { ERROR_NESTING_NOT_ALLOWED,
EAGAIN },
213#ifndef ERROR_PIPE_LOCAL
214#define ERROR_PIPE_LOCAL 229L
217 { ERROR_BAD_PIPE,
EPIPE },
218 { ERROR_PIPE_BUSY,
EAGAIN },
219 { ERROR_NO_DATA,
EPIPE },
220 { ERROR_PIPE_NOT_CONNECTED,
EPIPE },
221 { ERROR_OPERATION_ABORTED,
EINTR },
222 { ERROR_NOT_ENOUGH_QUOTA,
ENOMEM },
223 { ERROR_MOD_NOT_FOUND,
ENOENT },
224 { ERROR_PRIVILEGE_NOT_HELD,
EACCES, },
225 { ERROR_CANT_RESOLVE_FILENAME,
ELOOP, },
281 for (
i = 0;
i < (
int)(
sizeof(errmap) /
sizeof(*errmap));
i++) {
283 return errmap[
i].err;
287 if (
winerr >= WSABASEERR) {
293#define map_errno rb_w32_map_errno
295static const char *NTLoginName;
297static OSVERSIONINFO osver;
303 memset(&osver, 0,
sizeof(OSVERSIONINFO));
304 osver.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
305 GetVersionEx(&osver);
313 return osver.dwPlatformId;
321 return osver.dwMajorVersion;
332 DWORD err = GetLastError(); \
333 if (err == ERROR_LOCK_VIOLATION || err == ERROR_IO_PENDING) \
334 errno = EWOULDBLOCK; \
335 else if (err == ERROR_NOT_LOCKED) \
338 errno = map_errno(err); \
341#define LK_LEN ULONG_MAX
349 const HANDLE fh = (HANDLE)
self;
350 const int oper =
argc;
366 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
395translate_wchar(WCHAR *p,
int from,
int to)
406translate_char(
char *p,
int from,
int to, UINT cp)
409 if ((
unsigned char)*p == from)
411 p = CharNextExA(cp, p, 0);
416#ifndef CSIDL_LOCAL_APPDATA
417#define CSIDL_LOCAL_APPDATA 28
419#ifndef CSIDL_COMMON_APPDATA
420#define CSIDL_COMMON_APPDATA 35
423#define CSIDL_WINDOWS 36
426#define CSIDL_SYSTEM 37
429#define CSIDL_PROFILE 40
434get_special_folder(
int n, WCHAR *
buf,
size_t len)
439 typedef BOOL (WINAPI *get_path_func)(LPITEMIDLIST, WCHAR*,
DWORD,
int);
440 static get_path_func func = (get_path_func)-1;
442 if (func == (get_path_func)-1) {
443 func = (get_path_func)
444 get_proc_address(
"shell32",
"SHGetPathFromIDListEx",
NULL);
446 if (!func &&
len < MAX_PATH)
return FALSE;
448 if (SHGetSpecialFolderLocation(
NULL,
n, &pidl) == 0) {
453 f = SHGetPathFromIDListW(pidl,
buf);
456 alloc->lpVtbl->Free(alloc, pidl);
457 alloc->lpVtbl->Release(alloc);
464regulate_path(WCHAR *
path)
466 WCHAR *p = translate_wchar(
path,
L'\\',
L'/');
475get_proc_address(
const char *module,
const char *func, HANDLE *mh)
481 h = LoadLibrary(module);
483 h = GetModuleHandle(module);
487 ptr = GetProcAddress(
h, func);
508#if defined _MSC_VER && _MSC_VER <= 1200
510#define GetSystemWindowsDirectoryW GetWindowsDirectoryW
517 static const WCHAR temp[] =
L"temp";
521 if (GetSystemWindowsDirectoryW(
path,
len))
return 0;
523 p = translate_wchar(
path,
L'\\',
L'/');
524 if (*(p - 1) !=
L'/') *p++ =
L'/';
526 memcpy(p, temp,
sizeof(temp));
542 WCHAR *buffer =
NULL;
543 size_t buffer_len = MAX_PATH,
len = 0;
545 HOME_NONE, ENV_HOME, ENV_DRIVEPATH, ENV_USERPROFILE
546 } home_type = HOME_NONE;
548 if ((
len = GetEnvironmentVariableW(
L"HOME",
NULL, 0)) != 0) {
550 home_type = ENV_HOME;
552 else if ((
len = GetEnvironmentVariableW(
L"HOMEDRIVE",
NULL, 0)) != 0) {
554 if ((
len = GetEnvironmentVariableW(
L"HOMEPATH",
NULL, 0)) != 0) {
556 home_type = ENV_DRIVEPATH;
559 else if ((
len = GetEnvironmentVariableW(
L"USERPROFILE",
NULL, 0)) != 0) {
561 home_type = ENV_USERPROFILE;
565 buffer =
ALLOC_N(WCHAR, buffer_len);
569 GetEnvironmentVariableW(
L"HOME", buffer, buffer_len);
572 len = GetEnvironmentVariableW(
L"HOMEDRIVE", buffer, buffer_len);
573 GetEnvironmentVariableW(
L"HOMEPATH", buffer +
len, buffer_len -
len);
575 case ENV_USERPROFILE:
576 GetEnvironmentVariableW(
L"USERPROFILE", buffer, buffer_len);
579 if (!get_special_folder(
CSIDL_PROFILE, buffer, buffer_len) &&
580 !get_special_folder(CSIDL_PERSONAL, buffer, buffer_len)) {
584 REALLOC_N(buffer, WCHAR, lstrlenW(buffer) + 1);
589 regulate_path(buffer);
598 static const WCHAR TMPDIR[] =
L"TMPDIR";
603#define set_env_val(vname) do { \
604 typedef char wk_name_offset[(numberof(wk.name) - (numberof(vname) - 1)) * 2 + 1]; \
605 WCHAR *const buf = wk.name + sizeof(wk_name_offset) / 2; \
606 MEMCPY(buf, vname, WCHAR, numberof(vname) - 1); \
621 else if (GetEnvironmentVariableW(
L"USERPROFILE",
env,
numberof(
env))) {
627 else if (get_special_folder(CSIDL_PERSONAL,
env,
numberof(
env))) {
639 NTLoginName =
"<Unknown>";
661static void init_stdhandle(
void);
663#if RUBY_MSVCRT_VERSION >= 80
666invalid_parameter(
const wchar_t *expr,
const wchar_t *func,
const wchar_t *file,
unsigned int line,
uintptr_t dummy)
671int ruby_w32_rtc_error;
675rtc_error_handler(
int e,
const char *
src,
int line,
const char *exe,
const char *
fmt, ...)
680 if (!ruby_w32_rtc_error)
return 0;
691static CRITICAL_SECTION select_mutex;
693static CRITICAL_SECTION socklist_mutex;
696static CRITICAL_SECTION conlist_mutex;
698#define conlist_disabled ((st_table *)-1)
700static char *uenvarea;
722constat_delete(HANDLE
h)
724 EnterCriticalSection(&conlist_mutex);
730 LeaveCriticalSection(&conlist_mutex);
738 DeleteCriticalSection(&select_mutex);
739 DeleteCriticalSection(&socklist_mutex);
740 DeleteCriticalSection(&conlist_mutex);
751 EnterCriticalSection(&socklist_mutex);
756 LeaveCriticalSection(&socklist_mutex);
758 EnterCriticalSection(&conlist_mutex);
764 LeaveCriticalSection(&conlist_mutex);
769install_vm_exit_handler(
void)
771 static bool installed = 0;
790 version = MAKEWORD(2, 0);
791 if (WSAStartup(version, &retdata))
792 rb_fatal(
"Unable to locate winsock library!");
793 if (LOBYTE(retdata.wVersion) != 2)
794 rb_fatal(
"could not find version 2 of winsock dll");
796 InitializeCriticalSection(&select_mutex);
797 InitializeCriticalSection(&socklist_mutex);
798 InitializeCriticalSection(&conlist_mutex);
803#define MAKE_SOCKDATA(af, fl) ((int)((((int)af)<<4)|((fl)&0xFFFF)))
804#define GET_FAMILY(v) ((int)(((v)>>4)&0xFFFF))
805#define GET_FLAGS(v) ((int)((v)&0xFFFF))
809socklist_insert(SOCKET sock,
int flag)
813 EnterCriticalSection(&socklist_mutex);
816 install_vm_exit_handler();
819 LeaveCriticalSection(&socklist_mutex);
826socklist_lookup(SOCKET sock,
int *flagp)
831 EnterCriticalSection(&socklist_mutex);
839 LeaveCriticalSection(&socklist_mutex);
846socklist_delete(SOCKET *sockp,
int *flagp)
852 EnterCriticalSection(&socklist_mutex);
859 *sockp = (SOCKET)
key;
866 LeaveCriticalSection(&socklist_mutex);
871static int w32_cmdvector(
const WCHAR *,
char ***, UINT,
rb_encoding *);
879#if RUBY_MSVCRT_VERSION >= 80
880 static void set_pioinfo_extra(
void);
882 _CrtSetReportMode(_CRT_ASSERT, 0);
883 _set_invalid_parameter_handler(invalid_parameter);
884 _RTC_SetErrorFunc(rtc_error_handler);
887 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX);
913 return (
char *)NTLoginName;
916#define MAXCHILDNUM 256
919static struct ChildRecord {
925#define FOREACH_CHILD(v) do { \
926 struct ChildRecord* v; \
927 for (v = ChildRecord; v < ChildRecord + sizeof(ChildRecord) / sizeof(ChildRecord[0]); ++v)
928#define END_FOREACH_CHILD } while (0)
931static struct ChildRecord *
936 if (child->pid == pid) {
944static struct ChildRecord *
945FindChildSlotByHandle(HANDLE
h)
949 if (child->hProcess ==
h) {
958CloseChildHandle(
struct ChildRecord *child)
960 HANDLE
h = child->hProcess;
961 child->hProcess =
NULL;
967static struct ChildRecord *
968FindFreeChildSlot(
void)
973 child->hProcess =
NULL;
987#define InternalCmdsMax 8
1042internal_match(
const void *
key,
const void *elem)
1049is_command_com(
const char *interp)
1053 if ((
i == 0 || (
i > 0 &&
isdirsep(interp[
i-1]))) &&
1060static int internal_cmd_match(
const char *cmdname,
int nt);
1064is_internal_cmd(
const char *cmd,
int nt)
1066 char cmdname[9], *b = cmdname, c;
1069 if (!(c = *cmd++))
return 0;
1070 }
while (isspace(c));
1073 while (isalpha(c)) {
1075 if (b == cmdname +
sizeof(cmdname))
return 0;
1078 if (c ==
'.') c = *cmd;
1080 case '<':
case '>':
case '|':
1082 case '\0':
case ' ':
case '\t':
case '\n':
1088 return internal_cmd_match(cmdname, nt);
1093internal_cmd_match(
const char *cmdname,
int nt)
1097 nm =
bsearch(cmdname, szInternalCmds,
1098 sizeof(szInternalCmds) /
sizeof(*szInternalCmds),
1099 sizeof(*szInternalCmds),
1101 if (!nm || !(nm[0] & (nt ? 2 : 1)))
1110 return _get_osfhandle(fh);
1115join_argv(
char *cmd,
char *
const *
argv, BOOL escape, UINT cp,
int backslash)
1119 int len,
n, bs, quote;
1121 for (t =
argv, q = cmd,
len = 0; (p = *t) != 0; t++) {
1124 if (!*p ||
strpbrk(p,
" \t\"'")) {
1129 for (bs = 0; *p; ++p) {
1148 case '<':
case '>':
case '|':
case '^':
1149 if (escape && !quote) {
1150 len += (
n = p - s) + 1;
1161 p = CharNextExA(cp, p, 0) - 1;
1165 len += (
n = p - s) + 1;
1169 if (backslash > 0) {
1172 translate_char(q,
'/',
'\\', cp);
1175 if (quote) *q++ =
'"';
1188#define STRNDUPV(ptr, v, src, len) \
1189 (((char *)memcpy(((ptr) = ALLOCV((v), (len) + 1)), (src), (len)))[len] = 0)
1193check_spawn_mode(
int mode)
1207child_result(
struct ChildRecord *child,
int mode)
1215 if (mode == P_OVERLAY) {
1216 WaitForSingleObject(child->hProcess, INFINITE);
1217 GetExitCodeProcess(child->hProcess, &exitcode);
1218 CloseChildHandle(child);
1226CreateChild(
struct ChildRecord *child,
const WCHAR *cmd,
const WCHAR *prog, HANDLE hInput, HANDLE hOutput, HANDLE hError,
DWORD dwCreationFlags)
1229 STARTUPINFOW aStartupInfo;
1230 PROCESS_INFORMATION aProcessInformation;
1231 SECURITY_ATTRIBUTES sa;
1233 if (!cmd && !prog) {
1243 sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
1244 sa.lpSecurityDescriptor =
NULL;
1245 sa.bInheritHandle =
TRUE;
1247 memset(&aStartupInfo, 0,
sizeof(aStartupInfo));
1248 memset(&aProcessInformation, 0,
sizeof(aProcessInformation));
1249 aStartupInfo.cb =
sizeof(aStartupInfo);
1250 aStartupInfo.dwFlags = STARTF_USESTDHANDLES;
1252 aStartupInfo.hStdInput = hInput;
1255 aStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1258 aStartupInfo.hStdOutput = hOutput;
1261 aStartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1264 aStartupInfo.hStdError = hError;
1267 aStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
1270 dwCreationFlags |= NORMAL_PRIORITY_CLASS;
1272 if (lstrlenW(cmd) > 32767) {
1279 fRet = CreateProcessW(prog, (WCHAR *)cmd, &sa, &sa,
1280 sa.bInheritHandle, dwCreationFlags,
NULL,
NULL,
1281 &aStartupInfo, &aProcessInformation);
1290 CloseHandle(aProcessInformation.hThread);
1292 child->hProcess = aProcessInformation.hProcess;
1293 child->pid = (
rb_pid_t)aProcessInformation.dwProcessId;
1300is_batch(
const char *cmd)
1303 if (
len <= 4)
return 0;
1305 if (*cmd++ !=
'.')
return 0;
1311#define filecp rb_w32_filecp
1312#define mbstr_to_wstr rb_w32_mbstr_to_wstr
1313#define wstr_to_mbstr rb_w32_wstr_to_mbstr
1314#define acp_to_wstr(str, plen) mbstr_to_wstr(CP_ACP, str, -1, plen)
1315#define wstr_to_acp(str, plen) wstr_to_mbstr(CP_ACP, str, -1, plen)
1316#define filecp_to_wstr(str, plen) mbstr_to_wstr(filecp(), str, -1, plen)
1317#define wstr_to_filecp(str, plen) wstr_to_mbstr(filecp(), str, -1, plen)
1318#define utf8_to_wstr(str, plen) mbstr_to_wstr(CP_UTF8, str, -1, plen)
1319#define wstr_to_utf8(str, plen) wstr_to_mbstr(CP_UTF8, str, -1, plen)
1329 struct ChildRecord child;
1333 HANDLE outHandle =
NULL;
1352 if (!CreateChild(&child, wcmd, wprog,
NULL, outHandle, outHandle, 0)) {
1358 return child.hProcess;
1363w32_spawn(
int mode,
const char *cmd,
const char *prog, UINT cp)
1367 const char *shell =
NULL;
1368 WCHAR *wcmd =
NULL, *wshell =
NULL;
1374 char *cmd_sep =
NULL;
1376 if (check_spawn_mode(mode))
return -1;
1384 translate_char(p,
'/',
'\\', cp);
1391 if ((shell =
getenv(
"RUBYSHELL")) && (redir = has_redirection(cmd, cp))) {
1392 size_t shell_len =
strlen(shell);
1393 char *tmp =
ALLOCV(
v, shell_len +
strlen(cmd) +
sizeof(
" -c ") + 2);
1394 memcpy(tmp, shell, shell_len + 1);
1395 translate_char(tmp,
'/',
'\\', cp);
1396 sprintf(tmp + shell_len,
" -c \"%s\"", cmd);
1399 else if ((shell =
getenv(
"COMSPEC")) &&
1400 (nt = !is_command_com(shell),
1401 (redir < 0 ? has_redirection(cmd, cp) : redir) ||
1402 is_internal_cmd(cmd, nt))) {
1404 sprintf(tmp, nt ?
"%s /c \"%s\"" :
"%s /c %s", shell, cmd);
1408 int len = 0, quote = (*cmd ==
'"') ?
'"' : (*cmd ==
'\'') ?
'\'' : 0;
1410 for (prog = cmd + !!quote;; prog = CharNextExA(cp, prog, 0)) {
1411 if (*prog ==
'/') slash = 1;
1421 if ((
unsigned char)*prog == quote) {
1422 len = prog++ - cmd - 1;
1427 if (quote)
continue;
1433 sep = *(cmd_sep = &p[
len]);
1441 if (p && slash) translate_char(p,
'/',
'\\', cp);
1443 shell = p ? p : cmd;
1447 if (
strchr(shell,
' ')) quote = -1;
1448 if (shell == fbuf) {
1451 else if (shell != p &&
strchr(shell,
'/')) {
1455 if (p) translate_char(p,
'/',
'\\', cp);
1456 if (is_batch(shell)) {
1458 cmd = p =
ALLOCV(
v,
len + alen + (quote ? 2 : 0) + 1);
1459 if (quote) *p++ =
'"';
1462 if (quote) *p++ =
'"';
1463 memcpy(p, prog, alen + 1);
1471 if (cmd_sep) *cmd_sep = sep;
1477 struct ChildRecord *child = FindFreeChildSlot();
1478 if (CreateChild(child, wcmd, wshell,
NULL,
NULL,
NULL, 0)) {
1479 ret = child_result(child, mode);
1493 return w32_spawn(mode, cmd, prog,
filecp());
1500 return w32_spawn(mode, cmd, prog, CP_UTF8);
1505w32_aspawn_flags(
int mode,
const char *prog,
char *
const *
argv,
DWORD flags, UINT cp)
1509 BOOL ntcmd =
FALSE, tmpnt;
1517 if (check_spawn_mode(mode))
return -1;
1519 if (!prog) prog =
argv[0];
1520 if ((shell =
getenv(
"COMSPEC")) &&
1521 internal_cmd_match(prog, tmpnt = !is_command_com(shell))) {
1527 if (cmd == prog)
strlcpy(cmd = fbuf, prog,
sizeof(fbuf));
1528 translate_char(cmd,
'/',
'\\', cp);
1531 else if (
strchr(prog,
'/')) {
1533 if (
len <
sizeof(fbuf))
1534 strlcpy(cmd = fbuf, prog,
sizeof(fbuf));
1537 translate_char(cmd,
'/',
'\\', cp);
1540 if (c_switch || is_batch(prog)) {
1542 progs[0] = (
char *)prog;
1544 len = join_argv(
NULL, progs, ntcmd, cp, 1);
1545 if (c_switch)
len += 3;
1549 join_argv(cmd, progs, ntcmd, cp, 1);
1552 prog = c_switch ? shell : 0;
1565 struct ChildRecord *child = FindFreeChildSlot();
1566 if (CreateChild(child, wcmd, wprog,
NULL,
NULL,
NULL, flags)) {
1567 ret = child_result(child, mode);
1581 return w32_aspawn_flags(mode, prog,
argv, flags,
filecp());
1588 return w32_aspawn_flags(mode, prog,
argv, flags, CP_UTF8);
1623insert(
const char *
path,
VALUE vinfo,
void *enc)
1629 if (!tmpcurr)
return -1;
1633 if (!tmpcurr->
str)
return -1;
1636 *tail = &tmpcurr->
next;
1654 translate_char(
buf,
'\\',
'/', cp);
1659 if (status ||
last == tail)
return 0;
1673has_redirection(
const char *cmd, UINT cp)
1689 else if (quote == *
ptr)
1707 if (*
ptr++ ==
'%')
return TRUE;
1713 ptr = CharNextExA(cp,
ptr, 0);
1721static inline WCHAR *
1722skipspace(WCHAR *
ptr)
1731w32_cmdvector(
const WCHAR *cmd,
char ***vec, UINT cp,
rb_encoding *enc)
1734 int elements, strsz, done;
1735 int slashes, escape;
1736 WCHAR *
ptr, *base, *cmdline;
1737 char *cptr, *buffer;
1753 ptr = cmdline = wcsdup(cmd);
1764 while (*(
ptr = skipspace(
ptr))) {
1766 quote = slashes = globbing = escape = 0;
1767 for (done = 0; !done && *
ptr; ) {
1776 if (quote !=
L'\'') slashes++;
1816 if (!(slashes & 1)) {
1819 else if (quote == *
ptr) {
1820 if (quote ==
L'"' && quote ==
ptr[1])
1853 slashes = quote = 0;
1854 while (p < base +
len) {
1858 if (quote !=
L'\'') slashes++;
1863 if (!(slashes & 1) && quote && quote != c) {
1868 memcpy(p - ((slashes + 1) >> 1), p + (~slashes & 1),
1869 sizeof(WCHAR) * (base +
len - p));
1870 len -= ((slashes + 1) >> 1) + (~slashes & 1);
1871 p -= (slashes + 1) >> 1;
1872 if (!(slashes & 1)) {
1874 if (quote ==
L'"' && quote == *p)
1895 if (!curr)
goto do_nothing;
1899 if (globbing && (tail = cmdglob(curr, cmdtail, cp, enc))) {
1904 cmdtail = &curr->
next;
1914 for (elements = 0, strsz = 0, curr = cmdhead; curr; curr = curr->
next) {
1916 strsz += (curr->
len + 1);
1919 len = (elements+1)*
sizeof(
char *) + strsz;
1923 while ((curr = cmdhead) != 0) {
1924 cmdhead = curr->
next;
1929 for (vptr = *vec; *vptr; ++vptr);
1945 vptr = (
char **) buffer;
1947 cptr = buffer + (elements+1) *
sizeof(
char *);
1949 while ((curr = cmdhead) != 0) {
1951 cptr[curr->
len] =
'\0';
1953 cptr += curr->
len + 1;
1954 cmdhead = curr->
next;
1960 *vec = (
char **) buffer;
1982 get_proc_address(
"kernel32",
"GetFinalPathNameByHandleW",
NULL);
1983 if (!func) func = get_final_path_fail;
1984 get_final_path = func;
1985 return func(
f,
buf,
len, flag);
1995 const DWORD share_mode =
1996 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
1997 return CreateFileW(
path,
access, share_mode,
NULL, OPEN_EXISTING,
1998 FILE_FLAG_BACKUP_SEMANTICS|
flags,
NULL);
2008#define GetBit(bits, i) ((bits)[(i) / CHAR_BIT] & (1 << (i) % CHAR_BIT))
2009#define SetBit(bits, i) ((bits)[(i) / CHAR_BIT] |= (1 << (i) % CHAR_BIT))
2011#define BitOfIsDir(n) ((n) * 2)
2012#define BitOfIsRep(n) ((n) * 2 + 1)
2013#define DIRENT_PER_CHAR (CHAR_BIT / 2)
2017open_dir_handle(
const WCHAR *filename, WIN32_FIND_DATAW *fd)
2028 fh = open_special(filename, 0, 0);
2029 if (fh != INVALID_HANDLE_VALUE) {
2034 len = lstrlenW(filename);
2037 return INVALID_HANDLE_VALUE;
2041 p = &fullname[
len-1];
2042 if (!(
isdirsep(*p) || *p ==
L':')) *++p =
L'\\';
2049 fh = FindFirstFileW(fullname, fd);
2050 if (fh == INVALID_HANDLE_VALUE) {
2058w32_wopendir(
const WCHAR *wpath)
2061 WIN32_FIND_DATAW fd;
2074 if (wstati128(wpath, &sbuf,
FALSE) < 0) {
2077 if (!(sbuf.st_mode &
S_IFDIR) &&
2078 (!
ISALPHA(wpath[0]) || wpath[1] !=
L':' || wpath[2] !=
L'\0' ||
2079 ((1 << ((wpath[0] & 0x5f) -
'A')) & GetLogicalDrives()) == 0)) {
2083 fh = open_dir_handle(wpath, &fd);
2084 if (fh == INVALID_HANDLE_VALUE) {
2095 pathlen = lstrlenW(wpath);
2105 len = lstrlenW(fd.cFileName) + 1;
2106 altlen = lstrlenW(fd.cAlternateFileName) + 1;
2123 memcpy(&p->
start[idx +
len], fd.cAlternateFileName, altlen *
sizeof(WCHAR));
2132 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2134 if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2135 WCHAR *tmppath =
malloc((pathlen +
len + 1) *
sizeof(WCHAR));
2136 memcpy(tmppath, wpath, pathlen *
sizeof(WCHAR));
2137 tmppath[pathlen] =
L'\\';
2138 memcpy(tmppath + pathlen + 1, fd.cFileName,
len *
sizeof(WCHAR));
2145 idx +=
len + altlen;
2146 }
while (FindNextFileW(fh, &fd));
2157 UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
2166 int len = WideCharToMultiByte(cp, 0, wstr, clen,
NULL, 0,
NULL,
NULL);
2171 if (clen == -1) --
len;
2183 int len = MultiByteToWideChar(cp, 0,
str, clen,
NULL, 0);
2185 MultiByteToWideChar(cp, 0,
str, clen,
ptr,
len);
2188 if (clen == -1) --
len;
2202 ret = w32_wopendir(wpath);
2215 ret = w32_wopendir(wpath);
2226move_to_next_entry(
DIR *dirp)
2230 dirp->
curr += lstrlenW(dirp->
curr) + 1;
2231 dirp->
curr += lstrlenW(dirp->
curr) + 1;
2244win32_direct_conv(
const WCHAR *file,
const WCHAR *alt,
struct direct *entry,
const void *enc)
2246 UINT cp = *((UINT *)enc);
2262 long len = lstrlenW(wstr);
2269#if SIZEOF_INT < SIZEOF_LONG
2270# error long should equal to int on Windows
2273 len = WideCharToMultiByte(CP_UTF8, 0, wstr, clen,
NULL, 0,
NULL,
NULL);
2305ruby_direct_conv(
const WCHAR *file,
const WCHAR *alt,
struct direct *entry,
const void *enc)
2319readdir_internal(
DIR *dirp, BOOL (*conv)(
const WCHAR *,
const WCHAR *,
struct direct *,
const void *),
const void *enc)
2321 static int dummy = 0;
2356 move_to_next_entry(dirp);
2371 const UINT cp =
filecp();
2372 return readdir_internal(dirp, win32_direct_conv, &cp);
2375 const UINT cp = CP_UTF8;
2376 return readdir_internal(dirp, win32_direct_conv, &cp);
2379 return readdir_internal(dirp, ruby_direct_conv, enc);
2403 while (dirp->
curr && dirp->
loc < loc) {
2404 move_to_next_entry(dirp);
2441#if RUBY_MSVCRT_VERSION >= 140
2456 CRITICAL_SECTION _lock;
2458#define FILE_COUNT(stream) ((vcruntime_file*)stream)->_cnt
2459#define FILE_READPTR(stream) ((vcruntime_file*)stream)->_ptr
2460#define FILE_FILENO(stream) ((vcruntime_file*)stream)->_file
2462#define FILE_COUNT(stream) stream->_cnt
2463#define FILE_READPTR(stream) stream->_ptr
2464#define FILE_FILENO(stream) stream->_file
2468#if RUBY_MSVCRT_VERSION >= 140
2469typedef char lowio_text_mode;
2470typedef char lowio_pipe_lookahead[3];
2473 CRITICAL_SECTION lock;
2476 unsigned char osfile;
2477 lowio_text_mode textmode;
2478 lowio_pipe_lookahead _pipe_lookahead;
2492#if RUBY_MSVCRT_VERSION >= 80
2499#if !defined _CRTIMP || defined __MINGW32__
2501#define _CRTIMP __declspec(dllimport)
2504#if RUBY_MSVCRT_VERSION >= 140
2511static inline ioinfo* _pioinfo(
int);
2514#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
2515#define _osfhnd(i) (_pioinfo(i)->osfhnd)
2516#define _osfile(i) (_pioinfo(i)->osfile)
2517#define rb_acrt_lowio_lock_fh(i) EnterCriticalSection(&_pioinfo(i)->lock)
2518#define rb_acrt_lowio_unlock_fh(i) LeaveCriticalSection(&_pioinfo(i)->lock)
2520#if RUBY_MSVCRT_VERSION >= 80
2525set_pioinfo_extra(
void)
2527#if RUBY_MSVCRT_VERSION >= 140
2528# define FUNCTION_RET 0xc3
2530# define UCRTBASE "ucrtbased.dll"
2532# define UCRTBASE "ucrtbase.dll"
2535 char *p = (
char*)get_proc_address(UCRTBASE,
"_isatty",
NULL);
2543# define FUNCTION_BEFORE_RET_MARK "\x48\x83\xc4"
2544# define FUNCTION_SKIP_BYTES 1
2547# define PIOINFO_MARK "\x48\x8d\x0d"
2550# define PIOINFO_MARK "\x48\x8d\x15"
2555# define FUNCTION_BEFORE_RET_MARK "\x5d"
2556# define FUNCTION_SKIP_BYTES 0
2558# define PIOINFO_MARK "\x8B\x04\x85"
2561 for (pend += 10; pend < p + 300; pend++) {
2563 if (
memcmp(pend, FUNCTION_BEFORE_RET_MARK,
sizeof(FUNCTION_BEFORE_RET_MARK) - 1) == 0 &&
2564 *(pend + (
sizeof(FUNCTION_BEFORE_RET_MARK) - 1) + FUNCTION_SKIP_BYTES) & FUNCTION_RET == FUNCTION_RET) {
2566 for (pend -= (
sizeof(PIOINFO_MARK) - 1); pend > p; pend--) {
2567 if (
memcmp(pend, PIOINFO_MARK,
sizeof(PIOINFO_MARK) - 1) == 0) {
2580 p +=
sizeof(PIOINFO_MARK) - 1;
2591 fd = _open(
"NUL", O_RDONLY);
2593 if (
_osfhnd(fd) == _get_osfhandle(fd)) {
2605#define pioinfo_extra 0
2616#define _set_osfhnd(fh, osfh) (void)(_osfhnd(fh) = osfh)
2617#define _set_osflags(fh, flags) (_osfile(fh) = (flags))
2622#define FNOINHERIT 0x10
2628static int is_console(SOCKET);
2639rb_w32_open_osfhandle(
intptr_t osfhandle,
int flags)
2648 if (flags & O_APPEND)
2654 if (flags & O_NOINHERIT)
2658 hF = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
2659 fh = _open_osfhandle((
intptr_t)hF, 0);
2685#define open_null(fd) \
2687 (nullfd = open("NUL", O_RDWR)) : 0), \
2688 ((nullfd == (fd)) ? (keep = 1) : dup2(nullfd, fd)), \
2703 if (nullfd >= 0 && !keep)
close(nullfd);
2713 if (socklist_lookup(sock,
NULL))
2738 static char buffer[512];
2745#if WSAEWOULDBLOCK != EWOULDBLOCK
2750 for (s = 0; s < (
int)(
sizeof(errmap)/
sizeof(*errmap)); s++)
2751 if (errmap[s].
winerr == WSAEWOULDBLOCK)
2753 for (
i = s;
i < (
int)(
sizeof(errmap)/
sizeof(*errmap));
i++)
2754 if (errmap[
i].
err == e) {
2755 e = errmap[
i].winerr;
2760 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
2761 FORMAT_MESSAGE_IGNORE_INSERTS, &source, e,
2762 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
2763 buffer,
sizeof(buffer),
NULL) == 0 &&
2764 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
2765 FORMAT_MESSAGE_IGNORE_INSERTS, &source, e, 0,
2766 buffer,
sizeof(buffer),
NULL) == 0)
2767 strlcpy(buffer,
"Unknown Error",
sizeof(buffer));
2862 for (
i = 0;
i < set->fd_count;
i++) {
2863 if (set->fd_array[
i] == s) {
2864 memmove(&set->fd_array[
i], &set->fd_array[
i+1],
2865 sizeof(set->fd_array[0]) * (--set->fd_count -
i));
2879 if (s == (SOCKET)INVALID_HANDLE_VALUE)
2889 max = min(
src->fd_count, (UINT)max);
2890 if ((UINT)dst->capa < (UINT)max) {
2892 dst->
fdset =
xrealloc(dst->
fdset,
sizeof(
unsigned int) +
sizeof(SOCKET) * dst->capa);
2896 max *
sizeof(
src->fd_array[0]));
2897 dst->
fdset->fd_count =
src->fd_count;
2904 if ((UINT)dst->capa <
src->fdset->fd_count) {
2906 dst->
fdset =
xrealloc(dst->
fdset,
sizeof(
unsigned int) +
sizeof(SOCKET) * dst->capa);
2910 src->fdset->fd_count *
sizeof(
src->fdset->fd_array[0]));
2911 dst->
fdset->fd_count =
src->fdset->fd_count;
2930 while (s < src->fd_count) {
2931 SOCKET fd =
src->fd_array[s];
2933 if (!func || (*func)(fd)) {
2937 for (d = 0; d < dst->
fdset->fd_count; d++) {
2938 if (dst->
fdset->fd_array[d] == fd)
2941 if (d == dst->
fdset->fd_count) {
2942 if ((
int)dst->
fdset->fd_count >= dst->capa) {
2944 dst->
fdset =
xrealloc(dst->
fdset,
sizeof(
unsigned int) +
sizeof(SOCKET) * dst->capa);
2946 dst->
fdset->fd_array[dst->
fdset->fd_count++] = fd;
2950 &
src->fd_array[s+1],
2951 sizeof(
src->fd_array[0]) * (--
src->fd_count - s));
2961 return dst ? dst->
fdset->fd_count : m;
2969 if (!
src || !dst)
return 0;
2971 for (s = 0; s <
src->fd_count; ++s) {
2972 SOCKET fd =
src->fd_array[s];
2974 for (d = 0; d < dst->fd_count; ++d) {
2975 if (dst->fd_array[d] == fd)
2979 dst->fd_array[dst->fd_count++] = fd;
2983 return dst->fd_count;
2988is_not_socket(SOCKET sock)
3000 ret = (GetFileType((HANDLE)sock) == FILE_TYPE_PIPE);
3008is_readable_pipe(SOCKET sock)
3018 ret = (GetLastError() == ERROR_BROKEN_PIPE);
3027is_console(SOCKET sock)
3034 ret = (PeekConsoleInput((HANDLE)sock, &ir, 1, &
n));
3042is_readable_console(SOCKET sock)
3049 if (PeekConsoleInput((HANDLE)sock, &ir, 1, &
n) &&
n > 0) {
3050 if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown &&
3051 ir.Event.KeyEvent.uChar.AsciiChar) {
3055 ReadConsoleInput((HANDLE)sock, &ir, 1, &
n);
3065is_invalid_handle(SOCKET sock)
3067 return (HANDLE)sock == INVALID_HANDLE_VALUE;
3085 EnterCriticalSection(&select_mutex);
3086 r =
select(nfds, rd, wr, ex, timeout);
3087 LeaveCriticalSection(&select_mutex);
3088 if (r == SOCKET_ERROR) {
3144 struct timeval *timeout,
void *th)
3153 struct timeval limit = {0, 0};
3155 if (nfds < 0 || (timeout && (timeout->
tv_sec < 0 || timeout->
tv_usec < 0))) {
3161 if (timeout->
tv_sec < 0 ||
3163 timeout->
tv_usec >= 1000000) {
3170 if (limit.
tv_usec >= 1000000) {
3183 nonsock += extract_fd(&else_rd, rd, is_not_socket);
3186 nonsock += extract_fd(&else_wr, wr, is_not_socket);
3189 if (extract_fd(
NULL, else_rd.
fdset, is_invalid_handle) > 0 ||
3190 extract_fd(
NULL, else_wr.
fdset, is_invalid_handle) > 0) {
3198 extract_fd(&pipe_rd, else_rd.
fdset, is_pipe);
3201 extract_fd(&cons_rd, else_rd.
fdset, is_console);
3204 extract_fd(&except, ex, is_not_socket);
3207 if (rd && (
int)rd->fd_count > r) r = (
int)rd->fd_count;
3208 if (wr && (
int)wr->fd_count > r) r = (
int)wr->fd_count;
3209 if (ex && (
int)ex->fd_count > r) r = (
int)ex->fd_count;
3210 if (nfds > r) nfds = r;
3224 extract_fd(&else_rd, pipe_rd.
fdset, is_readable_pipe);
3225 extract_fd(&else_rd, cons_rd.
fdset, is_readable_console);
3228 if (else_rd.
fdset->fd_count || else_wr.
fdset->fd_count) {
3229 r = do_select(nfds, rd, wr, ex, &zero);
3231 r += copy_fd(rd, else_rd.
fdset);
3232 r += copy_fd(wr, else_wr.
fdset);
3248 if (rd) copy_fd(&orig_rd, rd);
3249 if (wr) copy_fd(&orig_wr, wr);
3250 if (ex) copy_fd(&orig_ex, ex);
3251 r = do_select(nfds, rd, wr, ex, &zero);
3253 if (rd) copy_fd(rd, &orig_rd);
3254 if (wr) copy_fd(wr, &orig_wr);
3255 if (ex) copy_fd(ex, &orig_ex);
3262 if (compare(&rest, &
wait) < 0) dowait = &rest;
3264 Sleep(dowait->
tv_sec * 1000 + (dowait->
tv_usec + 999) / 1000);
3288get_wsa_extension_function(SOCKET s, GUID *guid)
3293 WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, guid,
sizeof(*guid),
3310 r = accept(
TO_SOCKET(s), addr, addrlen);
3311 if (r != INVALID_SOCKET) {
3312 SetHandleInformation((HANDLE)r, HANDLE_FLAG_INHERIT, 0);
3315 socklist_insert(r, 0);
3337 if (r == SOCKET_ERROR)
3351 r = connect(
TO_SOCKET(s), addr, addrlen);
3352 if (r == SOCKET_ERROR) {
3353 int err = WSAGetLastError();
3354 if (
err != WSAEWOULDBLOCK)
3372 r = getpeername(
TO_SOCKET(s), addr, addrlen);
3373 if (r == SOCKET_ERROR)
3389 r = getsockname(sock, addr, addrlen);
3390 if (r == SOCKET_ERROR) {
3391 DWORD wsaerror = WSAGetLastError();
3392 if (wsaerror == WSAEINVAL) {
3394 if (socklist_lookup(sock, &flags)) {
3397 memset(addr, 0, *addrlen);
3398 addr->sa_family = af;
3417 r = getsockopt(
TO_SOCKET(s), level, optname, optval, optlen);
3418 if (r == SOCKET_ERROR)
3432 r = ioctlsocket(
TO_SOCKET(s), cmd, argp);
3433 if (r == SOCKET_ERROR)
3448 if (r == SOCKET_ERROR)
3466 if (result != SOCKET_ERROR)
3468 else if ((
err = WSAGetLastError()) == WSA_IO_PENDING) {
3472 result = WSAGetOverlappedResult(s, wol, &
size,
TRUE, &flg);
3479 result = SOCKET_ERROR;
3482 if ((
err = WSAGetLastError()) == WSAECONNABORTED && !
input)
3484 else if (
err == WSAEMSGSIZE &&
input) {
3492 case WAIT_OBJECT_0 + 1:
3495 CancelIo((HANDLE)s);
3500 if (
err == WSAECONNABORTED && !
input)
3506 CloseHandle(wol->hEvent);
3513overlapped_socket_io(BOOL
input,
int fd,
char *
buf,
int len,
int flags,
3514 struct sockaddr *addr,
int *addrlen)
3525 socklist_lookup(s, &mode);
3529 if (addr && addrlen)
3530 r = recvfrom(s,
buf,
len, flags, addr, addrlen);
3532 r = recv(s,
buf,
len, flags);
3533 if (r == SOCKET_ERROR)
3537 if (addr && addrlen)
3538 r = sendto(s,
buf,
len, flags, addr, *addrlen);
3540 r = send(s,
buf,
len, flags);
3541 if (r == SOCKET_ERROR) {
3543 if (
err == WSAECONNABORTED)
3556 memset(&wol, 0,
sizeof(wol));
3561 if (addr && addrlen)
3562 ret = WSARecvFrom(s, &wbuf, 1, &
size, &flg, addr, addrlen,
3565 ret = WSARecv(s, &wbuf, 1, &
size, &flg, &wol,
NULL);
3568 if (addr && addrlen)
3569 ret = WSASendTo(s, &wbuf, 1, &
size, flags, addr, *addrlen,
3572 ret = WSASend(s, &wbuf, 1, &
size, flags, &wol,
NULL);
3576 finish_overlapped_socket(
input, s, &wol, ret, &rlen,
size);
3593 struct sockaddr *from,
int *fromlen)
3595 return overlapped_socket_io(
TRUE, fd,
buf,
len, flags, from, fromlen);
3608 const struct sockaddr *to,
int tolen)
3610 return overlapped_socket_io(
FALSE, fd, (
char *)
buf,
len, flags,
3611 (
struct sockaddr *)to, &tolen);
3614#if !defined(MSG_TRUNC) && !defined(__MINGW32__)
3625#ifndef WSAID_WSARECVMSG
3626#define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
3628#ifndef WSAID_WSASENDMSG
3629#define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
3633#define msghdr_to_wsamsg(msg, wsamsg) \
3636 (wsamsg)->name = (msg)->msg_name; \
3637 (wsamsg)->namelen = (msg)->msg_namelen; \
3638 (wsamsg)->lpBuffers = ALLOCA_N(WSABUF, (msg)->msg_iovlen); \
3639 (wsamsg)->dwBufferCount = (msg)->msg_iovlen; \
3640 for (i = 0; i < (msg)->msg_iovlen; ++i) { \
3641 (wsamsg)->lpBuffers[i].buf = (msg)->msg_iov[i].iov_base; \
3642 (wsamsg)->lpBuffers[i].len = (msg)->msg_iov[i].iov_len; \
3644 (wsamsg)->Control.buf = (msg)->msg_control; \
3645 (wsamsg)->Control.len = (msg)->msg_controllen; \
3646 (wsamsg)->dwFlags = (msg)->msg_flags; \
3653 typedef int (WSAAPI *WSARecvMsg_t)(SOCKET,
WSAMSG *,
DWORD *, WSAOVERLAPPED *, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
3654 static WSARecvMsg_t pWSARecvMsg =
NULL;
3665 pWSARecvMsg = (WSARecvMsg_t)get_wsa_extension_function(s, &guid);
3673 socklist_lookup(s, &mode);
3676 if ((ret = pWSARecvMsg(s, &wsamsg, &
len,
NULL,
NULL)) == SOCKET_ERROR) {
3685 memset(&wol, 0,
sizeof(wol));
3688 ret = pWSARecvMsg(s, &wsamsg, &
size, &wol,
NULL);
3691 ret = finish_overlapped_socket(
TRUE, s, &wol, ret, &
len,
size);
3693 if (ret == SOCKET_ERROR)
3708 typedef int (WSAAPI *WSASendMsg_t)(SOCKET,
const WSAMSG *,
DWORD,
DWORD *, WSAOVERLAPPED *, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
3709 static WSASendMsg_t pWSASendMsg =
NULL;
3720 pWSASendMsg = (WSASendMsg_t)get_wsa_extension_function(s, &guid);
3727 socklist_lookup(s, &mode);
3730 if ((ret = pWSASendMsg(s, &wsamsg, flags, &
len,
NULL,
NULL)) == SOCKET_ERROR) {
3739 memset(&wol, 0,
sizeof(wol));
3742 ret = pWSASendMsg(s, &wsamsg, flags, &
size, &wol,
NULL);
3745 finish_overlapped_socket(
FALSE, s, &wol, ret, &
len,
size);
3759 r = setsockopt(
TO_SOCKET(s), level, optname, optval, optlen);
3760 if (r == SOCKET_ERROR)
3775 if (r == SOCKET_ERROR)
3783open_ifs_socket(
int af,
int type,
int protocol)
3785 unsigned long proto_buffers_len = 0;
3787 SOCKET out = INVALID_SOCKET;
3789 if (WSAEnumProtocols(
NULL,
NULL, &proto_buffers_len) == SOCKET_ERROR) {
3790 error_code = WSAGetLastError();
3791 if (error_code == WSAENOBUFS) {
3792 WSAPROTOCOL_INFO *proto_buffers;
3793 int protocols_available = 0;
3795 proto_buffers = (WSAPROTOCOL_INFO *)
malloc(proto_buffers_len);
3796 if (!proto_buffers) {
3797 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
3798 return INVALID_SOCKET;
3801 protocols_available =
3802 WSAEnumProtocols(
NULL, proto_buffers, &proto_buffers_len);
3803 if (protocols_available != SOCKET_ERROR) {
3805 for (
i = 0;
i < protocols_available;
i++) {
3806 if ((af !=
AF_UNSPEC && af != proto_buffers[
i].iAddressFamily) ||
3807 (
type != proto_buffers[
i].iSocketType) ||
3808 (protocol != 0 && protocol != proto_buffers[
i].iProtocol))
3811 if ((proto_buffers[
i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0)
3814 out = WSASocket(af,
type, protocol, &(proto_buffers[
i]), 0,
3815 WSA_FLAG_OVERLAPPED);
3818 if (out == INVALID_SOCKET)
3819 out = WSASocket(af,
type, protocol,
NULL, 0, 0);
3820 if (out != INVALID_SOCKET)
3821 SetHandleInformation((HANDLE)out, HANDLE_FLAG_INHERIT, 0);
3824 free(proto_buffers);
3841 s = open_ifs_socket(af,
type, protocol);
3842 if (s == INVALID_SOCKET) {
3847 fd = rb_w32_open_osfhandle(s, O_RDWR|
O_BINARY|O_NOINHERIT);
3860struct hostent * WSAAPI
3865 r = gethostbyaddr(addr,
len,
type);
3875struct hostent * WSAAPI
3880 r = gethostbyname(
name);
3896 if (r == SOCKET_ERROR)
3902#undef getprotobyname
3905struct protoent * WSAAPI
3910 r = getprotobyname(
name);
3917#undef getprotobynumber
3920struct protoent * WSAAPI
3925 r = getprotobynumber(num);
3935struct servent * WSAAPI
3950struct servent * WSAAPI
3955 r = getservbyport(port,
proto);
3964socketpair_internal(
int af,
int type,
int protocol, SOCKET *sv)
3966 SOCKET svr = INVALID_SOCKET, r = INVALID_SOCKET, w = INVALID_SOCKET;
3967 struct sockaddr_in sock_in4;
3969 struct sockaddr_in6 sock_in6;
3971 struct sockaddr *addr;
3977#if defined PF_INET && PF_INET != AF_INET
3980 sock_in4.sin_family = AF_INET;
3981 sock_in4.sin_port = 0;
3983 addr = (
struct sockaddr *)&sock_in4;
3984 len =
sizeof(sock_in4);
3988 memset(&sock_in6, 0,
sizeof(sock_in6));
3989 sock_in6.sin6_family = AF_INET6;
3990 sock_in6.sin6_addr = IN6ADDR_LOOPBACK_INIT;
3991 addr = (
struct sockaddr *)&sock_in6;
3992 len =
sizeof(sock_in6);
3999 if (
type != SOCK_STREAM) {
4004 sv[0] = (SOCKET)INVALID_HANDLE_VALUE;
4005 sv[1] = (SOCKET)INVALID_HANDLE_VALUE;
4008 svr = open_ifs_socket(af,
type, protocol);
4009 if (svr == INVALID_SOCKET)
4011 if (bind(svr, addr,
len) < 0)
4013 if (getsockname(svr, addr, &
len) < 0)
4015 if (
type == SOCK_STREAM)
4018 w = open_ifs_socket(af,
type, protocol);
4019 if (w == INVALID_SOCKET)
4021 if (connect(w, addr,
len) < 0)
4024 r = accept(svr, addr, &
len);
4025 if (r == INVALID_SOCKET)
4027 SetHandleInformation((HANDLE)r, HANDLE_FLAG_INHERIT, 0);
4034 if (r != INVALID_SOCKET)
4036 if (w != INVALID_SOCKET)
4043 if (svr != INVALID_SOCKET)
4056 if (socketpair_internal(af,
type, protocol, pair) < 0)
4058 sv[0] = rb_w32_open_osfhandle(pair[0], O_RDWR|
O_BINARY|O_NOINHERIT);
4060 closesocket(pair[0]);
4061 closesocket(pair[1]);
4064 sv[1] = rb_w32_open_osfhandle(pair[1], O_RDWR|
O_BINARY|O_NOINHERIT);
4067 closesocket(pair[1]);
4076#if !defined(_MSC_VER) || _MSC_VER >= 1400
4079str2guid(
const char *
str, GUID *guid)
4081#define hex2byte(str) \
4082 ((isdigit(*(str)) ? *(str) - '0' : toupper(*(str)) - 'A' + 10) << 4 | (isdigit(*((str) + 1)) ? *((str) + 1) - '0' : toupper(*((str) + 1)) - 'A' + 10))
4096 for (
i = 0;
i < 6;
i++) {
4103#ifndef HAVE_TYPE_NET_LUID
4123 IP_ADAPTER_ADDRESSES *root, *addr;
4127 if (ret != ERROR_BUFFER_OVERFLOW) {
4133 if (ret != ERROR_SUCCESS) {
4139 if (pConvertInterfaceGuidToLuid == (
cigl_t)-1)
4140 pConvertInterfaceGuidToLuid =
4141 (
cigl_t)get_proc_address(
"iphlpapi.dll",
4142 "ConvertInterfaceGuidToLuid",
NULL);
4143 if (pConvertInterfaceLuidToNameA == (
cilnA_t)-1)
4144 pConvertInterfaceLuidToNameA =
4145 (
cilnA_t)get_proc_address(
"iphlpapi.dll",
4146 "ConvertInterfaceLuidToNameA",
NULL);
4148 for (prev =
NULL, addr = root; addr; addr = addr->Next) {
4159 str2guid(addr->AdapterName, &guid);
4160 if (pConvertInterfaceGuidToLuid && pConvertInterfaceLuidToNameA &&
4161 pConvertInterfaceGuidToLuid(&guid, &luid) == NO_ERROR &&
4162 pConvertInterfaceLuidToNameA(&luid,
name,
sizeof(
name)) == NO_ERROR) {
4169 if (addr->IfType & IF_TYPE_SOFTWARE_LOOPBACK)
4171 if (addr->OperStatus == IfOperStatusUp) {
4174 if (addr->FirstUnicastAddress) {
4175 IP_ADAPTER_UNICAST_ADDRESS *cur;
4177 for (cur = addr->FirstUnicastAddress; cur; cur = cur->Next) {
4178 if (cur->Flags & IP_ADAPTER_ADDRESS_TRANSIENT ||
4179 cur->DadState == IpDadStateDeprecated) {
4191 cur->Address.iSockaddrLength);
4247setfl(SOCKET sock,
int arg)
4254 socklist_lookup(sock, &flag);
4262 flag &= ~O_NONBLOCK;
4266 ret = ioctlsocket(sock, FIONBIO, &ioctlArg);
4278dupfd(HANDLE hDup,
int flags,
int minfd)
4288 goto close_fds_and_return;
4291 goto close_fds_and_return;
4293 fds[filled++] = ret;
4294 }
while (filled < (
int)
numberof(fds));
4296 ret = dupfd(hDup, flags, minfd);
4298 close_fds_and_return:
4300 while (filled > 0) {
4301 int fd = fds[--filled];
4329 return setfl(sock,
arg);
4335 if (!(DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
4336 GetCurrentProcess(), &hDup, 0
L,
4338 DUPLICATE_SAME_ACCESS))) {
4350 flag &= ~FNOINHERIT;
4351 if ((ret = dupfd(hDup, flag,
arg)) == -1)
4357 if (
h == -1)
return -1;
4358 if (!GetHandleInformation((HANDLE)
h, &flag)) {
4362 return (flag & HANDLE_FLAG_INHERIT) ? 0 :
FD_CLOEXEC;
4366 if (
h == -1)
return -1;
4370 if (!SetHandleInformation((HANDLE)
h, HANDLE_FLAG_INHERIT,
4393 return setfl(sock, nonblock ?
O_NONBLOCK : 0);
4395 else if (is_pipe(sock)) {
4397 if (!GetNamedPipeHandleState((HANDLE)sock, &state,
NULL,
NULL,
NULL,
NULL, 0)) {
4402 state |= PIPE_NOWAIT;
4405 state &= ~PIPE_NOWAIT;
4407 if (!SetNamedPipeHandleState((HANDLE)sock, &state,
NULL,
NULL)) {
4431poll_child_status(
struct ChildRecord *child,
int *stat_loc)
4436 if (!GetExitCodeProcess(child->hProcess, &exitcode)) {
4438 err = GetLastError();
4440 case ERROR_INVALID_PARAMETER:
4443 case ERROR_INVALID_HANDLE:
4451 CloseChildHandle(child);
4454 if (exitcode != STILL_ACTIVE) {
4461 CloseChildHandle(child);
4463 *stat_loc = exitcode << 8;
4464 if (exitcode & 0xC0000000) {
4465 static const struct {
4469 {STATUS_ACCESS_VIOLATION,
SIGSEGV},
4470 {STATUS_ILLEGAL_INSTRUCTION,
SIGILL},
4471 {STATUS_PRIVILEGED_INSTRUCTION,
SIGILL},
4472 {STATUS_FLOAT_DENORMAL_OPERAND,
SIGFPE},
4473 {STATUS_FLOAT_DIVIDE_BY_ZERO,
SIGFPE},
4474 {STATUS_FLOAT_INEXACT_RESULT,
SIGFPE},
4475 {STATUS_FLOAT_INVALID_OPERATION,
SIGFPE},
4476 {STATUS_FLOAT_OVERFLOW,
SIGFPE},
4477 {STATUS_FLOAT_STACK_CHECK,
SIGFPE},
4478 {STATUS_FLOAT_UNDERFLOW,
SIGFPE},
4479#ifdef STATUS_FLOAT_MULTIPLE_FAULTS
4480 {STATUS_FLOAT_MULTIPLE_FAULTS,
SIGFPE},
4482#ifdef STATUS_FLOAT_MULTIPLE_TRAPS
4483 {STATUS_FLOAT_MULTIPLE_TRAPS,
SIGFPE},
4485 {STATUS_CONTROL_C_EXIT,
SIGINT},
4489 if (table[
i].status == exitcode) {
4490 *stat_loc |= table[
i].sig;
4523 struct ChildRecord* cause;
4526 if (!child->pid || child->pid < 0)
continue;
4527 if ((pid = poll_child_status(child, stat_loc)))
return pid;
4528 events[
count++] = child->hProcess;
4536 if (ret == WAIT_TIMEOUT)
return 0;
4537 if ((ret -= WAIT_OBJECT_0) ==
count) {
4545 cause = FindChildSlotByHandle(events[ret]);
4550 return poll_child_status(cause, stat_loc);
4553 struct ChildRecord* child = FindChildSlot(pid);
4560 while (!(pid = poll_child_status(child, stat_loc))) {
4563 if (ret == WAIT_OBJECT_0 + 1)
return -1;
4564 if (ret != WAIT_OBJECT_0) {
4573 if (pid == -1 && retried) pid = 0;
4579#include <sys/timeb.h>
4581static int have_precisetime = -1;
4584get_systemtime(FILETIME *ft)
4586 typedef void (WINAPI *get_time_func)(FILETIME *ft);
4587 static get_time_func func = (get_time_func)-1;
4589 if (func == (get_time_func)-1) {
4591 func = (get_time_func)get_proc_address(
"kernel32",
"GetSystemTimePreciseAsFileTime",
NULL);
4593 func = GetSystemTimeAsFileTime;
4594 have_precisetime = 0;
4597 have_precisetime = 1;
4606filetime_split(
const FILETIME* ft,
long *subsec)
4612 tmp.LowPart = ft->dwLowDateTime;
4613 tmp.HighPart = ft->dwHighDateTime;
4620 lt -= (
LONG_LONG)((1970-1601)*365.2425) * 24 * 60 * 60 * subsec_unit;
4622 *subsec = (
long)(
lt % subsec_unit);
4633 get_systemtime(&ft);
4634 tv->
tv_sec = filetime_split(&ft, &subsec);
4650 get_systemtime(&ft);
4651 sp->
tv_sec = filetime_split(&ft, &subsec);
4658 LARGE_INTEGER
count;
4659 if (!QueryPerformanceFrequency(&freq)) {
4663 if (!QueryPerformanceCounter(&
count)) {
4668 if (freq.QuadPart < 1000000000)
4669 sp->
tv_nsec = (
count.QuadPart % freq.QuadPart) * 1000000000 / freq.QuadPart;
4671 sp->
tv_nsec = (
long)((
count.QuadPart % freq.QuadPart) * (1000000000.0 / freq.QuadPart));
4694 if (!QueryPerformanceFrequency(&freq)) {
4699 sp->
tv_nsec = (
long)(1000000000.0 / freq.QuadPart);
4710w32_getcwd(
char *buffer,
int size, UINT cp,
void *alloc(
int,
void *),
void *
arg)
4715 len = GetCurrentDirectoryW(0,
NULL);
4727 if (!GetCurrentDirectoryW(
len, p)) {
4732 wlen = translate_wchar(p,
L'\\',
L'/') - p + 1;
4741 buffer = (*alloc)(
len,
arg);
4747 WideCharToMultiByte(cp, 0, p, wlen, buffer,
len,
NULL,
NULL);
4754getcwd_alloc(
int size,
void *dummy)
4770 return w32_getcwd(buffer,
size, CP_UTF8, getcwd_alloc,
NULL);
4775getcwd_value(
int size,
void *
arg)
4787 w32_getcwd(
NULL, 0, CP_UTF8, getcwd_value, &cwd);
4824 if (pid < 0 || (pid == 0 &&
sig !=
SIGINT)) {
4829 if ((
unsigned int)pid == GetCurrentProcessId() &&
4831 if ((ret =
raise(
sig)) != 0) {
4842 OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE, (
DWORD)pid);
4843 if (hProc ==
NULL || hProc == INVALID_HANDLE_VALUE) {
4844 if (GetLastError() == ERROR_INVALID_PARAMETER) {
4860 DWORD ctrlEvent = CTRL_C_EVENT;
4864 ctrlEvent = CTRL_BREAK_EVENT;
4866 if (!GenerateConsoleCtrlEvent(ctrlEvent, (
DWORD)pid)) {
4867 if ((
err = GetLastError()) == 0)
4879 struct ChildRecord* child = FindChildSlot(pid);
4881 hProc = child->hProcess;
4884 hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
FALSE, (
DWORD)pid);
4886 if (hProc ==
NULL || hProc == INVALID_HANDLE_VALUE) {
4887 if (GetLastError() == ERROR_INVALID_PARAMETER) {
4897 if (!GetExitCodeProcess(hProc, &status)) {
4901 else if (status == STILL_ACTIVE) {
4902 if (!TerminateProcess(hProc, 0)) {
4929wlink(
const WCHAR *from,
const WCHAR *to)
4931 if (!CreateHardLinkW(to, from,
NULL)) {
4953 ret = wlink(wfrom, wto);
4961link(
const char *from,
const char *to)
4973 ret = wlink(wfrom, wto);
4980#ifndef FILE_DEVICE_FILE_SYSTEM
4981# define FILE_DEVICE_FILE_SYSTEM 0x00000009
4983#ifndef FSCTL_GET_REPARSE_POINT
4984# define FSCTL_GET_REPARSE_POINT ((0x9<<16)|(42<<2))
4986#ifndef IO_REPARSE_TAG_SYMLINK
4987# define IO_REPARSE_TAG_SYMLINK 0xA000000CL
4998 f = open_special(
path, 0, FILE_FLAG_OPEN_REPARSE_POINT);
4999 if (
f == INVALID_HANDLE_VALUE) {
5000 return GetLastError();
5008 rp->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) {
5009 e = ERROR_INVALID_PARAMETER;
5026 if (e == ERROR_MORE_DATA) {
5034 case ERROR_MORE_DATA:
5043 size_t bufsize, WCHAR **result,
DWORD *
len)
5045 int e = reparse_symlink(
path,
rp, bufsize);
5048 if (!e || e == ERROR_MORE_DATA) {
5051 name = ((
char *)
rp->SymbolicLinkReparseBuffer.PathBuffer +
5052 rp->SymbolicLinkReparseBuffer.PrintNameOffset);
5053 ret =
rp->SymbolicLinkReparseBuffer.PrintNameLength;
5054 *
len = ret /
sizeof(WCHAR);
5056 else if (
rp->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
5057 static const WCHAR *volume =
L"Volume{";
5059 name = ((
char *)
rp->MountPointReparseBuffer.PathBuffer +
5060 rp->MountPointReparseBuffer.SubstituteNameOffset +
5061 volume_prefix_len *
sizeof(WCHAR));
5062 ret =
rp->MountPointReparseBuffer.SubstituteNameLength;
5063 *
len = ret /
sizeof(WCHAR);
5064 ret -= volume_prefix_len *
sizeof(WCHAR);
5065 if (ret >
sizeof(volume) - 1 *
sizeof(WCHAR) &&
5066 memcmp(
name, volume,
sizeof(volume) - 1 *
sizeof(WCHAR)) == 0)
5074 if ((
char *)
name + ret +
sizeof(WCHAR) > (
char *)
rp + bufsize)
5078 ((WCHAR *)
name)[ret/
sizeof(WCHAR)] =
L'\0';
5079 translate_wchar(
name,
L'\\',
L'/');
5089w32_readlink(UINT cp,
const char *
path,
char *
buf,
size_t bufsize)
5094 WCHAR *wname, *wpath =
ALLOCV(wtmp,
size +
sizeof(WCHAR) *
len);
5099 MultiByteToWideChar(cp, 0,
path, -1, wpath,
len);
5101 if (e && e != ERROR_MORE_DATA) {
5106 len = lstrlenW(wname) + 1;
5107 ret = WideCharToMultiByte(cp, 0, wname,
len,
buf, bufsize,
NULL,
NULL);
5124 return w32_readlink(CP_UTF8,
path,
buf, bufsize);
5134#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5135#define SYMBOLIC_LINK_FLAG_DIRECTORY (0x1)
5137#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
5138#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
5143w32_symlink(UINT cp,
const char *
src,
const char *
link)
5145 int atts, len1, len2;
5147 WCHAR *wsrc, *wlink;
5152 typedef BOOLEAN (WINAPI *create_symbolic_link_func)(WCHAR*, WCHAR*,
DWORD);
5153 static create_symbolic_link_func create_symbolic_link =
5154 (create_symbolic_link_func)-1;
5157 if (create_symbolic_link == (create_symbolic_link_func)-1) {
5158 create_symbolic_link = (create_symbolic_link_func)
5159 get_proc_address(
"kernel32",
"CreateSymbolicLinkW",
NULL);
5161 if (!create_symbolic_link) {
5174 len1 = MultiByteToWideChar(cp, 0,
src, -1,
NULL, 0);
5175 len2 = MultiByteToWideChar(cp, 0,
link, -1,
NULL, 0);
5177 wlink = wsrc + len1;
5178 MultiByteToWideChar(cp, 0,
src, -1, wsrc, len1);
5179 MultiByteToWideChar(cp, 0,
link, -1, wlink, len2);
5180 translate_wchar(wsrc,
L'/',
L'\\');
5182 atts = GetFileAttributesW(wsrc);
5183 if (atts != -1 && atts & FILE_ATTRIBUTE_DIRECTORY)
5185 ret = create_symbolic_link(wlink, wsrc, flag |= create_flag);
5187 (e = GetLastError()) == ERROR_INVALID_PARAMETER &&
5190 flag &= ~SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
5191 ret = create_symbolic_link(wlink, wsrc, flag);
5192 if (!ret) e = GetLastError();
5207 return w32_symlink(CP_UTF8,
src,
link);
5221 return waitpid(-1, status, 0);
5226w32_getenv(
const char *
name, UINT cp)
5228 WCHAR *wenvarea, *wenv;
5239 wenvarea = GetEnvironmentStringsW();
5244 for (wenv = wenvarea, wlen = 1; *wenv; wenv += lstrlenW(wenv) + 1)
5245 wlen += lstrlenW(wenv) + 1;
5247 FreeEnvironmentStringsW(wenvarea);
5262 return w32_getenv(
name, CP_UTF8);
5269 return w32_getenv(
name, CP_ACP);
5276 BY_HANDLE_FILE_INFORMATION
st = {0};
5278 HANDLE
h = open_special(
path, 0, FILE_FLAG_OPEN_REPARSE_POINT);
5280 if (
h == INVALID_HANDLE_VALUE) {
5281 ASSUME(e = GetLastError());
5284 if (!GetFileInformationByHandle(
h, &
st)) {
5285 ASSUME(e = GetLastError());
5288 *atts =
st.dwFileAttributes;
5289 *vsn =
st.dwVolumeSerialNumber;
5297wrename(
const WCHAR *oldpath,
const WCHAR *newpath)
5301 DWORD oldvsn = 0, newvsn = 0, e;
5303 e = get_attr_vsn(oldpath, &oldatts, &oldvsn);
5308 if (oldatts & FILE_ATTRIBUTE_REPARSE_POINT) {
5309 HANDLE fh = open_special(oldpath, 0, 0);
5310 if (fh == INVALID_HANDLE_VALUE) {
5312 if (e == ERROR_CANT_RESOLVE_FILENAME) {
5319 get_attr_vsn(newpath, &newatts, &newvsn);
5322 if (newatts != (
DWORD)-1 && newatts & FILE_ATTRIBUTE_READONLY)
5323 SetFileAttributesW(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY);
5325 if (!MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
5329 DWORD e = GetLastError();
5330 if ((e == ERROR_ACCESS_DENIED) && (oldatts & FILE_ATTRIBUTE_DIRECTORY) &&
5337 SetFileAttributesW(newpath, oldatts);
5356 ret = wrename(wfrom, wto);
5375 ret = wrename(wfrom, wto);
5383isUNCRoot(
const WCHAR *
path)
5386 const WCHAR *p =
path + 2;
5387 if (p[0] ==
L'?' && p[1] ==
L'\\') {
5395 for (p++; *p; p++) {
5399 if (!p[0] || !p[1] || (p[1] ==
L'.' && !p[2]))
5406#define COPY_STAT(src, dest, size_cast) do { \
5407 (dest).st_dev = (src).st_dev; \
5408 (dest).st_ino = (src).st_ino; \
5409 (dest).st_mode = (src).st_mode; \
5410 (dest).st_nlink = (src).st_nlink; \
5411 (dest).st_uid = (src).st_uid; \
5412 (dest).st_gid = (src).st_gid; \
5413 (dest).st_rdev = (src).st_rdev; \
5414 (dest).st_size = size_cast(src).st_size; \
5415 (dest).st_atime = (src).st_atime; \
5416 (dest).st_mtime = (src).st_mtime; \
5417 (dest).st_ctime = (src).st_ctime; \
5420static time_t filetime_to_unixtime(
const FILETIME *ft);
5421static long filetime_to_nsec(
const FILETIME *ft);
5422static WCHAR *name_for_stat(WCHAR *
buf,
const WCHAR *
path);
5430 BY_HANDLE_FILE_INFORMATION info;
5433 if (ret)
return ret;
5434 if (GetEnvironmentVariableW(
L"TZ",
NULL, 0) == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND)
return ret;
5435 if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &info)) {
5436 st->st_atime = filetime_to_unixtime(&info.ftLastAccessTime);
5437 st->st_mtime = filetime_to_unixtime(&info.ftLastWriteTime);
5438 st->st_ctime = filetime_to_unixtime(&info.ftCreationTime);
5448 int ret =
fstat(fd, &tmp);
5450 if (ret)
return ret;
5452 stati128_handle((HANDLE)_get_osfhandle(fd),
st);
5456#if !defined FILE_INVALID_FILE_ID && !defined __MINGW32__
5458 BYTE Identifier[16];
5462#if !defined(_WIN32_WINNT_WIN8) || _WIN32_WINNT < 0x602
5463#define FileIdInfo 0x12
5474 typedef BOOL (WINAPI *gfibhe_t)(HANDLE,
int,
void *,
DWORD);
5475 static gfibhe_t pGetFileInformationByHandleEx = (gfibhe_t)-1;
5477 if (pGetFileInformationByHandleEx == (gfibhe_t)-1)
5478 pGetFileInformationByHandleEx = (gfibhe_t)get_proc_address(
"kernel32",
"GetFileInformationByHandleEx",
NULL);
5480 if (pGetFileInformationByHandleEx) {
5481 if (pGetFileInformationByHandleEx(
h,
FileIdInfo,
id,
sizeof(*
id)))
5484 return GetLastError();
5486 return ERROR_INVALID_PARAMETER;
5493 BY_HANDLE_FILE_INFORMATION info;
5496 if (GetFileInformationByHandle(
h, &info)) {
5498 st->st_size = ((__int64)info.nFileSizeHigh << 32) | info.nFileSizeLow;
5499 st->st_atime = filetime_to_unixtime(&info.ftLastAccessTime);
5500 st->st_atimensec = filetime_to_nsec(&info.ftLastAccessTime);
5501 st->st_mtime = filetime_to_unixtime(&info.ftLastWriteTime);
5502 st->st_mtimensec = filetime_to_nsec(&info.ftLastWriteTime);
5503 st->st_ctime = filetime_to_unixtime(&info.ftCreationTime);
5504 st->st_ctimensec = filetime_to_nsec(&info.ftCreationTime);
5505 st->st_nlink = info.nNumberOfLinks;
5506 attr = info.dwFileAttributes;
5507 if (!get_ino(
h, &fii)) {
5508 st->st_ino = *((
unsigned __int64 *)&fii.
FileId);
5509 st->st_inohigh = *((__int64 *)&fii.
FileId + 1);
5512 st->st_ino = ((__int64)info.nFileIndexHigh << 32) | info.nFileIndexLow;
5521filetime_to_unixtime(
const FILETIME *ft)
5524 time_t t = filetime_split(ft, &subsec);
5526 if (t < 0)
return 0;
5532filetime_to_nsec(
const FILETIME *ft)
5534 if (have_precisetime <= 0)
5538 tmp.LowPart = ft->dwLowDateTime;
5539 tmp.HighPart = ft->dwHighDateTime;
5540 return (
long)(tmp.QuadPart % 10000000) * 100;
5546fileattr_to_unixmode(
DWORD attr,
const WCHAR *
path)
5550 if (attr & FILE_ATTRIBUTE_READONLY) {
5557 if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
5563 else if (attr & FILE_ATTRIBUTE_DIRECTORY) {
5571 const WCHAR *end =
path + lstrlenW(
path);
5572 while (
path < end) {
5573 end = CharPrevW(
path, end);
5575 if ((_wcsicmp(end,
L".bat") == 0) ||
5576 (_wcsicmp(end,
L".cmd") == 0) ||
5577 (_wcsicmp(end,
L".com") == 0) ||
5578 (_wcsicmp(end,
L".exe") == 0)) {
5583 if (!iswalnum(*end))
break;
5587 mode |= (mode & 0500) >> 3;
5588 mode |= (mode & 0500) >> 6;
5595check_valid_dir(
const WCHAR *
path)
5597 WIN32_FIND_DATAW fd;
5605 if (!(p = wcsstr(
path,
L"...")))
5607 q = p + wcsspn(p,
L".");
5608 if ((p ==
path || wcschr(
L":/\\", *(p - 1))) &&
5609 (!*q || wcschr(
L":/\\", *q))) {
5616 if (!GetFullPathNameW(
path,
sizeof(full) /
sizeof(WCHAR), full, &dmy)) {
5620 if (full[1] ==
L':' && !full[3] && GetDriveTypeW(full) != DRIVE_NO_ROOT_DIR)
5623 fh = open_dir_handle(
path, &fd);
5624 if (fh == INVALID_HANDLE_VALUE)
5635 WIN32_FIND_DATAW wfd;
5637 int e = GetLastError();
5639 if ((e == ERROR_FILE_NOT_FOUND) || (e == ERROR_INVALID_NAME)
5640 || (e == ERROR_PATH_NOT_FOUND || (e == ERROR_BAD_NETPATH))) {
5646 h = FindFirstFileW(
path, &wfd);
5647 if (
h == INVALID_HANDLE_VALUE) {
5652 st->st_mode = fileattr_to_unixmode(wfd.dwFileAttributes,
path);
5653 st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
5654 st->st_atimensec = filetime_to_nsec(&wfd.ftLastAccessTime);
5655 st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
5656 st->st_mtimensec = filetime_to_nsec(&wfd.ftLastWriteTime);
5657 st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
5658 st->st_ctimensec = filetime_to_nsec(&wfd.ftCreationTime);
5659 st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
5666path_drive(
const WCHAR *
path)
5668 return (iswalpha(
path[0]) &&
path[1] ==
L':') ?
5669 towupper(
path[0]) -
L'A' : _getdrive() - 1;
5672static const WCHAR namespace_prefix[] = {
L'\\',
L'\\',
L'?',
L'\\'};
5678 DWORD flags =
lstat ? FILE_FLAG_OPEN_REPARSE_POINT : 0;
5683 f = open_special(
path, 0, flags);
5684 if (
f != INVALID_HANDLE_VALUE) {
5685 DWORD attr = stati128_handle(
f,
st);
5688 if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
5693 attr &= ~FILE_ATTRIBUTE_REPARSE_POINT;
5695 if (attr & FILE_ATTRIBUTE_DIRECTORY) {
5696 if (check_valid_dir(
path))
return -1;
5698 st->st_mode = fileattr_to_unixmode(attr,
path);
5702 if (wcsncmp(
path, namespace_prefix,
numberof(namespace_prefix)) == 0)
5707 if (stat_by_find(
path,
st))
return -1;
5710 st->st_dev =
st->st_rdev = path_drive(
path);
5740 if (!(
path = name_for_stat(buf1,
path)))
5751name_for_stat(WCHAR *buf1,
const WCHAR *
path)
5757 for (p =
path, s = buf1; *p; p++, s++) {
5765 if (!
len ||
L'\"' == *(--s)) {
5769 end = buf1 +
len - 1;
5771 if (isUNCRoot(buf1)) {
5774 else if (*end !=
L'\\')
5775 lstrcatW(buf1,
L"\\");
5777 else if (*end ==
L'\\' || (buf1 + 1 == end && *end ==
L':'))
5778 lstrcatW(buf1,
L".");
5806 ret = wstati128(wpath,
st,
lstat);
5815 return w32_stati128(
path,
st, CP_UTF8,
TRUE);
5834 return _lseeki64(fd, ofs, whence);
5871 long upos, lpos, usize, lsize;
5875 if ((lpos = SetFilePointer(
h, 0, (upos = 0, &upos),
SEEK_CUR)) == -1L &&
5876 (e = GetLastError())) {
5883 (e = GetLastError())) {
5886 else if (!SetEndOfFile(
h)) {
5892 SetFilePointer(
h, lpos, &upos,
SEEK_SET);
5898w32_truncate(
const char *
path,
off_t length, UINT cp)
5906 h = CreateFileW(wpath, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
5907 if (
h == INVALID_HANDLE_VALUE) {
5913 ret = rb_chsize(
h, length);
5922 return w32_truncate(
path, length, CP_UTF8);
5938 h = (HANDLE)_get_osfhandle(fd);
5939 if (
h == (HANDLE)-1)
return -1;
5940 return rb_chsize(
h, length);
5945filetime_to_clock(FILETIME *ft)
5947 __int64 qw = ft->dwHighDateTime;
5949 qw |= ft->dwLowDateTime;
5958 FILETIME create,
exit, kernel, user;
5960 if (GetProcessTimes(GetCurrentProcess(),&create, &
exit, &kernel, &user)) {
5961 tmbuf->
tms_utime = filetime_to_clock(&user);
5962 tmbuf->
tms_stime = filetime_to_clock(&kernel);
5977#define yield_once() Sleep(0)
5978#define yield_until(condition) do yield_once(); while (!(condition))
5995call_asynchronous(PVOID argp)
5999 arg->stackaddr = &argp;
6011 BOOL interrupted =
FALSE;
6024 thr = CreateThread(
NULL, 0, call_asynchronous, &
arg, 0, &val);
6032 if (TerminateThread(thr, intrval)) {
6037 GetExitCodeThread(thr, &val);
6042 MEMORY_BASIC_INFORMATION m;
6044 memset(&m, 0,
sizeof(m));
6045 if (!VirtualQuery(
arg.stackaddr, &m,
sizeof(m))) {
6047 arg.stackaddr, GetLastError()));
6049 else if (!VirtualFree(m.AllocationBase, 0, MEM_RELEASE)) {
6051 m.AllocationBase, GetLastError()));
6062 rb_fatal(
"failed to launch waiter thread:%ld", GetLastError());
6072 WCHAR *envtop, *
env;
6073 char **myenvtop, **myenv;
6086 envtop = GetEnvironmentStringsW();
6087 for (
env = envtop, num = 0; *
env;
env += lstrlenW(
env) + 1)
6088 if (*
env !=
'=') num++;
6090 myenvtop = (
char **)
malloc(
sizeof(
char *) * (num + 1));
6091 for (
env = envtop, myenv = myenvtop; *
env;
env += lstrlenW(
env) + 1) {
6100 FreeEnvironmentStringsW(envtop);
6111 while (*t)
free(*t++);
6119 return GetCurrentProcessId();
6127 typedef long (WINAPI query_func)(HANDLE,
int,
void *, ULONG, ULONG *);
6128 static query_func *pNtQueryInformationProcess = (query_func *)-1;
6131 if (pNtQueryInformationProcess == (query_func *)-1)
6132 pNtQueryInformationProcess = (query_func *)get_proc_address(
"ntdll.dll",
"NtQueryInformationProcess",
NULL);
6133 if (pNtQueryInformationProcess) {
6136 void* PebBaseAddress;
6143 long ret = pNtQueryInformationProcess(GetCurrentProcess(), 0, &pbi,
sizeof(pbi), &
len);
6145 ppid = pbi.ParentProcessId;
6152STATIC_ASSERT(std_handle, (STD_OUTPUT_HANDLE-STD_INPUT_HANDLE)==(STD_ERROR_HANDLE-STD_OUTPUT_HANDLE));
6155#define set_new_std_handle(newfd, handle) do { \
6156 if ((unsigned)(newfd) > 2) break; \
6157 SetStdHandle(STD_INPUT_HANDLE+(STD_OUTPUT_HANDLE-STD_INPUT_HANDLE)*(newfd), \
6160#define set_new_std_fd(newfd) set_new_std_handle(newfd, (HANDLE)rb_w32_get_osfhandle(newfd))
6168 if (oldfd == newfd)
return newfd;
6169 ret =
dup2(oldfd, newfd);
6170 if (ret < 0)
return ret;
6190 ret = w32_wopen(wfile, oflag, pmode);
6197check_if_wdir(
const WCHAR *wfile)
6199 DWORD attr = GetFileAttributesW(wfile);
6200 if (attr == (
DWORD)-1L ||
6201 !(attr & FILE_ATTRIBUTE_DIRECTORY) ||
6202 check_valid_dir(wfile)) {
6224 ret = w32_wopen(wfile, oflag, pmode);
6235 if (oflag & O_CREAT) {
6242 return w32_wopen(file, oflag, pmode);
6246w32_wopen(
const WCHAR *file,
int oflag,
int pmode)
6252 DWORD attr = FILE_ATTRIBUTE_NORMAL;
6253 SECURITY_ATTRIBUTES sec;
6258 oflag &= ~O_SHARE_DELETE;
6259 if ((oflag & O_TEXT) || !(oflag &
O_BINARY)) {
6260 fd = _wopen(file, oflag, pmode);
6264 check_if_wdir(file);
6274 sec.nLength =
sizeof(sec);
6275 sec.lpSecurityDescriptor =
NULL;
6276 if (oflag & O_NOINHERIT) {
6277 sec.bInheritHandle =
FALSE;
6281 sec.bInheritHandle =
TRUE;
6283 oflag &= ~O_NOINHERIT;
6288 switch (oflag & (O_RDWR | O_RDONLY | O_WRONLY)) {
6290 access = GENERIC_READ | GENERIC_WRITE;
6302 oflag &= ~(O_RDWR | O_RDONLY | O_WRONLY);
6304 switch (oflag & (O_CREAT | O_EXCL | O_TRUNC)) {
6306 create = OPEN_ALWAYS;
6310 create = OPEN_EXISTING;
6312 case O_CREAT | O_EXCL:
6313 case O_CREAT | O_EXCL | O_TRUNC:
6314 create = CREATE_NEW;
6317 case O_TRUNC | O_EXCL:
6318 create = TRUNCATE_EXISTING;
6320 case O_CREAT | O_TRUNC:
6321 create = CREATE_ALWAYS;
6327 if (oflag & O_CREAT) {
6330 attr = FILE_ATTRIBUTE_READONLY;
6332 oflag &= ~(O_CREAT | O_EXCL | O_TRUNC);
6334 if (oflag & O_TEMPORARY) {
6335 attr |= FILE_FLAG_DELETE_ON_CLOSE;
6338 oflag &= ~O_TEMPORARY;
6340 if (oflag & _O_SHORT_LIVED)
6341 attr |= FILE_ATTRIBUTE_TEMPORARY;
6342 oflag &= ~_O_SHORT_LIVED;
6344 switch (oflag & (O_SEQUENTIAL | O_RANDOM)) {
6348 attr |= FILE_FLAG_SEQUENTIAL_SCAN;
6351 attr |= FILE_FLAG_RANDOM_ACCESS;
6357 oflag &= ~(O_SEQUENTIAL | O_RANDOM);
6359 if (oflag & ~O_APPEND) {
6366 h = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
6379 h = CreateFileW(file,
access, FILE_SHARE_READ | FILE_SHARE_WRITE | share_delete, &sec, create, attr,
NULL);
6380 if (
h == INVALID_HANDLE_VALUE) {
6381 DWORD e = GetLastError();
6382 if (e != ERROR_ACCESS_DENIED || !check_if_wdir(file))
6389 switch (GetFileType(
h)) {
6390 case FILE_TYPE_CHAR:
6393 case FILE_TYPE_PIPE:
6396 case FILE_TYPE_UNKNOWN:
6403 if (!(flags & (
FDEV |
FPIPE)) && (oflag & O_APPEND))
6423 int save_errno =
errno;
6425 if (
fflush(fp))
return -1;
6433 if (closesocket(sock) == SOCKET_ERROR) {
6444 static DWORD serial = 0;
6445 static const char prefix[] =
"\\\\.\\pipe\\ruby";
6447 width_of_prefix = (
int)
sizeof(prefix) - 1,
6449 width_of_serial = (
int)
sizeof(serial) * 2,
6450 width_of_ids = width_of_pid + 1 + width_of_serial + 1
6452 char name[
sizeof(prefix) + width_of_ids];
6453 SECURITY_ATTRIBUTES sec;
6454 HANDLE hRead, hWrite,
h;
6455 int fdRead, fdWrite;
6462 sec.nLength =
sizeof(sec);
6463 sec.lpSecurityDescriptor =
NULL;
6464 sec.bInheritHandle =
FALSE;
6467 hRead = CreateNamedPipe(
name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
6468 0, 2, 65536, 65536, 0, &sec);
6470 if (hRead == INVALID_HANDLE_VALUE) {
6472 if (
err == ERROR_PIPE_BUSY)
6480 hWrite = CreateFile(
name, GENERIC_READ | GENERIC_WRITE, 0, &sec,
6481 OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
NULL);
6483 if (hWrite == INVALID_HANDLE_VALUE) {
6491 h = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
6492 fdRead = _open_osfhandle((
intptr_t)
h, 0);
6496 CloseHandle(hWrite);
6511 h = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
6512 fdWrite = _open_osfhandle((
intptr_t)
h, 0);
6514 if (fdWrite == -1) {
6516 CloseHandle(hWrite);
6538console_emulator_p(
void)
6543 const void *
const func = WriteConsoleW;
6545 MEMORY_BASIC_INFORMATION m;
6547 memset(&m, 0,
sizeof(m));
6548 if (!VirtualQuery(func, &m,
sizeof(m))) {
6551 k = GetModuleHandle(
"kernel32.dll");
6552 if (!k)
return FALSE;
6553 return (HMODULE)m.AllocationBase != k;
6559constat_handle(HANDLE
h)
6564 EnterCriticalSection(&conlist_mutex);
6566 if (console_emulator_p()) {
6570 install_vm_exit_handler();
6577 CONSOLE_SCREEN_BUFFER_INFO csbi;
6580 p->
vt100.
attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
6583 if (GetConsoleScreenBufferInfo(
h, &csbi)) {
6591 LeaveCriticalSection(&conlist_mutex);
6598constat_reset(HANDLE
h)
6603 EnterCriticalSection(&conlist_mutex);
6611 LeaveCriticalSection(&conlist_mutex);
6614#define FOREGROUND_MASK (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
6615#define BACKGROUND_MASK (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
6617#define constat_attr_color_reverse(attr) \
6618 ((attr) & ~(FOREGROUND_MASK | BACKGROUND_MASK)) | \
6619 (((attr) & FOREGROUND_MASK) << 4) | \
6620 (((attr) & BACKGROUND_MASK) >> 4)
6631 bold =
attr & FOREGROUND_INTENSITY;
6632 attr &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
6634 while (
count-- > 0) {
6637 attr = default_attr;
6642 bold = FOREGROUND_INTENSITY;
6645#ifndef COMMON_LVB_UNDERSCORE
6646#define COMMON_LVB_UNDERSCORE 0x8000
6655 attr &= ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
6659 attr = (
attr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN)) | FOREGROUND_RED;
6663 attr = (
attr & ~(FOREGROUND_BLUE | FOREGROUND_RED)) | FOREGROUND_GREEN;
6667 attr = (
attr & ~FOREGROUND_BLUE) | FOREGROUND_GREEN | FOREGROUND_RED;
6671 attr = (
attr & ~(FOREGROUND_GREEN | FOREGROUND_RED)) | FOREGROUND_BLUE;
6675 attr = (
attr & ~FOREGROUND_GREEN) | FOREGROUND_BLUE | FOREGROUND_RED;
6679 attr = (
attr & ~FOREGROUND_RED) | FOREGROUND_BLUE | FOREGROUND_GREEN;
6683 attr |= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
6687 attr &= ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);
6690 attr = (
attr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN)) | BACKGROUND_RED;
6693 attr = (
attr & ~(BACKGROUND_BLUE | BACKGROUND_RED)) | BACKGROUND_GREEN;
6696 attr = (
attr & ~BACKGROUND_BLUE) | BACKGROUND_GREEN | BACKGROUND_RED;
6699 attr = (
attr & ~(BACKGROUND_GREEN | BACKGROUND_RED)) | BACKGROUND_BLUE;
6702 attr = (
attr & ~BACKGROUND_GREEN) | BACKGROUND_BLUE | BACKGROUND_RED;
6705 attr = (
attr & ~BACKGROUND_RED) | BACKGROUND_BLUE | BACKGROUND_GREEN;
6708 attr |= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
6720constat_clear(HANDLE handle, WORD
attr,
DWORD len, COORD pos)
6724 FillConsoleOutputAttribute(handle,
attr,
len, pos, &written);
6725 FillConsoleOutputCharacterW(handle,
L' ',
len, pos, &written);
6730constat_apply(HANDLE handle,
struct constat *s, WCHAR w)
6732 CONSOLE_SCREEN_BUFFER_INFO csbi;
6738 if (!GetConsoleScreenBufferInfo(handle, &csbi))
return;
6740 if (arg0) arg1 =
seq[0];
6746 csbi.dwCursorPosition.X = 0;
6748 csbi.dwCursorPosition.Y -= arg1;
6749 if (csbi.dwCursorPosition.Y < csbi.srWindow.Top)
6750 csbi.dwCursorPosition.Y = csbi.srWindow.Top;
6751 SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6754 csbi.dwCursorPosition.X = 0;
6757 csbi.dwCursorPosition.Y += arg1;
6758 if (csbi.dwCursorPosition.Y > csbi.srWindow.Bottom)
6759 csbi.dwCursorPosition.Y = csbi.srWindow.Bottom;
6760 SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6763 csbi.dwCursorPosition.X += arg1;
6764 if (csbi.dwCursorPosition.X >= csbi.srWindow.Right)
6765 csbi.dwCursorPosition.X = csbi.srWindow.Right;
6766 SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6769 csbi.dwCursorPosition.X -= arg1;
6770 if (csbi.dwCursorPosition.X < csbi.srWindow.Left)
6771 csbi.dwCursorPosition.X = csbi.srWindow.Left;
6772 SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6776 arg1 += csbi.srWindow.Left;
6777 if (arg1 > csbi.srWindow.Right)
6778 arg1 = csbi.srWindow.Right;
6779 csbi.dwCursorPosition.X = arg1;
6780 SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6783 arg1 += csbi.srWindow.Top;
6784 if (arg1 > csbi.srWindow.Bottom)
6785 arg1 = csbi.srWindow.Bottom;
6786 csbi.dwCursorPosition.Y = arg1;
6787 SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6791 pos.Y = arg1 + csbi.srWindow.Top - 1;
6792 if (pos.Y > csbi.srWindow.Bottom) pos.Y = csbi.srWindow.Bottom;
6793 if (
count < 2 || (arg1 =
seq[1]) <= 0) arg1 = 1;
6794 pos.X = arg1 + csbi.srWindow.Left - 1;
6795 if (pos.X > csbi.srWindow.Right) pos.X = csbi.srWindow.Right;
6796 SetConsoleCursorPosition(handle, pos);
6799 switch (arg0 ? arg1 : 0) {
6801 constat_clear(handle, csbi.wAttributes,
6802 (csbi.dwSize.X * (csbi.srWindow.Bottom - csbi.dwCursorPosition.Y + 1)
6803 - csbi.dwCursorPosition.X),
6804 csbi.dwCursorPosition);
6808 pos.Y = csbi.srWindow.Top;
6809 constat_clear(handle, csbi.wAttributes,
6810 (csbi.dwSize.X * (csbi.dwCursorPosition.Y - csbi.srWindow.Top)
6811 + csbi.dwCursorPosition.X + 1),
6816 pos.Y = csbi.srWindow.Top;
6817 constat_clear(handle, csbi.wAttributes,
6818 (csbi.dwSize.X * (csbi.srWindow.Bottom - csbi.srWindow.Top + 1)),
6824 constat_clear(handle, csbi.wAttributes,
6825 (csbi.dwSize.X * csbi.dwSize.Y),
6831 switch (arg0 ? arg1 : 0) {
6833 constat_clear(handle, csbi.wAttributes,
6834 (csbi.dwSize.X - csbi.dwCursorPosition.X),
6835 csbi.dwCursorPosition);
6839 pos.Y = csbi.dwCursorPosition.Y;
6840 constat_clear(handle, csbi.wAttributes,
6841 csbi.dwCursorPosition.X + 1, pos);
6845 pos.Y = csbi.dwCursorPosition.Y;
6846 constat_clear(handle, csbi.wAttributes,
6847 csbi.dwSize.X, pos);
6855 SetConsoleCursorPosition(handle, s->
vt100.
saved);
6859 CONSOLE_CURSOR_INFO cci;
6860 GetConsoleCursorInfo(handle, &cci);
6861 cci.bVisible =
TRUE;
6862 SetConsoleCursorInfo(handle, &cci);
6867 CONSOLE_CURSOR_INFO cci;
6868 GetConsoleCursorInfo(handle, &cci);
6869 cci.bVisible =
FALSE;
6870 SetConsoleCursorInfo(handle, &cci);
6878static const long MAXSIZE_CONSOLE_WRITING = 31366;
6882constat_parse(HANDLE
h,
struct constat *s,
const WCHAR **ptrp,
long *lenp)
6884 const WCHAR *
ptr = *ptrp;
6885 long rest,
len = *lenp;
6889 rest = *lenp -
len - 1;
6894 if (
len > 0 && *
ptr !=
L'[')
continue;
6903 rest = *lenp -
len - 1;
6904 if (rest > 0) --rest;
6909 if (wc >=
L'0' && wc <=
L'9') {
6912 *
seq = (*
seq * 10) + (wc -
L'0');
6928 constat_apply(
h, s, wc);
6934 else if ((rest = *lenp -
len) < MAXSIZE_CONSOLE_WRITING) {
6953 int save_errno =
errno;
6957 constat_delete((HANDLE)sock);
6961 socklist_delete(&sock,
NULL);
6964 if (closesocket(sock) == SOCKET_ERROR) {
6972setup_overlapped(OVERLAPPED *ol,
int fd,
int iswrite)
6974 memset(ol, 0,
sizeof(*ol));
6982 DWORD low = SetFilePointer((HANDLE)
_osfhnd(fd), 0, &high, method);
6983#ifndef INVALID_SET_FILE_POINTER
6984#define INVALID_SET_FILE_POINTER ((DWORD)-1)
6988 if (
err != NO_ERROR) {
6994 ol->OffsetHigh = high;
7005finish_overlapped(OVERLAPPED *ol,
int fd,
DWORD size)
7007 CloseHandle(ol->hEvent);
7010 LONG high = ol->OffsetHigh;
7012 if (low < ol->Offset)
7014 SetFilePointer((HANDLE)
_osfhnd(fd), low, &high, FILE_BEGIN);
7031 BOOL islineinput =
FALSE;
7038 if (_get_osfhandle(fd) == -1) {
7055 isconsole = is_console(
_osfhnd(fd)) && (osver.dwMajorVersion < 6 || (osver.dwMajorVersion == 6 && osver.dwMinorVersion < 2));
7058 GetConsoleMode((HANDLE)
_osfhnd(fd),&mode);
7059 islineinput = (mode & ENABLE_LINE_INPUT) != 0;
7064 constat_reset((HANDLE)
_osfhnd(fd));
7076 if (setup_overlapped(&ol, fd,
FALSE)) {
7082 err = GetLastError();
7094 else if (
err != ERROR_IO_PENDING) {
7095 CloseHandle(ol.hEvent);
7096 if (
err == ERROR_ACCESS_DENIED)
7098 else if (
err == ERROR_BROKEN_PIPE ||
err == ERROR_HANDLE_EOF) {
7110 if (
wait != WAIT_OBJECT_0) {
7111 if (
wait == WAIT_OBJECT_0 + 1)
7115 CloseHandle(ol.hEvent);
7116 CancelIo((HANDLE)
_osfhnd(fd));
7122 (
err = GetLastError()) != ERROR_HANDLE_EOF) {
7124 if (
err != ERROR_BROKEN_PIPE) {
7128 CloseHandle(ol.hEvent);
7129 CancelIo((HANDLE)
_osfhnd(fd));
7135 err = GetLastError();
7139 finish_overlapped(&ol, fd,
read);
7144 if (
err != ERROR_OPERATION_ABORTED &&
7145 !(isconsole &&
len == 1 && (!islineinput || *((
char *)
buf - 1) ==
'\n')) &&
size > 0)
7174 if (_get_osfhandle(fd) == -1) {
7200 if (setup_overlapped(&ol, fd,
TRUE)) {
7205 if (!WriteFile((HANDLE)
_osfhnd(fd),
buf,
len, &written, &ol)) {
7206 err = GetLastError();
7207 if (
err != ERROR_IO_PENDING) {
7208 CloseHandle(ol.hEvent);
7209 if (
err == ERROR_ACCESS_DENIED)
7219 if (
wait != WAIT_OBJECT_0) {
7220 if (
wait == WAIT_OBJECT_0 + 1)
7224 CloseHandle(ol.hEvent);
7225 CancelIo((HANDLE)
_osfhnd(fd));
7230 if (!GetOverlappedResult((HANDLE)
_osfhnd(fd), &ol, &written,
TRUE)) {
7232 CloseHandle(ol.hEvent);
7233 CancelIo((HANDLE)
_osfhnd(fd));
7239 finish_overlapped(&ol, fd, written);
7242 if (written ==
len) {
7248 size_t newlen =
len / 2;
7268 DWORD dwMode, reslen;
7272 const WCHAR *
ptr, *next;
7277 if (!GetConsoleMode(handle, &dwMode))
7280 s = constat_handle(handle);
7295 if (!
ptr)
return -1L;
7304 if (!WriteConsoleW(handle,
ptr,
len, &reslen,
NULL))
7305 reslen = (
DWORD)-1L;
7309 long curlen = constat_parse(handle, s, (next =
ptr, &next), &
len);
7310 reslen += next -
ptr;
7313 if (!WriteConsoleW(handle,
ptr, curlen, &written,
NULL)) {
7314 reslen = (
DWORD)-1L;
7322 if (wbuffer)
free(wbuffer);
7323 return (
long)reslen;
7326#if RUBY_MSVCRT_VERSION < 80 && !defined(HAVE__GMTIME64_S)
7329unixtime_to_filetime(
time_t time, FILETIME *ft)
7334 ft->dwLowDateTime = tmp.LowPart;
7335 ft->dwHighDateTime = tmp.HighPart;
7342timespec_to_filetime(
const struct timespec *ts, FILETIME *ft)
7347 tmp.QuadPart += ts->
tv_nsec / 100;
7348 ft->dwLowDateTime = tmp.LowPart;
7349 ft->dwHighDateTime = tmp.HighPart;
7355wutimensat(
int dirfd,
const WCHAR *
path,
const struct timespec *times,
int flags)
7358 FILETIME atime, mtime;
7378 if (timespec_to_filetime(×[0], &atime)) {
7381 if (timespec_to_filetime(×[1], &mtime)) {
7386 get_systemtime(&atime);
7391 const DWORD attr = GetFileAttributesW(
path);
7392 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY))
7393 SetFileAttributesW(
path, attr & ~FILE_ATTRIBUTE_READONLY);
7394 hFile = open_special(
path, GENERIC_WRITE, 0);
7395 if (hFile == INVALID_HANDLE_VALUE) {
7400 if (!SetFileTime(hFile,
NULL, &atime, &mtime)) {
7406 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY))
7407 SetFileAttributesW(
path, attr);
7474 ret = wutimensat(dirfd, wpath, times, flags);
7488 ret = wutimensat(dirfd, wpath, times, flags);
7502 ret = _wchdir(wpath);
7509wmkdir(
const WCHAR *wpath,
int mode)
7514 if (CreateDirectoryW(wpath,
NULL) ==
FALSE) {
7518 if (_wchmod(wpath, mode) == -1) {
7519 RemoveDirectoryW(wpath);
7536 ret = wmkdir(wpath, mode);
7550 ret = wmkdir(wpath, mode);
7557wrmdir(
const WCHAR *wpath)
7561 const DWORD attr = GetFileAttributesW(wpath);
7562 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
7563 SetFileAttributesW(wpath, attr & ~FILE_ATTRIBUTE_READONLY);
7565 if (RemoveDirectoryW(wpath) ==
FALSE) {
7568 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
7569 SetFileAttributesW(wpath, attr);
7585 ret = wrmdir(wpath);
7599 ret = wrmdir(wpath);
7606wunlink(
const WCHAR *
path)
7609 const DWORD SYMLINKD = FILE_ATTRIBUTE_REPARSE_POINT|FILE_ATTRIBUTE_DIRECTORY;
7611 const DWORD attr = GetFileAttributesW(
path);
7612 if (attr == (
DWORD)-1) {
7614 else if ((attr & SYMLINKD) == SYMLINKD) {
7615 ret = RemoveDirectoryW(
path);
7618 if (attr & FILE_ATTRIBUTE_READONLY) {
7619 SetFileAttributesW(
path, attr & ~FILE_ATTRIBUTE_READONLY);
7621 ret = DeleteFileW(
path);
7626 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
7627 SetFileAttributesW(
path, attr);
7643 ret = wunlink(wpath);
7657 ret = wunlink(wpath);
7671 ret = _wchmod(wpath, mode);
7680 typedef BOOL (WINAPI *set_file_information_by_handle_func)
7682 static set_file_information_by_handle_func set_file_info =
7683 (set_file_information_by_handle_func)-1;
7687 LARGE_INTEGER CreationTime;
7688 LARGE_INTEGER LastAccessTime;
7689 LARGE_INTEGER LastWriteTime;
7690 LARGE_INTEGER ChangeTime;
7691 DWORD FileAttributes;
7692 } info = {{{0}}, {{0}}, {{0}},};
7693 HANDLE
h = (HANDLE)_get_osfhandle(fd);
7695 if (
h == INVALID_HANDLE_VALUE) {
7699 if (set_file_info == (set_file_information_by_handle_func)-1) {
7700 set_file_info = (set_file_information_by_handle_func)
7701 get_proc_address(
"kernel32",
"SetFileInformationByHandle",
NULL);
7703 if (!set_file_info) {
7708 info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
7709 if (!(mode & 0200)) info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
7710 if (!set_file_info(
h, 0, &info,
sizeof(info))) {
7724 if (_get_osfhandle(fd) == -1) {
7727 if (!GetConsoleMode((HANDLE)
_osfhnd(fd), &mode)) {
7734#if defined(_MSC_VER) && RUBY_MSVCRT_VERSION <= 60
7735extern long _ftol(
double);
7756 int *ip = (
int *)(&x + 1) - 1;
7765 typedef char *(WSAAPI inet_ntop_t)(
int,
void *,
char *,
size_t);
7766 static inet_ntop_t *pInetNtop = (inet_ntop_t *)-1;
7767 if (pInetNtop == (inet_ntop_t *)-1)
7768 pInetNtop = (inet_ntop_t *)get_proc_address(
"ws2_32",
"inet_ntop",
NULL);
7770 return pInetNtop(af, (
void *)addr, numaddr, numaddr_len);
7774 memcpy(&in.s_addr, addr,
sizeof(in.s_addr));
7775 snprintf(numaddr, numaddr_len,
"%s", inet_ntoa(in));
7784 typedef int (WSAAPI inet_pton_t)(
int,
const char*,
void *);
7785 static inet_pton_t *pInetPton = (inet_pton_t *)-1;
7786 if (pInetPton == (inet_pton_t *)-1)
7787 pInetPton = (inet_pton_t *)get_proc_address(
"ws2_32",
"inet_pton",
NULL);
7789 return pInetPton(af,
src, dst);
7801#if RUBY_MSVCRT_VERSION < 80 && !defined(HAVE__GMTIME64_S)
7804unixtime_to_systemtime(
const time_t t, SYSTEMTIME *
st)
7807 if (unixtime_to_filetime(t, &ft))
return -1;
7808 if (!FileTimeToSystemTime(&ft,
st))
return -1;
7814systemtime_to_tm(
const SYSTEMTIME *
st,
struct tm *t)
7816 int y =
st->wYear, m =
st->wMonth, d =
st->wDay;
7831 d += 31 + 28 + (!(y % 4) && ((y % 100) || !(y % 400)));
7832 d += ((m - 3) * 153 + 2) / 5;
7840systemtime_to_localtime(TIME_ZONE_INFORMATION *tz, SYSTEMTIME *gst, SYSTEMTIME *lst)
7842 TIME_ZONE_INFORMATION stdtz;
7845 if (!SystemTimeToTzSpecificLocalTime(tz, gst, lst))
return -1;
7847 GetTimeZoneInformation(&stdtz);
7850 if (tz->StandardBias == tz->DaylightBias)
return 0;
7851 if (!tz->StandardDate.wMonth)
return 0;
7852 if (!tz->DaylightDate.wMonth)
return 0;
7853 if (tz != &stdtz) stdtz = *tz;
7855 stdtz.StandardDate.wMonth = stdtz.DaylightDate.wMonth = 0;
7856 if (!SystemTimeToTzSpecificLocalTime(&stdtz, gst, &sst))
return 0;
7857 if (lst->wMinute == sst.wMinute && lst->wHour == sst.wHour)
7863#ifdef HAVE__GMTIME64_S
7864# ifndef HAVE__LOCALTIME64_S
7866# define HAVE__LOCALTIME64_S 1
7868# ifndef MINGW_HAS_SECURE_API
7869 _CRTIMP errno_t __cdecl _gmtime64_s(
struct tm*
tm,
const __time64_t *
time);
7870 _CRTIMP errno_t __cdecl _localtime64_s(
struct tm*
tm,
const __time64_t *
time);
7872# define gmtime_s _gmtime64_s
7873# define localtime_s _localtime64_s
7886#if RUBY_MSVCRT_VERSION >= 80 || defined(HAVE__GMTIME64_S)
7887 e = gmtime_s(
rp, tp);
7888 if (e != 0)
goto error;
7892 if (unixtime_to_systemtime(*tp, &
st))
goto error;
7894 systemtime_to_tm(&
st,
rp);
7910#if RUBY_MSVCRT_VERSION >= 80 || defined(HAVE__LOCALTIME64_S)
7911 e = localtime_s(
rp, tp);
7915 SYSTEMTIME gst, lst;
7916 if (unixtime_to_systemtime(*tp, &gst))
goto error;
7917 rp->tm_isdst = systemtime_to_localtime(
NULL, &gst, &lst);
7918 systemtime_to_tm(&lst,
rp);
7929 int len =
sizeof(tmp);
7930 int r = getsockopt((SOCKET)
h, SOL_SOCKET, SO_DEBUG, (
char *)&tmp, &
len);
7931 if (r != SOCKET_ERROR || WSAGetLastError() != WSAENOTSOCK) {
7934 flags &= ~O_NONBLOCK;
7937 socklist_insert((SOCKET)
h,
f);
7943 return rb_w32_open_osfhandle((
intptr_t)
h, flags);
7954 constat_delete((HANDLE)sock);
7957 socklist_delete(&sock,
NULL);
7962#if !defined(__MINGW64__) && defined(__MINGW64_VERSION_MAJOR)
7968rb_w32_pow(
double x,
double y)
7972 unsigned int default_control = _controlfp(0, 0);
7973 _controlfp(_PC_64, _MCW_PC);
7976 _controlfp(default_control, _MCW_PC);
8001 if (
f == (HANDLE)-1)
return INVALID_HANDLE_VALUE;
8014 f = CreateFileW(
ptr, 0,
8015 FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
8016 FILE_FLAG_BACKUP_SEMANTICS,
NULL);
8018 if (
f == INVALID_HANDLE_VALUE)
return f;
8021 if (GetFileType(
f) == FILE_TYPE_DISK) {
8023 ZeroMemory(
st,
sizeof(*
st));
8024 err = get_ino(
f, &
st->info.fii);
8029 else if (
err != ERROR_INVALID_PARAMETER) {
8031 return INVALID_HANDLE_VALUE;
8035 if (GetFileInformationByHandle(
f, &
st->info.bhfi)) {
8040 if (ret) CloseHandle(ret);
8041 return INVALID_HANDLE_VALUE;
8047 CloseHandle((HANDLE)
h);
8067 HANDLE f1 = 0, f2 = 0;
8069 f1 = w32_io_info(&fname1, &st1);
8070 if (f1 == INVALID_HANDLE_VALUE)
return Qfalse;
8073 arg.fname = &fname2;
8078 f2 = w32_io_info(&fname2, &st2);
8080 if (f2 == INVALID_HANDLE_VALUE)
return Qfalse;
8081 if (f2) CloseHandle(f2);
8085 if (st1.
info.
bhfi.dwVolumeSerialNumber == st2.
info.
bhfi.dwVolumeSerialNumber &&
8102 typedef HRESULT (WINAPI *set_thread_description_func)(HANDLE, PCWSTR);
8103 static set_thread_description_func set_thread_description =
8104 (set_thread_description_func)-1;
8105 if (set_thread_description == (set_thread_description_func)-1) {
8106 set_thread_description = (set_thread_description_func)
8107 get_proc_address(
"kernel32",
"SetThreadDescription",
NULL);
8109 if (set_thread_description) {
8110 result = set_thread_description(th,
name);
8118 int idx, result =
FALSE;
8141#if RUBY_MSVCRT_VERSION < 120
#define ENCINDEX_UTF_16LE
#define ENCINDEX_US_ASCII
int rb_enc_get_index(VALUE obj)
rb_encoding * rb_utf8_encoding(void)
rb_encoding * rb_enc_from_index(int index)
rb_encoding * rb_filesystem_encoding(void)
int rb_enc_to_index(rb_encoding *enc)
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
int rb_econv_has_convpath_p(const char *from_encoding, const char *to_encoding)
#define ECONV_UNDEF_REPLACE
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
#define ENCODING_GET(obj)
#define ECONV_INVALID_REPLACE
char str[HTML_ESCAPE_MAX_LEN+1]
void rb_fatal(const char *fmt,...)
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
#define is_socket(fd, path)
#define GetOpenFile(obj, fp)
VALUE type(ANYARGS)
ANYARGS-ed function type.
unsigned char buf[MIME_BUF_SIZE]
ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_8
void st_free_table(st_table *tab)
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
st_table * st_init_numtable(void)
int st_insert(st_table *tab, st_data_t key, st_data_t value)
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
struct _NtCmdLineElement * next
unsigned LONG_LONG VolumeSerialNumber
uintptr_t(* func)(uintptr_t self, int argc, uintptr_t *argv)
struct constat::@265 vt100
struct sockaddr * ifa_addr
struct ifaddrs * ifa_next
union w32_io_info_t::@267 info
BY_HANDLE_FILE_INFORMATION bhfi
char * ruby_strdup(const char *)
VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker)
#define rb_w32_reparse_buffer_size(n)
#define COPY_STAT(src, dest, size_cast)
VALUE rb_w32_special_folder(int type)
int rb_w32_select_with_thread(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *timeout, void *th)
int WSAAPI rb_w32_getsockname(int fd, struct sockaddr *addr, int *addrlen)
int rb_w32_check_interrupt(void *)
int WSAAPI rb_w32_socket(int af, int type, int protocol)
int WSAAPI rb_w32_listen(int s, int backlog)
void setnetent(int stayopen)
int rb_w32_uutimensat(int dirfd, const char *path, const struct timespec *times, int flags)
int WSAAPI rb_w32_shutdown(int s, int how)
int WSAAPI rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *timeout)
struct servent *WSAAPI rb_w32_getservbyname(const char *name, const char *proto)
#define FSCTL_GET_REPARSE_POINT
int rb_w32_ftruncate(int fd, off_t length)
int rb_w32_times(struct tms *tmbuf)
struct servent *WSAAPI rb_w32_getservbyport(int port, const char *proto)
#define constat_attr_color_reverse(attr)
int kill(int pid, int sig)
struct netent * getnetent(void)
VALUE rb_dir_getwd_ospath(void)
EXTERN_C _CRTIMP ioinfo * __pioinfo[]
ssize_t rb_w32_read(int fd, void *buf, size_t size)
void rb_w32_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
SOCKET rb_w32_get_osfhandle(int fh)
int rb_w32_mkdir(const char *path, int mode)
ssize_t rb_w32_write(int fd, const void *buf, size_t size)
int rb_w32_utimes(const char *path, const struct timeval *times)
const char *WSAAPI rb_w32_inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
int rb_w32_set_thread_description(HANDLE th, const WCHAR *name)
#define SYMBOLIC_LINK_FLAG_DIRECTORY
int ioctl(int i, int u,...)
#define COMMON_LVB_UNDERSCORE
#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
int rb_w32_isatty(int fd)
rb_pid_t rb_w32_aspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags)
int sendmsg(int fd, const struct msghdr *msg, int flags)
#define INVALID_SET_FILE_POINTER
WCHAR * rb_w32_home_dir(void)
struct netent * getnetbyname(const char *name)
int symlink(const char *src, const char *link)
char * rb_w32_ugetcwd(char *buffer, int size)
int rb_w32_truncate(const char *path, off_t length)
#define rb_acrt_lowio_lock_fh(i)
int rb_w32_uchown(const char *path, int owner, int group)
#define _set_osflags(fh, flags)
int fchmod(int fd, int mode)
#define utf8_to_wstr(str, plen)
int rb_w32_umkdir(const char *path, int mode)
int rb_w32_wopen(const WCHAR *file, int oflag,...)
#define rb_w32_stati128(path, st)
DWORD(WINAPI * cilnA_t)(const NET_LUID *, char *, size_t)
DWORD(WINAPI * cigl_t)(const GUID *, NET_LUID *)
rb_pid_t rb_w32_uspawn(int mode, const char *cmd, const char *prog)
int rb_w32_ulink(const char *from, const char *to)
DIR * rb_w32_uopendir(const char *filename)
#define FILE_FILENO(stream)
long rb_w32_telldir(DIR *dirp)
int WSAAPI rb_w32_getsockopt(int s, int level, int optname, char *optval, int *optlen)
int rb_w32_stat(const char *path, struct stat *st)
int clock_gettime(clockid_t clock_id, struct timespec *sp)
int rb_w32_uchdir(const char *path)
DWORD(WINAPI * get_final_path_func)(HANDLE, WCHAR *, DWORD, DWORD)
int rb_w32_uchmod(const char *path, int mode)
struct protoent *WSAAPI rb_w32_getprotobyname(const char *name)
int rb_w32_pipe(int fds[2])
char * rb_w32_getenv(const char *name)
int rb_w32_uutime(const char *path, const struct utimbuf *times)
char * rb_w32_ugetenv(const char *name)
void rb_w32_rewinddir(DIR *dirp)
#define set_new_std_fd(newfd)
int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
int rb_w32_uaccess(const char *path, int mode)
int rb_w32_utime(const char *path, const struct utimbuf *times)
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc)
int WSAAPI rb_w32_setsockopt(int s, int level, int optname, const char *optval, int optlen)
void setprotoent(int stayopen)
#define rb_acrt_lowio_unlock_fh(i)
struct tm * localtime_r(const time_t *tp, struct tm *rp)
void rb_w32_free_environ(char **env)
char ** rb_w32_get_environ(void)
int rb_w32_fstati128(int fd, struct stati128 *st)
#define yield_until(condition)
int rb_w32_set_nonblock(int fd)
int lchown(const char *path, int owner, int group)
void rb_w32_closedir(DIR *dirp)
ssize_t readlink(const char *path, char *buf, size_t bufsize)
rb_pid_t rb_w32_aspawn(int mode, const char *prog, char *const *argv)
int WSAAPI rb_w32_connect(int s, const struct sockaddr *addr, int addrlen)
VALUE(*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE)
int WSAAPI rb_w32_getpeername(int s, struct sockaddr *addr, int *addrlen)
char * rb_w32_wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen, long *plen)
void rb_w32_fd_copy(rb_fdset_t *dst, const fd_set *src, int max)
struct tm * gmtime_r(const time_t *tp, struct tm *rp)
int rb_w32_lstati128(const char *path, struct stati128 *st)
int rb_w32_unlink(const char *path)
struct protoent * getprotoent(void)
int link(const char *from, const char *to)
rb_pid_t rb_w32_uaspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags)
UINT rb_w32_system_tmpdir(WCHAR *path, UINT len)
#define CSIDL_LOCAL_APPDATA
#define wstr_to_utf8(str, plen)
void rb_w32_seekdir(DIR *dirp, long loc)
rb_pid_t rb_w32_getppid(void)
int getifaddrs(struct ifaddrs **ifap)
int WSAAPI rb_w32_send(int fd, const char *buf, int len, int flags)
int rb_w32_rmdir(const char *path)
int rb_w32_usymlink(const char *src, const char *link)
int rb_w32_utimensat(int dirfd, const char *path, const struct timespec *times, int flags)
void rb_w32_fdset(int fd, fd_set *set)
int rb_w32_ustati128(const char *path, struct stati128 *st)
int WSAAPI rb_w32_bind(int s, const struct sockaddr *addr, int addrlen)
char rb_w32_fd_is_text(int fd)
int WSAAPI rb_w32_gethostname(char *name, int len)
int flock(int fd, int oper)
int WSAAPI rb_w32_accept(int s, struct sockaddr *addr, int *addrlen)
VALUE rb_w32_file_identical_p(VALUE fname1, VALUE fname2)
rb_pid_t rb_w32_getpid(void)
int recvmsg(int fd, struct msghdr *msg, int flags)
int rb_w32_set_thread_description_str(HANDLE th, VALUE name)
int rb_w32_urmdir(const char *path)
int __cdecl gettimeofday(struct timeval *tv, struct timezone *tz)
int rb_w32_ulchown(const char *path, int owner, int group)
struct servent * getservent(void)
#define END_FOREACH_CHILD
int rb_w32_uutimes(const char *path, const struct timeval *times)
int WSAAPI rb_w32_recv(int fd, char *buf, int len, int flags)
int rb_w32_fstat(int fd, struct stat *st)
DIR * rb_w32_opendir(const char *filename)
#define IOINFO_ARRAY_ELTS
ssize_t rb_w32_ureadlink(const char *path, char *buf, size_t bufsize)
int rb_w32_is_socket(int fd)
void setservent(int stayopen)
rb_pid_t rb_w32_spawn(int mode, const char *cmd, const char *prog)
int rb_w32_utruncate(const char *path, off_t length)
#define IO_REPARSE_TAG_SYMLINK
void rb_w32_sysinit(int *argc, char ***argv)
int WSAAPI rb_w32_sendto(int fd, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)
int rb_w32_fclose(FILE *fp)
int rb_w32_access(const char *path, int mode)
#define wstr_to_filecp(str, plen)
char * rb_w32_strerror(int e)
rb_pid_t waitpid(rb_pid_t pid, int *stat_loc, int options)
void freeifaddrs(struct ifaddrs *ifp)
WCHAR * rb_w32_mbstr_to_wstr(UINT cp, const char *str, int clen, long *plen)
int socketpair(int af, int type, int protocol, int *sv)
int rb_w32_uopen(const char *file, int oflag,...)
int rb_w32_reparse_symlink_p(const WCHAR *path)
#define _set_osfhnd(fh, osfh)
off_t rb_w32_lseek(int fd, off_t ofs, int whence)
int rb_w32_ulstati128(const char *path, struct stati128 *st)
#define MAKE_SOCKDATA(af, fl)
int chown(const char *path, int owner, int group)
int rb_w32_wrap_io_handle(HANDLE h, int flags)
int rb_w32_time_subtract(struct timeval *rest, const struct timeval *wait)
struct _NtCmdLineElement NtCmdLineElement
#define set_env_val(vname)
struct hostent *WSAAPI rb_w32_gethostbyaddr(const char *addr, int len, int type)
int rb_w32_map_errno(DWORD winerr)
#define filecp_to_wstr(str, plen)
int fcntl(int fd, int cmd,...)
void sethostent(int stayopen)
int WSAAPI rb_w32_ioctlsocket(int s, long cmd, u_long *argp)
rb_pid_t rb_w32_uaspawn(int mode, const char *prog, char *const *argv)
int rb_w32_uunlink(const char *path)
#define msghdr_to_wsamsg(msg, wsamsg)
int clock_getres(clockid_t clock_id, struct timespec *sp)
int rb_w32_urename(const char *from, const char *to)
MJIT_FUNC_EXPORTED HANDLE rb_w32_start_process(const char *abspath, char *const *argv, int out_fd)
int rb_w32_io_cancelable_p(int fd)
struct hostent *WSAAPI rb_w32_gethostbyname(const char *name)
int WSAAPI rb_w32_recvfrom(int fd, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
struct protoent *WSAAPI rb_w32_getprotobynumber(int num)
int rb_w32_open(const char *file, int oflag,...)
int rb_w32_read_reparse_point(const WCHAR *path, rb_w32_reparse_buffer_t *rp, size_t bufsize, WCHAR **result, DWORD *len)
STATIC_ASSERT(std_handle,(STD_OUTPUT_HANDLE-STD_INPUT_HANDLE)==(STD_ERROR_HANDLE-STD_OUTPUT_HANDLE))
struct netent * getnetbyaddr(long net, int type)
int rb_w32_fdisset(int fd, fd_set *set)
int rb_w32_rename(const char *from, const char *to)
uintptr_t rb_w32_asynchronize(asynchronous_func_t func, uintptr_t self, int argc, uintptr_t *argv, uintptr_t intrval)
struct direct * rb_w32_readdir(DIR *dirp, rb_encoding *enc)
#define STRNDUPV(ptr, v, src, len)
long rb_w32_write_console(uintptr_t strarg, int fd)
int WSAAPI rb_w32_inet_pton(int af, const char *src, void *dst)
char * rb_w32_getcwd(char *buffer, int size)
int rb_w32_dup2(int oldfd, int newfd)
void rb_w32_fdclr(int fd, fd_set *set)
int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout)
char * rb_w32_conv_from_wstr(const WCHAR *wstr, long *lenp, rb_encoding *enc)
int rb_w32_unwrap_io_handle(int fd)
int rb_w32_set_nonblock2(int fd, int nonblock)
int rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout)
int rb_w32_sleep(unsigned long msec)
uintptr_t(* asynchronous_func_t)(uintptr_t self, int argc, uintptr_t *argv)
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID