41 #define isdirsep(x) ((x) == '/' || (x) == '\\')
48 #if defined __BORLANDC__
49 # define _filbuf _fgetc
50 # define _flsbuf _fputc
51 # define enough_to_get(n) (--(n) >= 0)
52 # define enough_to_put(n) (++(n) < 0)
54 # define enough_to_get(n) (--(n) >= 0)
55 # define enough_to_put(n) (--(n) >= 0)
59 #define Debug(something) something
61 #define Debug(something)
64 #define TO_SOCKET(x) _get_osfhandle(x)
70 static int wstati64(
const WCHAR *path,
struct stati64 *st);
73 #define RUBY_CRITICAL(expr) do { expr; } while (0)
80 { ERROR_INVALID_FUNCTION, EINVAL },
81 { ERROR_FILE_NOT_FOUND, ENOENT },
82 { ERROR_PATH_NOT_FOUND, ENOENT },
83 { ERROR_TOO_MANY_OPEN_FILES, EMFILE },
84 { ERROR_ACCESS_DENIED, EACCES },
85 { ERROR_INVALID_HANDLE, EBADF },
86 { ERROR_ARENA_TRASHED, ENOMEM },
87 { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
88 { ERROR_INVALID_BLOCK, ENOMEM },
89 { ERROR_BAD_ENVIRONMENT, E2BIG },
90 { ERROR_BAD_FORMAT, ENOEXEC },
91 { ERROR_INVALID_ACCESS, EINVAL },
92 { ERROR_INVALID_DATA, EINVAL },
93 { ERROR_INVALID_DRIVE, ENOENT },
94 { ERROR_CURRENT_DIRECTORY, EACCES },
95 { ERROR_NOT_SAME_DEVICE, EXDEV },
96 { ERROR_NO_MORE_FILES, ENOENT },
97 { ERROR_WRITE_PROTECT, EROFS },
98 { ERROR_BAD_UNIT, ENODEV },
99 { ERROR_NOT_READY, ENXIO },
100 { ERROR_BAD_COMMAND, EACCES },
101 { ERROR_CRC, EACCES },
102 { ERROR_BAD_LENGTH, EACCES },
104 { ERROR_NOT_DOS_DISK, EACCES },
105 { ERROR_SECTOR_NOT_FOUND, EACCES },
106 { ERROR_OUT_OF_PAPER, EACCES },
107 { ERROR_WRITE_FAULT, EIO },
108 { ERROR_READ_FAULT, EIO },
109 { ERROR_GEN_FAILURE, EACCES },
110 { ERROR_LOCK_VIOLATION, EACCES },
111 { ERROR_SHARING_VIOLATION, EACCES },
112 { ERROR_WRONG_DISK, EACCES },
113 { ERROR_SHARING_BUFFER_EXCEEDED, EACCES },
114 { ERROR_BAD_NETPATH, ENOENT },
115 { ERROR_NETWORK_ACCESS_DENIED, EACCES },
116 { ERROR_BAD_NET_NAME, ENOENT },
117 { ERROR_FILE_EXISTS, EEXIST },
118 { ERROR_CANNOT_MAKE, EACCES },
119 { ERROR_FAIL_I24, EACCES },
120 { ERROR_INVALID_PARAMETER, EINVAL },
121 { ERROR_NO_PROC_SLOTS, EAGAIN },
122 { ERROR_DRIVE_LOCKED, EACCES },
123 { ERROR_BROKEN_PIPE, EPIPE },
124 { ERROR_DISK_FULL, ENOSPC },
125 { ERROR_INVALID_TARGET_HANDLE, EBADF },
126 { ERROR_INVALID_HANDLE, EINVAL },
127 { ERROR_WAIT_NO_CHILDREN, ECHILD },
128 { ERROR_CHILD_NOT_COMPLETE, ECHILD },
129 { ERROR_DIRECT_ACCESS_HANDLE, EBADF },
130 { ERROR_NEGATIVE_SEEK, EINVAL },
131 { ERROR_SEEK_ON_DEVICE, EACCES },
132 { ERROR_DIR_NOT_EMPTY, ENOTEMPTY },
133 { ERROR_DIRECTORY, ENOTDIR },
134 { ERROR_NOT_LOCKED, EACCES },
135 { ERROR_BAD_PATHNAME, ENOENT },
136 { ERROR_MAX_THRDS_REACHED, EAGAIN },
137 { ERROR_LOCK_FAILED, EACCES },
138 { ERROR_ALREADY_EXISTS, EEXIST },
139 { ERROR_INVALID_STARTING_CODESEG, ENOEXEC },
140 { ERROR_INVALID_STACKSEG, ENOEXEC },
141 { ERROR_INVALID_MODULETYPE, ENOEXEC },
142 { ERROR_INVALID_EXE_SIGNATURE, ENOEXEC },
143 { ERROR_EXE_MARKED_INVALID, ENOEXEC },
144 { ERROR_BAD_EXE_FORMAT, ENOEXEC },
145 { ERROR_ITERATED_DATA_EXCEEDS_64k,ENOEXEC },
146 { ERROR_INVALID_MINALLOCSIZE, ENOEXEC },
147 { ERROR_DYNLINK_FROM_INVALID_RING,ENOEXEC },
148 { ERROR_IOPL_NOT_ENABLED, ENOEXEC },
149 { ERROR_INVALID_SEGDPL, ENOEXEC },
150 { ERROR_AUTODATASEG_EXCEEDS_64k, ENOEXEC },
151 { ERROR_RING2SEG_MUST_BE_MOVABLE, ENOEXEC },
152 { ERROR_RELOC_CHAIN_XEEDS_SEGLIM, ENOEXEC },
153 { ERROR_INFLOOP_IN_RELOC_CHAIN, ENOEXEC },
154 { ERROR_FILENAME_EXCED_RANGE, ENOENT },
155 { ERROR_NESTING_NOT_ALLOWED, EAGAIN },
156 #ifndef ERROR_PIPE_LOCAL
157 #define ERROR_PIPE_LOCAL 229L
160 { ERROR_BAD_PIPE, EPIPE },
161 { ERROR_PIPE_BUSY, EAGAIN },
162 { ERROR_NO_DATA, EPIPE },
163 { ERROR_PIPE_NOT_CONNECTED, EPIPE },
164 { ERROR_OPERATION_ABORTED, EINTR },
165 { ERROR_NOT_ENOUGH_QUOTA, ENOMEM },
166 { ERROR_MOD_NOT_FOUND, ENOENT },
169 { WSAEACCES, EACCES },
170 { WSAEFAULT, EFAULT },
171 { WSAEINVAL, EINVAL },
172 { WSAEMFILE, EMFILE },
201 { WSAENAMETOOLONG, ENAMETOOLONG },
205 { WSAENOTEMPTY, ENOTEMPTY },
221 for (i = 0; i < (int)(
sizeof(
errmap) /
sizeof(*
errmap)); i++) {
222 if (
errmap[i].winerr == winerr) {
227 if (winerr >= WSABASEERR) {
233 #define map_errno rb_w32_map_errno
242 memset(&
osver, 0,
sizeof(OSVERSIONINFO));
243 osver.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
244 GetVersionEx(&
osver);
251 return osver.dwPlatformId;
258 return osver.dwMajorVersion;
261 #define IsWinNT() rb_w32_iswinnt()
262 #define IsWin95() rb_w32_iswin95()
264 #define IfWin95(win95, winnt) (IsWin95() ? (win95) : (winnt))
266 #define IfWin95(win95, winnt) (winnt)
272 static HANDLE current_process_handle =
NULL;
275 if (!current_process_handle)
276 current_process_handle = GetCurrentProcess();
277 if (!DuplicateHandle(current_process_handle, GetCurrentThread(),
278 current_process_handle, &h,
279 0,
FALSE, DUPLICATE_SAME_ACCESS))
287 #define LK_ERR(f,i) \
292 DWORD err = GetLastError(); \
293 if (err == ERROR_LOCK_VIOLATION || err == ERROR_IO_PENDING) \
294 errno = EWOULDBLOCK; \
295 else if (err == ERROR_NOT_LOCKED) \
298 errno = map_errno(err); \
301 #define LK_LEN ULONG_MAX
308 const HANDLE fh = (HANDLE)
self;
309 const int oper =
argc;
311 memset(&o, 0,
sizeof(o));
325 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
344 const HANDLE fh = (HANDLE)
self;
345 const int oper =
argc;
380 locker = flock_win95;
391 static inline WCHAR *
405 if ((
unsigned char)*p == from)
412 #ifndef CSIDL_LOCAL_APPDATA
413 #define CSIDL_LOCAL_APPDATA 28
415 #ifndef CSIDL_COMMON_APPDATA
416 #define CSIDL_COMMON_APPDATA 35
418 #ifndef CSIDL_WINDOWS
419 #define CSIDL_WINDOWS 36
422 #define CSIDL_SYSTEM 37
424 #ifndef CSIDL_PROFILE
425 #define CSIDL_PROFILE 40
434 if (SHGetSpecialFolderLocation(
NULL, n, &pidl) == 0) {
435 f = SHGetPathFromIDListW(pidl, env);
437 alloc->lpVtbl->Free(alloc, pidl);
438 alloc->lpVtbl->Release(alloc);
447 if (p - path == 2 && path[1] == L
':') {
460 h = LoadLibrary(module);
462 h = GetModuleHandle(module);
466 ptr = GetProcAddress(h, func);
479 typedef UINT WINAPI wgetdir_func(WCHAR*, UINT);
483 return (*(wgetdir_func *)ptr)(path,
len);
484 return GetWindowsDirectoryW(path, len);
487 #define numberof(array) (sizeof(array) / sizeof(*array))
492 WCHAR path[_MAX_PATH];
502 static const WCHAR temp[] = L
"temp";
509 if (*(p - 1) != L
'/') *p++ = L
'/';
510 if (p - path +
numberof(temp) >= len)
return 0;
511 memcpy(p, temp,
sizeof(temp));
512 return p - path +
numberof(temp) - 1;
518 static const WCHAR TMPDIR[] = L
"TMPDIR";
519 struct {WCHAR
name[6],
eq, val[_MAX_PATH];} wk;
523 #define set_env_val(vname) do { \
524 typedef char namesizecheck[numberof(wk.name) < numberof(vname) - 1 ? -1 : 1]; \
525 WCHAR *const buf = wk.name + numberof(wk.name) - numberof(vname) + 1; \
526 MEMCPY(buf, vname, WCHAR, numberof(vname) - 1); \
538 if (GetEnvironmentVariableW(L
"HOMEPATH",
env + len,
numberof(
env) - len) || len) {
541 else if (GetEnvironmentVariableW(L
"USERPROFILE",
env,
numberof(
env))) {
592 invalid_parameter(
const wchar_t *
expr,
const wchar_t *
func,
const wchar_t *file,
unsigned int line,
uintptr_t dummy)
597 int ruby_w32_rtc_error;
600 rtc_error_handler(
int e,
const char *src,
int line,
const char *exe,
const char *fmt, ...)
605 if (!ruby_w32_rtc_error)
return 0;
624 if (NtSocketsInitialized) {
628 NtSocketsInitialized = 0;
631 FreeEnvironmentStrings(envarea);
634 DeleteCriticalSection(&select_mutex);
647 version = MAKEWORD(2, 0);
648 if (WSAStartup(version, &retdata))
649 rb_fatal (
"Unable to locate winsock library!\n");
650 if (LOBYTE(retdata.wVersion) != 2)
651 rb_fatal(
"could not find version 2 of winsock dll\n");
655 NtSocketsInitialized = 1;
665 static void set_pioinfo_extra(
void);
667 _CrtSetReportMode(_CRT_ASSERT, 0);
668 _set_invalid_parameter_handler(invalid_parameter);
669 _RTC_SetErrorFunc(rtc_error_handler);
672 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX);
694 InitializeCriticalSection(&select_mutex);
708 #define MAXCHILDNUM 256
715 #define FOREACH_CHILD(v) do { \
716 struct ChildRecord* v; \
717 for (v = ChildRecord; v < ChildRecord + sizeof(ChildRecord) / sizeof(ChildRecord[0]); ++v)
718 #define END_FOREACH_CHILD } while (0)
725 if (child->pid == pid) {
737 if (child->hProcess == h) {
759 child->hProcess =
NULL;
828 return strcmp(key, *(
const char *
const *)elem);
834 int i =
strlen(interp) - 11;
836 if ((i == 0 || i > 0 &&
isdirsep(interp[i-1])) &&
848 char cmdname[9], *b = cmdname, c;
851 if (!(c = *cmd++))
return 0;
852 }
while (isspace(c));
857 if (b == cmdname +
sizeof(cmdname))
return 0;
860 if (c ==
'.') c = *cmd;
862 case '<':
case '>':
case '|':
864 case '\0':
case ' ':
case '\t':
case '\n':
878 nm = bsearch(cmdname, szInternalCmds,
879 sizeof(szInternalCmds) /
sizeof(*szInternalCmds),
880 sizeof(*szInternalCmds),
882 if (!nm || !(nm[0][-1] & (nt ? 2 : 1)))
890 return _get_osfhandle(fh);
898 int len, n, bs, quote;
900 for (t = argv, q = cmd, len = 0; p = *t; t++) {
903 if (!*p || strpbrk(p,
" \t\"'")) {
908 for (bs = 0; *
p; ++
p) {
927 case '<':
case '>':
case '|':
case '^':
928 if (escape && !quote) {
929 len += (n = p - s) + 1;
944 len += (n = p - s) + 1;
949 if (quote) *q++ =
'"';
961 #ifdef HAVE_SYS_PARAM_H
962 # include <sys/param.h>
964 # define MAXPATHLEN 512
967 #define STRNDUPV(ptr, v, src, len) \
968 (((char *)memcpy(((ptr) = ALLOCV((v), (len) + 1)), (src), (len)))[len] = 0)
996 WaitForSingleObject(child->
hProcess, INFINITE);
997 GetExitCodeProcess(child->
hProcess, &exitcode);
1006 CreateChild(
const WCHAR *cmd,
const WCHAR *prog, SECURITY_ATTRIBUTES *psa,
1007 HANDLE hInput, HANDLE hOutput, HANDLE hError,
DWORD dwCreationFlags)
1010 STARTUPINFOW aStartupInfo;
1011 PROCESS_INFORMATION aProcessInformation;
1012 SECURITY_ATTRIBUTES sa;
1015 if (!cmd && !prog) {
1027 sa.nLength =
sizeof (SECURITY_ATTRIBUTES);
1028 sa.lpSecurityDescriptor =
NULL;
1029 sa.bInheritHandle =
TRUE;
1033 memset(&aStartupInfo, 0,
sizeof(aStartupInfo));
1034 memset(&aProcessInformation, 0,
sizeof(aProcessInformation));
1035 aStartupInfo.cb =
sizeof(aStartupInfo);
1036 aStartupInfo.dwFlags = STARTF_USESTDHANDLES;
1038 aStartupInfo.hStdInput = hInput;
1041 aStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1044 aStartupInfo.hStdOutput = hOutput;
1047 aStartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1050 aStartupInfo.hStdError = hError;
1053 aStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
1056 dwCreationFlags |= NORMAL_PRIORITY_CLASS;
1058 if (lstrlenW(cmd) > 32767) {
1065 fRet = CreateProcessW(prog, (WCHAR *)cmd, psa, psa,
1066 psa->bInheritHandle, dwCreationFlags,
NULL,
NULL,
1067 &aStartupInfo, &aProcessInformation);
1076 CloseHandle(aProcessInformation.hThread);
1078 child->
hProcess = aProcessInformation.hProcess;
1079 child->
pid = (rb_pid_t)aProcessInformation.dwProcessId;
1083 child->
pid = -child->
pid;
1093 if (len <= 4)
return 0;
1095 if (*cmd++ !=
'.')
return 0;
1101 static UINT
filecp(
void);
1102 static WCHAR *
mbstr_to_wstr(UINT,
const char *,
int,
long *);
1103 static char *
wstr_to_mbstr(UINT,
const WCHAR *,
int,
long *);
1104 #define acp_to_wstr(str, plen) mbstr_to_wstr(CP_ACP, str, -1, plen)
1105 #define wstr_to_acp(str, plen) wstr_to_mbstr(CP_ACP, str, -1, plen)
1106 #define filecp_to_wstr(str, plen) mbstr_to_wstr(filecp(), str, -1, plen)
1107 #define wstr_to_filecp(str, plen) wstr_to_mbstr(filecp(), str, -1, plen)
1108 #define utf8_to_wstr(str, plen) mbstr_to_wstr(CP_UTF8, str, -1, plen)
1109 #define wstr_to_utf8(str, plen) wstr_to_mbstr(CP_UTF8, str, -1, plen)
1116 const char *shell =
NULL;
1117 WCHAR *wcmd, *wshell;
1139 sprintf(tmp,
"%s -c \"%s\"", shell, cmd);
1142 else if ((shell =
getenv(
"COMSPEC")) &&
1147 sprintf(tmp, nt ?
"%s /c \"%s\"" :
"%s /c %s", shell, cmd);
1151 int len = 0, quote = (*cmd ==
'"') ?
'"' : (*cmd ==
'\'') ?
'\'' : 0;
1152 for (prog = cmd + !!quote;; prog =
CharNext(prog)) {
1158 if ((
unsigned char)*prog == quote) {
1159 len = prog++ - cmd - 1;
1164 if (quote)
continue;
1174 shell = p ? p : cmd;
1178 if (
strchr(shell,
' ')) quote = -1;
1179 if (shell == fbuf) {
1182 else if (shell != p &&
strchr(shell,
'/')) {
1189 cmd = p =
ALLOCV(v, len + alen + (quote ? 2 : 0) + 1);
1190 if (quote) *p++ =
'"';
1191 memcpy(p, shell, len);
1193 if (quote) *p++ =
'"';
1194 memcpy(p, prog, alen + 1);
1218 BOOL ntcmd =
FALSE, tmpnt;
1221 WCHAR *wcmd, *wprog;
1227 if (!prog) prog = argv[0];
1228 if ((shell =
getenv(
"COMSPEC")) &&
1235 if (cmd == prog)
strlcpy(cmd = fbuf, prog,
sizeof(fbuf));
1239 else if (
strchr(prog,
'/')) {
1241 if (len <
sizeof(fbuf))
1242 strlcpy(cmd = fbuf, prog,
sizeof(fbuf));
1250 progs[0] = (
char *)prog;
1253 if (c_switch) len += 3;
1258 if (c_switch)
strlcat(cmd,
" /c", len);
1260 prog = c_switch ? shell : 0;
1297 #define NTGLOB 0x1 // element contains a wildcard
1298 #define NTMALLOC 0x2 // string in element was malloc'ed
1299 #define NTSTRING 0x4 // element contains a quoted string
1308 if (!tmpcurr)
return -1;
1312 if (!tmpcurr->
str)
return -1;
1315 *tail = &tmpcurr->
next;
1330 if (!(buf =
malloc(patt->
len + 1)))
return 0;
1333 buf[patt->
len] =
'\0';
1341 if (status || last == tail)
return 0;
1364 for (ptr = cmd; *ptr;) {
1370 else if (quote == *ptr)
1386 if (*++ptr !=
'_' && !
ISALPHA(*ptr))
break;
1387 while (*++ptr ==
'_' ||
ISALNUM(*ptr));
1388 if (*ptr++ ==
'%')
return TRUE;
1401 static inline char *
1413 int elements, strsz, done;
1414 int slashes, escape;
1415 char *ptr, *base, *buffer, *cmdline;
1432 ptr = cmdline =
strdup(cmd);
1445 quote = slashes = globbing = escape = 0;
1446 for (done = 0; !done && *ptr; ) {
1455 if (quote !=
'\'') slashes++;
1495 if (!(slashes & 1)) {
1498 else if (quote == *ptr) {
1499 if (quote ==
'"' && quote == ptr[1])
1532 slashes = quote = 0;
1533 while (p < base + len) {
1537 if (quote !=
'\'') slashes++;
1542 if (!(slashes & 1) && quote && quote != c) {
1547 memcpy(p - ((slashes + 1) >> 1), p + (~slashes & 1),
1549 len -= ((slashes + 1) >> 1) + (~slashes & 1);
1550 p -= (slashes + 1) >> 1;
1551 if (!(slashes & 1)) {
1553 if (quote ==
'"' && quote == *p)
1574 if (!curr)
goto do_nothing;
1578 if (globbing && (tail =
cmdglob(curr, cmdtail))) {
1583 cmdtail = &curr->
next;
1593 for (elements = 0, strsz = 0, curr = cmdhead; curr; curr = curr->
next) {
1595 strsz += (curr->
len + 1);
1598 len = (elements+1)*
sizeof(
char *) + strsz;
1599 buffer = (
char *)
malloc(len);
1602 while (curr = cmdhead) {
1603 cmdhead = curr->
next;
1608 for (vptr = *vec; *vptr; ++vptr);
1624 vptr = (
char **) buffer;
1626 ptr = buffer + (elements+1) *
sizeof(
char *);
1628 while (curr = cmdhead) {
1631 ptr += curr->
len + 1;
1632 cmdhead = curr->
next;
1638 *vec = (
char **) buffer;
1647 #define PATHLEN 1024
1655 #define GetBit(bits, i) ((bits)[(i) / CHAR_BIT] & (1 << (i) % CHAR_BIT))
1656 #define SetBit(bits, i) ((bits)[(i) / CHAR_BIT] |= (1 << (i) % CHAR_BIT))
1658 #define BitOfIsDir(n) ((n) * 2)
1659 #define BitOfIsRep(n) ((n) * 2 + 1)
1660 #define DIRENT_PER_CHAR (CHAR_BIT / 2)
1666 static const WCHAR wildcard[] = L
"\\*";
1675 len = lstrlenW(filename);
1676 scanname =
ALLOCV_N(WCHAR, v, len +
sizeof(wildcard) /
sizeof(WCHAR));
1677 lstrcpyW(scanname, filename);
1678 p = CharPrevW(scanname, scanname + len);
1679 if (*p == L
'/' || *p == L
'\\' || *p == L
':')
1680 lstrcatW(scanname, wildcard + 1);
1682 lstrcatW(scanname, wildcard);
1687 fh = FindFirstFileW(scanname, fd);
1689 if (fh == INVALID_HANDLE_VALUE) {
1698 struct stati64 sbuf;
1699 WIN32_FIND_DATAW fd;
1713 if (!(sbuf.st_mode & S_IFDIR) &&
1714 (!
ISALPHA(filename[0]) || filename[1] !=
':' || filename[2] !=
'\0' ||
1715 ((1 << ((filename[0] & 0x5f) -
'A')) & GetLogicalDrives()) == 0)) {
1720 if (fh == INVALID_HANDLE_VALUE) {
1740 len = lstrlenW(fd.cFileName) + 1;
1756 memcpy(&p->
start[idx], fd.cFileName, len *
sizeof(WCHAR));
1765 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1767 if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1772 }
while (FindNextFileW(fh, &fd));
1782 UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1790 int len = WideCharToMultiByte(cp, 0, wstr, clen,
NULL, 0,
NULL,
NULL) - 1;
1791 if (!(ptr =
malloc(len + 1)))
return 0;
1792 WideCharToMultiByte(cp, 0, wstr, clen, ptr, len + 1,
NULL,
NULL);
1793 if (plen) *plen =
len;
1801 int len = MultiByteToWideChar(cp, 0, str, clen,
NULL, 0) - 1;
1802 if (!(ptr =
malloc(
sizeof(WCHAR) * (len + 1))))
return 0;
1803 MultiByteToWideChar(cp, 0, str, clen, ptr, len + 1);
1804 if (plen) *plen =
len;
1841 dirp->
curr += lstrlenW(dirp->
curr) + 1;
1875 src =
rb_enc_str_new((
char *)wstr, lstrlenW(wstr) *
sizeof(WCHAR), utf16);
1904 static int dummy = 0;
1973 while (dirp->
curr && dirp->
loc < loc) {
2007 #if (defined _MT || defined __MSVCRT__) && !defined __BORLANDC__
2008 #define MSVCRT_THREADS
2010 #ifdef MSVCRT_THREADS
2011 # define MTHREAD_ONLY(x) x
2012 # define STHREAD_ONLY(x)
2013 #elif defined(__BORLANDC__)
2014 # define MTHREAD_ONLY(x)
2015 # define STHREAD_ONLY(x)
2017 # define MTHREAD_ONLY(x)
2018 # define STHREAD_ONLY(x) x
2025 #ifdef MSVCRT_THREADS
2027 CRITICAL_SECTION lock;
2035 #if !defined _CRTIMP || defined __MINGW32__
2037 #define _CRTIMP __declspec(dllimport)
2040 #if !defined(__BORLANDC__)
2043 #define IOINFO_L2E 5
2044 #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
2045 #define _pioinfo(i) ((ioinfo*)((char*)(__pioinfo[i >> IOINFO_L2E]) + (i & (IOINFO_ARRAY_ELTS - 1)) * (sizeof(ioinfo) + pioinfo_extra)))
2046 #define _osfhnd(i) (_pioinfo(i)->osfhnd)
2047 #define _osfile(i) (_pioinfo(i)->osfile)
2048 #define _pipech(i) (_pioinfo(i)->pipech)
2054 set_pioinfo_extra(
void)
2058 fd = _open(
"NUL", O_RDONLY);
2059 for (pioinfo_extra = 0; pioinfo_extra <= 64; pioinfo_extra +=
sizeof(
void *)) {
2060 if (
_osfhnd(fd) == _get_osfhandle(fd)) {
2066 if (pioinfo_extra > 64) {
2072 #define pioinfo_extra 0
2075 #define _set_osfhnd(fh, osfh) (void)(_osfhnd(fh) = osfh)
2076 #define _set_osflags(fh, flags) (_osfile(fh) = (flags))
2079 #define FEOFLAG 0x02
2081 #define FNOINHERIT 0x10
2082 #define FAPPEND 0x20
2105 if (flags & O_APPEND)
2111 if (flags & O_NOINHERIT)
2115 hF = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
2116 fh = _open_osfhandle((
intptr_t)hF, 0);
2141 #define open_null(fd) \
2143 (nullfd = open("NUL", O_RDWR)) : 0), \
2144 ((nullfd == (fd)) ? (keep = 1) : dup2(nullfd, fd)), \
2153 if (
fileno(stdout) < 0) {
2156 if (
fileno(stderr) < 0) {
2159 if (nullfd >= 0 && !keep) close(nullfd);
2160 setvbuf(stderr,
NULL, _IONBF, 0);
2164 #define _set_osfhnd(fh, osfh) (void)((fh), (osfh))
2165 #define _set_osflags(fh, flags) (void)((fh), (flags))
2177 int fd = _open_osfhandle(osfhandle, flags);
2214 static char buffer[512];
2218 #if defined __BORLANDC__ && defined ENOTEMPTY // _sys_errlist is broken
2221 return "Filename too long";
2223 return "Directory not empty";
2230 #if WSAEWOULDBLOCK != EWOULDBLOCK
2235 for (s = 0; s < (int)(
sizeof(
errmap)/
sizeof(*
errmap)); s++)
2238 for (i = s; i < (int)(
sizeof(
errmap)/
sizeof(*errmap)); i++)
2245 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
2246 FORMAT_MESSAGE_IGNORE_INSERTS, &source, e,
2247 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
2248 buffer,
sizeof(buffer),
NULL) == 0 &&
2249 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
2250 FORMAT_MESSAGE_IGNORE_INSERTS, &source, e, 0,
2251 buffer,
sizeof(buffer),
NULL) == 0)
2252 strlcpy(buffer,
"Unknown Error",
sizeof(buffer));
2258 while ((p = strpbrk(p,
"\r\n")) !=
NULL) {
2339 for (i = 0; i <
set->fd_count; i++) {
2340 if (set->fd_array[i] == s) {
2341 memmove(&set->fd_array[i], &set->fd_array[i+1],
2342 sizeof(set->fd_array[0]) * (--set->fd_count - i));
2355 if (s == (SOCKET)INVALID_HANDLE_VALUE)
2364 max =
min(src->fd_count, (UINT)max);
2365 if ((UINT)dst->capa < (UINT)max) {
2367 dst->fdset =
xrealloc(dst->fdset,
sizeof(
unsigned int) +
sizeof(SOCKET) * dst->capa);
2370 memcpy(dst->fdset->fd_array, src->fd_array,
2371 max *
sizeof(src->fd_array[0]));
2372 dst->fdset->fd_count = src->fd_count;
2379 if ((UINT)dst->capa < src->fdset->fd_count) {
2381 dst->fdset =
xrealloc(dst->fdset,
sizeof(
unsigned int) +
sizeof(SOCKET) * dst->capa);
2384 memcpy(dst->fdset->fd_array, src->fdset->fd_array,
2385 src->fdset->fd_count *
sizeof(src->fdset->fd_array[0]));
2386 dst->fdset->fd_count = src->fdset->fd_count;
2404 while (s < src->fd_count) {
2405 SOCKET fd = src->fd_array[s];
2411 for (d = 0; d < dst->fdset->fd_count; d++) {
2412 if (dst->fdset->fd_array[d] == fd)
2415 if (d == dst->fdset->fd_count) {
2416 if ((
int)dst->fdset->fd_count >= dst->capa) {
2418 dst->fdset =
xrealloc(dst->fdset,
sizeof(
unsigned int) +
sizeof(SOCKET) * dst->capa);
2420 dst->fdset->fd_array[dst->fdset->fd_count++] = fd;
2424 &src->fd_array[s+1],
2425 sizeof(src->fd_array[0]) * (--src->fd_count - s));
2435 return dst ? dst->fdset->fd_count : m;
2442 if (!src || !dst)
return 0;
2444 for (s = 0; s < src->fd_count; ++s) {
2445 SOCKET fd = src->fd_array[s];
2447 for (d = 0; d < dst->fd_count; ++d) {
2448 if (dst->fd_array[d] == fd)
2452 dst->fd_array[dst->fd_count++] = fd;
2456 return dst->fd_count;
2471 ret = (GetFileType((HANDLE)sock) == FILE_TYPE_PIPE);
2484 if (PeekNamedPipe((HANDLE)sock,
NULL, 0,
NULL, &n,
NULL)) {
2488 ret = (GetLastError() == ERROR_BROKEN_PIPE);
2503 ret = (PeekConsoleInput((HANDLE)sock, &ir, 1, &n))
2517 if (PeekConsoleInput((HANDLE)sock, &ir, 1, &n) && n > 0) {
2518 if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown &&
2519 ir.Event.KeyEvent.uChar.AsciiChar) {
2523 ReadConsoleInput((HANDLE)sock, &ir, 1, &n);
2534 return (HANDLE)sock == INVALID_HANDLE_VALUE;
2551 EnterCriticalSection(&select_mutex);
2552 r = select(nfds, rd, wr, ex, timeout);
2553 LeaveCriticalSection(&select_mutex);
2554 if (r == SOCKET_ERROR) {
2607 struct timeval *timeout,
void *th)
2616 struct timeval limit = {0, 0};
2618 if (nfds < 0 || (timeout && (timeout->
tv_sec < 0 || timeout->
tv_usec < 0))) {
2624 if (timeout->
tv_sec < 0 ||
2626 timeout->
tv_usec >= 1000000) {
2633 if (limit.
tv_usec >= 1000000) {
2639 if (!NtSocketsInitialized) {
2674 if (rd && (
int)rd->fd_count > r) r = (int)rd->fd_count;
2675 if (wr && (
int)wr->fd_count > r) r = (
int)wr->fd_count;
2676 if (ex && (
int)ex->fd_count > r) r = (
int)ex->fd_count;
2677 if (nfds > r) nfds = r;
2697 if (else_rd.fdset->fd_count || else_wr.fdset->fd_count) {
2700 r +=
copy_fd(rd, else_rd.fdset);
2701 r +=
copy_fd(wr, else_wr.fdset);
2717 if (rd)
copy_fd(&orig_rd, rd);
2718 if (wr)
copy_fd(&orig_wr, wr);
2719 if (ex)
copy_fd(&orig_ex, ex);
2722 if (rd)
copy_fd(rd, &orig_rd);
2723 if (wr)
copy_fd(wr, &orig_wr);
2724 if (ex)
copy_fd(ex, &orig_ex);
2731 if (
compare(&rest, &wait) < 0) dowait = &rest;
2760 WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, guid,
sizeof(*guid),
2761 &ptr,
sizeof(ptr), &dmy,
NULL,
NULL);
2775 if (!NtSocketsInitialized) {
2779 HANDLE h = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
2782 r = accept(
TO_SOCKET(s), addr, addrlen);
2783 if (r != INVALID_SOCKET) {
2809 if (!NtSocketsInitialized) {
2814 if (r == SOCKET_ERROR)
2826 if (!NtSocketsInitialized) {
2830 r = connect(
TO_SOCKET(s), addr, addrlen);
2831 if (r == SOCKET_ERROR) {
2832 int err = WSAGetLastError();
2833 if (err != WSAEWOULDBLOCK)
2849 if (!NtSocketsInitialized) {
2853 r = getpeername(
TO_SOCKET(s), addr, addrlen);
2854 if (r == SOCKET_ERROR)
2866 if (!NtSocketsInitialized) {
2870 r = getsockname(
TO_SOCKET(s), addr, addrlen);
2871 if (r == SOCKET_ERROR)
2881 if (!NtSocketsInitialized) {
2885 r = getsockopt(
TO_SOCKET(s), level, optname, optval, optlen);
2886 if (r == SOCKET_ERROR)
2898 if (!NtSocketsInitialized) {
2902 r = ioctlsocket(
TO_SOCKET(s), cmd, argp);
2903 if (r == SOCKET_ERROR)
2915 if (!NtSocketsInitialized) {
2920 if (r == SOCKET_ERROR)
2937 if (result != SOCKET_ERROR)
2939 else if ((err = WSAGetLastError()) == WSA_IO_PENDING) {
2943 result = WSAGetOverlappedResult(s, wol, &size,
TRUE, &flg)
2953 case WAIT_OBJECT_0 + 1:
2964 CloseHandle(wol->hEvent);
2971 struct sockaddr *addr,
int *addrlen)
2982 if (!NtSocketsInitialized)
2991 if (addr && addrlen)
2992 r = recvfrom(s, buf, len, flags, addr, addrlen);
2994 r = recv(s, buf, len, flags);
2997 if (addr && addrlen)
2998 r = sendto(s, buf, len, flags, addr, *addrlen);
3000 r = send(s, buf, len, flags);
3002 if (r == SOCKET_ERROR)
3011 memset(&wol, 0,
sizeof(wol));
3016 if (addr && addrlen)
3017 ret = WSARecvFrom(s, &wbuf, 1, &size, &flg, addr, addrlen,
3020 ret = WSARecv(s, &wbuf, 1, &size, &flg, &wol,
NULL);
3023 if (addr && addrlen)
3024 ret = WSASendTo(s, &wbuf, 1, &size, flags, addr, *addrlen,
3027 ret = WSASend(s, &wbuf, 1, &size, flags, &wol,
NULL);
3046 struct sockaddr *from,
int *fromlen)
3059 const struct sockaddr *to,
int tolen)
3062 (
struct sockaddr *)to, &tolen);
3065 #if !defined(MSG_TRUNC) && !defined(__MINGW32__)
3075 #ifndef WSAID_WSARECVMSG
3076 #define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
3078 #ifndef WSAID_WSASENDMSG
3079 #define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
3082 #define msghdr_to_wsamsg(msg, wsamsg) \
3085 (wsamsg)->name = (msg)->msg_name; \
3086 (wsamsg)->namelen = (msg)->msg_namelen; \
3087 (wsamsg)->lpBuffers = ALLOCA_N(WSABUF, (msg)->msg_iovlen); \
3088 (wsamsg)->dwBufferCount = (msg)->msg_iovlen; \
3089 for (i = 0; i < (msg)->msg_iovlen; ++i) { \
3090 (wsamsg)->lpBuffers[i].buf = (msg)->msg_iov[i].iov_base; \
3091 (wsamsg)->lpBuffers[i].len = (msg)->msg_iov[i].iov_len; \
3093 (wsamsg)->Control.buf = (msg)->msg_control; \
3094 (wsamsg)->Control.len = (msg)->msg_controllen; \
3095 (wsamsg)->dwFlags = (msg)->msg_flags; \
3101 typedef int (WSAAPI *WSARecvMsg_t)(SOCKET,
WSAMSG *,
DWORD *, WSAOVERLAPPED *, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
3102 static WSARecvMsg_t pWSARecvMsg =
NULL;
3110 if (!NtSocketsInitialized)
3129 if ((ret = pWSARecvMsg(s, &wsamsg, &len,
NULL,
NULL)) == SOCKET_ERROR) {
3138 memset(&wol, 0,
sizeof(wol));
3141 ret = pWSARecvMsg(s, &wsamsg, &size, &wol,
NULL);
3146 if (ret == SOCKET_ERROR)
3160 typedef int (WSAAPI *WSASendMsg_t)(SOCKET,
const WSAMSG *,
DWORD, DWORD *, WSAOVERLAPPED *, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
3161 static WSASendMsg_t pWSASendMsg =
NULL;
3169 if (!NtSocketsInitialized)
3187 if ((ret = pWSASendMsg(s, &wsamsg, flags, &len,
NULL,
NULL)) == SOCKET_ERROR) {
3196 memset(&wol, 0,
sizeof(wol));
3199 ret = pWSASendMsg(s, &wsamsg, flags, &size, &wol,
NULL);
3214 if (!NtSocketsInitialized) {
3218 r = setsockopt(
TO_SOCKET(s), level, optname, optval, optlen);
3219 if (r == SOCKET_ERROR)
3231 if (!NtSocketsInitialized) {
3236 if (r == SOCKET_ERROR)
3245 unsigned long proto_buffers_len = 0;
3247 SOCKET out = INVALID_SOCKET;
3249 if (WSAEnumProtocols(
NULL,
NULL, &proto_buffers_len) == SOCKET_ERROR) {
3250 error_code = WSAGetLastError();
3251 if (error_code == WSAENOBUFS) {
3252 WSAPROTOCOL_INFO *proto_buffers;
3253 int protocols_available = 0;
3255 proto_buffers = (WSAPROTOCOL_INFO *)
malloc(proto_buffers_len);
3256 if (!proto_buffers) {
3257 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
3258 return INVALID_SOCKET;
3261 protocols_available =
3262 WSAEnumProtocols(
NULL, proto_buffers, &proto_buffers_len);
3263 if (protocols_available != SOCKET_ERROR) {
3265 for (i = 0; i < protocols_available; i++) {
3266 if ((af !=
AF_UNSPEC && af != proto_buffers[i].iAddressFamily) ||
3267 (type != proto_buffers[i].iSocketType) ||
3268 (protocol != 0 && protocol != proto_buffers[i].iProtocol))
3271 if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0)
3274 out = WSASocket(af, type, protocol, &(proto_buffers[i]), 0,
3275 WSA_FLAG_OVERLAPPED);
3278 if (out == INVALID_SOCKET)
3279 out = WSASocket(af, type, protocol,
NULL, 0, 0);
3282 free(proto_buffers);
3297 if (!NtSocketsInitialized) {
3302 if (s == INVALID_SOCKET) {
3317 #undef gethostbyaddr
3319 struct hostent * WSAAPI
3323 if (!NtSocketsInitialized) {
3327 r = gethostbyaddr(addr, len, type);
3334 #undef gethostbyname
3336 struct hostent * WSAAPI
3340 if (!NtSocketsInitialized) {
3344 r = gethostbyname(name);
3357 if (!NtSocketsInitialized) {
3361 r = gethostname(name, len);
3362 if (r == SOCKET_ERROR)
3368 #undef getprotobyname
3370 struct protoent * WSAAPI
3374 if (!NtSocketsInitialized) {
3378 r = getprotobyname(name);
3385 #undef getprotobynumber
3387 struct protoent * WSAAPI
3391 if (!NtSocketsInitialized) {
3395 r = getprotobynumber(num);
3402 #undef getservbyname
3404 struct servent * WSAAPI
3408 if (!NtSocketsInitialized) {
3412 r = getservbyname(name, proto);
3419 #undef getservbyport
3421 struct servent * WSAAPI
3425 if (!NtSocketsInitialized) {
3429 r = getservbyport(port, proto);
3439 SOCKET svr = INVALID_SOCKET, r = INVALID_SOCKET, w = INVALID_SOCKET;
3440 struct sockaddr_in sock_in4;
3442 struct sockaddr_in6 sock_in6;
3444 struct sockaddr *addr;
3448 if (!NtSocketsInitialized) {
3454 #if defined PF_INET && PF_INET != AF_INET
3457 sock_in4.sin_family = AF_INET;
3458 sock_in4.sin_port = 0;
3459 sock_in4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3460 addr = (
struct sockaddr *)&sock_in4;
3461 len =
sizeof(sock_in4);
3465 memset(&sock_in6, 0,
sizeof(sock_in6));
3466 sock_in6.sin6_family = AF_INET6;
3467 sock_in6.sin6_addr = IN6ADDR_LOOPBACK_INIT;
3468 addr = (
struct sockaddr *)&sock_in6;
3469 len =
sizeof(sock_in6);
3476 if (type != SOCK_STREAM) {
3481 sv[0] = (SOCKET)INVALID_HANDLE_VALUE;
3482 sv[1] = (SOCKET)INVALID_HANDLE_VALUE;
3486 if (svr == INVALID_SOCKET)
3488 if (bind(svr, addr, len) < 0)
3490 if (getsockname(svr, addr, &len) < 0)
3492 if (type == SOCK_STREAM)
3496 if (w == INVALID_SOCKET)
3498 if (connect(w, addr, len) < 0)
3501 r = accept(svr, addr, &len);
3502 if (r == INVALID_SOCKET)
3510 if (r != INVALID_SOCKET)
3512 if (w != INVALID_SOCKET)
3519 if (svr != INVALID_SOCKET)
3535 closesocket(pair[0]);
3536 closesocket(pair[1]);
3542 closesocket(pair[1]);
3599 arg = va_arg(va,
int);
3608 flag &= ~O_NONBLOCK;
3612 ret = ioctlsocket(sock, FIONBIO, &ioctlArg);
3632 if (!GetExitCodeProcess(child->
hProcess, &exitcode)) {
3635 err = GetLastError();
3636 if (err == ERROR_INVALID_PARAMETER)
3639 if (GetLastError() == ERROR_INVALID_HANDLE)
3647 if (exitcode != STILL_ACTIVE) {
3655 if (stat_loc) *stat_loc = exitcode << 8;
3679 if (!child->pid || child->pid < 0)
continue;
3681 events[count++] = child->hProcess;
3689 if (ret == WAIT_TIMEOUT)
return 0;
3690 if ((ret -= WAIT_OBJECT_0) == count) {
3720 #include <sys/timeb.h>
3726 unsigned LONG_LONG
lt;
3728 tmp.LowPart = ft->dwLowDateTime;
3729 tmp.HighPart = ft->dwHighDateTime;
3737 lt -= (LONG_LONG)((1970-1601)*365.2425) * 24 * 60 * 60 * 1000 * 1000;
3742 return tv->
tv_sec > 0 ? 0 : -1;
3750 GetSystemTimeAsFileTime(&ft);
3762 len = GetCurrentDirectory(0,
NULL);
3783 if (!GetCurrentDirectory(size, p)) {
3796 chown(
const char *path,
int owner,
int group)
3813 if (pid < 0 || pid == 0 && sig !=
SIGINT) {
3819 if ((
unsigned int)pid == GetCurrentProcessId() &&
3820 (sig != 0 && sig !=
SIGKILL)) {
3821 if ((ret =
raise(sig)) != 0) {
3832 OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE, (
DWORD)pid);
3833 if (hProc ==
NULL || hProc == INVALID_HANDLE_VALUE) {
3834 if (GetLastError() == ERROR_INVALID_PARAMETER) {
3850 DWORD ctrlEvent = CTRL_C_EVENT;
3854 ctrlEvent = CTRL_BREAK_EVENT;
3856 if (!GenerateConsoleCtrlEvent(ctrlEvent, (
DWORD)pid)) {
3857 if ((err = GetLastError()) == 0)
3874 hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
FALSE, (
DWORD)pid);
3876 if (hProc ==
NULL || hProc == INVALID_HANDLE_VALUE) {
3877 if (GetLastError() == ERROR_INVALID_PARAMETER) {
3887 if (!GetExitCodeProcess(hProc, &status)) {
3891 else if (status == STILL_ACTIVE) {
3892 if (!TerminateProcess(hProc, 0)) {
3918 wlink(
const WCHAR *from,
const WCHAR *to)
3920 typedef BOOL (WINAPI link_func)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
3921 static link_func *pCreateHardLinkW =
NULL;
3922 static int myerrno = 0;
3924 if (!pCreateHardLinkW && !myerrno) {
3926 if (!pCreateHardLinkW)
3929 if (!pCreateHardLinkW) {
3934 if (!pCreateHardLinkW(to, from,
NULL)) {
3955 ret =
wlink(wfrom, wto);
3962 link(
const char *from,
const char *to)
3974 ret =
wlink(wfrom, wto);
3983 return waitpid(-1, status, 0);
3992 if (len == 0)
return NULL;
3993 if (envarea) FreeEnvironmentStrings(envarea);
3994 envarea = GetEnvironmentStrings();
4000 for (env = envarea; *env; env +=
strlen(env) + 1)
4002 return env + len + 1;
4008 wrename(
const WCHAR *oldpath,
const WCHAR *newpath)
4014 oldatts = GetFileAttributesW(oldpath);
4015 newatts = GetFileAttributesW(newpath);
4017 if (oldatts == -1) {
4023 if (newatts != -1 && newatts & FILE_ATTRIBUTE_READONLY)
4024 SetFileAttributesW(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY);
4026 if (!MoveFileW(oldpath, newpath))
4030 switch (GetLastError()) {
4031 case ERROR_ALREADY_EXISTS:
4032 case ERROR_FILE_EXISTS:
4034 if (MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
4039 if (!DeleteFileW(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
4041 else if (MoveFileW(oldpath, newpath)) {
4053 SetFileAttributesW(newpath, oldatts);
4098 if (path[0] == L
'\\' && path[1] == L
'\\') {
4100 for (p = path + 2; *
p; p++) {
4105 for (p++; *
p; p++) {
4109 if (!p[0] || !p[1] || (p[1] == L
'.' && !p[2]))
4116 #define COPY_STAT(src, dest, size_cast) do { \
4117 (dest).st_dev = (src).st_dev; \
4118 (dest).st_ino = (src).st_ino; \
4119 (dest).st_mode = (src).st_mode; \
4120 (dest).st_nlink = (src).st_nlink; \
4121 (dest).st_uid = (src).st_uid; \
4122 (dest).st_gid = (src).st_gid; \
4123 (dest).st_rdev = (src).st_rdev; \
4124 (dest).st_size = size_cast(src).st_size; \
4125 (dest).st_atime = (src).st_atime; \
4126 (dest).st_mtime = (src).st_mtime; \
4127 (dest).st_ctime = (src).st_ctime; \
4136 BY_HANDLE_FILE_INFORMATION info;
4137 int ret =
fstat(fd, st);
4139 if (ret)
return ret;
4143 if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &info)) {
4145 if (!(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
4159 BY_HANDLE_FILE_INFORMATION info;
4161 int ret =
fstat(fd, &tmp);
4163 if (ret)
return ret;
4168 if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &info)) {
4170 if (!(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
4174 st->st_size = ((__int64)info.nFileSizeHigh << 32) | info.nFileSizeLow;
4198 if (attr & FILE_ATTRIBUTE_READONLY) {
4202 mode |= S_IREAD | S_IWRITE |
S_IWUSR;
4205 if (attr & FILE_ATTRIBUTE_DIRECTORY) {
4206 mode |= S_IFDIR | S_IEXEC;
4212 if (path && (mode & S_IFREG)) {
4213 const WCHAR *end = path + lstrlenW(path);
4214 while (path < end) {
4215 end = CharPrevW(path, end);
4217 if ((_wcsicmp(end, L
".bat") == 0) ||
4218 (_wcsicmp(end, L
".cmd") == 0) ||
4219 (_wcsicmp(end, L
".com") == 0) ||
4220 (_wcsicmp(end, L
".exe") == 0)) {
4228 mode |= (mode & 0700) >> 3;
4229 mode |= (mode & 0700) >> 6;
4237 WIN32_FIND_DATAW fd;
4242 if (wcsstr(path, L
"...") ==
NULL)
4246 if (fh == INVALID_HANDLE_VALUE)
4256 WIN32_FIND_DATAW wfd;
4257 WIN32_FILE_ATTRIBUTE_DATA wfa;
4259 memset(st, 0,
sizeof(*st));
4262 if (wcspbrk(path, L
"?*")) {
4266 if (GetFileAttributesExW(path, GetFileExInfoStandard, (
void*)&wfa)) {
4267 if (wfa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
4272 st->st_size = ((__int64)wfa.nFileSizeHigh << 32) | wfa.nFileSizeLow;
4281 int e = GetLastError();
4283 if ((e == ERROR_FILE_NOT_FOUND) || (e == ERROR_INVALID_NAME)
4284 || (e == ERROR_PATH_NOT_FOUND || (e == ERROR_BAD_NETPATH))) {
4290 h = FindFirstFileW(path, &wfd);
4291 if (h != INVALID_HANDLE_VALUE) {
4297 st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
4305 st->st_dev = st->st_rdev = (iswalpha(path[0]) && path[1] == L
':') ?
4306 towupper(path[0]) - L
'A' : _getdrive() - 1;
4313 win95_stat(
const WCHAR *path,
struct stati64 *st)
4315 int ret = _wstati64(path, st);
4316 if (ret)
return ret;
4317 if (st->st_mode & S_IFDIR) {
4323 #define win95_stat(path, st) -1
4340 WCHAR *buf1, *s, *end;
4349 size = lstrlenW(path) + 2;
4351 for (p = path, s = buf1; *
p; p++, s++) {
4359 if (!len || L
'\"' == *(--s)) {
4363 end = buf1 + len - 1;
4368 else if (*end != L
'\\')
4369 lstrcatW(buf1, L
"\\");
4371 else if (*end == L
'\\' || (buf1 + 1 == end && *end == L
':'))
4372 lstrcatW(buf1, L
".");
4413 struct stati64 stat;
4417 if ((stat.st_mode & mode) != mode) {
4427 struct stati64 stat;
4431 if ((stat.st_mode & mode) != mode) {
4441 long upos, lpos, usize, lsize, uend, lend;
4446 if (((lpos = SetFilePointer(h, 0, (upos = 0, &upos),
SEEK_CUR)) == -1L &&
4447 (e = GetLastError())) ||
4448 ((lend = GetFileSize(h, (
DWORD *)&uend)) == -1L && (e = GetLastError()))) {
4452 end = ((
off_t)uend << 32) | (
unsigned long)lend;
4453 usize = (
long)(size >> 32);
4455 if (SetFilePointer(h, lsize, &usize,
SEEK_SET) == (
DWORD)-1L &&
4456 (e = GetLastError())) {
4459 else if (!SetEndOfFile(h)) {
4465 SetFilePointer(h, lpos, &upos,
SEEK_SET);
4476 int fd = open(path, O_WRONLY), e = 0;
4477 if (fd == -1)
return -1;
4478 ret = chsize(fd, (
unsigned long)length);
4479 if (ret == -1) e =
errno;
4481 if (ret == -1)
errno = e;
4485 h = CreateFile(path, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
4486 if (h == INVALID_HANDLE_VALUE) {
4502 return chsize(fd, (
unsigned long)length);
4505 h = (HANDLE)_get_osfhandle(fd);
4506 if (h == (HANDLE)-1)
return -1;
4512 _filelengthi64(
int fd)
4517 l = GetFileSize((HANDLE)_get_osfhandle(fd), &u);
4518 if (l == (
DWORD)-1L && (e = GetLastError())) {
4522 return ((
off_t)u << 32) | l;
4526 _lseeki64(
int fd,
off_t offset,
int whence)
4530 HANDLE h = (HANDLE)_get_osfhandle(fd);
4536 u = (
long)(offset >> 32);
4537 if ((l = SetFilePointer(h, (
long)offset, &u, whence)) == -1L &&
4538 (e = GetLastError())) {
4542 return ((
off_t)u << 32) | l;
4552 if (fgetpos(stream, (fpos_t *)&pos))
4557 if ((pos = _filelengthi64(
fileno(stream))) == (
off_t)-1)
4565 return fsetpos(stream, (fpos_t *)&pos);
4572 if (fgetpos(stream, (fpos_t *)&pos))
return (
off_t)-1;
4579 __int64 qw = ft->dwHighDateTime;
4581 qw |= ft->dwLowDateTime;
4589 FILETIME create, exit, kernel, user;
4591 if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
4606 #define yield_once() Sleep(0)
4607 #define yield_until(condition) do yield_once(); while (!(condition))
4616 #if defined __BORLANDC__
4619 read(
int fd,
void *
buf,
size_t size)
4621 int ret = _read(fd, buf, size);
4622 if ((ret < 0) && (errno == EPIPE)) {
4637 c = (
unsigned char)*stream->FILE_READPTR++;
4640 c = _filbuf(stream);
4641 #if defined __BORLANDC__
4642 if ((c ==
EOF) && (
errno == EPIPE)) {
4656 c = (
unsigned char)(*stream->FILE_READPTR++ = (
char)c);
4659 c = _flsbuf(c, stream);
4693 BOOL interrupted =
FALSE;
4714 if (TerminateThread(thr, intrval)) {
4719 GetExitCodeThread(thr, &val);
4724 MEMORY_BASIC_INFORMATION m;
4726 memset(&m, 0,
sizeof(m));
4727 if (!VirtualQuery(arg.
stackaddr, &m,
sizeof(m))) {
4728 Debug(fprintf(stderr,
"couldn't get stack base:%p:%d\n",
4731 else if (!VirtualFree(m.AllocationBase, 0, MEM_RELEASE)) {
4732 Debug(fprintf(stderr,
"couldn't release stack:%p:%d\n",
4733 m.AllocationBase, GetLastError()));
4744 rb_fatal(
"failed to launch waiter thread:%ld", GetLastError());
4754 char **myenvtop, **myenv;
4766 envtop = GetEnvironmentStrings();
4767 for (env = envtop, num = 0; *env; env +=
strlen(env) + 1)
4768 if (*env !=
'=') num++;
4770 myenvtop = (
char **)
malloc(
sizeof(
char *) * (num + 1));
4771 for (env = envtop, myenv = myenvtop; *env; env +=
strlen(env) + 1) {
4773 if (!(*myenv =
strdup(env))) {
4780 FreeEnvironmentStrings(envtop);
4790 while (*t)
free(*t++);
4799 pid = GetCurrentProcessId();
4810 typedef long (WINAPI query_func)(HANDLE, int,
void *,
ULONG, ULONG *);
4811 static query_func *pNtQueryInformationProcess =
NULL;
4815 if (!pNtQueryInformationProcess)
4816 pNtQueryInformationProcess = (query_func *)
get_proc_address(
"ntdll.dll",
"NtQueryInformationProcess",
NULL);
4817 if (pNtQueryInformationProcess) {
4820 void* PebBaseAddress;
4827 long ret = pNtQueryInformationProcess(GetCurrentProcess(), 0, &pbi,
sizeof(pbi), &len);
4829 ppid = pbi.ParentProcessId;
4845 va_start(arg, oflag);
4846 pmode = va_arg(arg,
int);
4864 va_start(arg, oflag);
4865 pmode = va_arg(arg,
int);
4868 if ((oflag & O_TEXT) || !(oflag &
O_BINARY))
4869 return _open(file, oflag, pmode);
4885 DWORD attr = FILE_ATTRIBUTE_NORMAL;
4886 SECURITY_ATTRIBUTES sec;
4889 if ((oflag & O_TEXT) || !(oflag &
O_BINARY)) {
4892 va_start(arg, oflag);
4893 pmode = va_arg(arg,
int);
4895 return _wopen(file, oflag, pmode);
4898 sec.nLength =
sizeof(sec);
4899 sec.lpSecurityDescriptor =
NULL;
4900 if (oflag & O_NOINHERIT) {
4901 sec.bInheritHandle =
FALSE;
4905 sec.bInheritHandle =
TRUE;
4907 oflag &= ~O_NOINHERIT;
4910 oflag &= ~(O_BINARY | O_TEXT);
4912 switch (oflag & (O_RDWR | O_RDONLY | O_WRONLY)) {
4914 access = GENERIC_READ | GENERIC_WRITE;
4917 access = GENERIC_READ;
4920 access = GENERIC_WRITE;
4926 oflag &= ~(O_RDWR | O_RDONLY | O_WRONLY);
4928 switch (oflag & (O_CREAT | O_EXCL | O_TRUNC)) {
4930 create = OPEN_ALWAYS;
4934 create = OPEN_EXISTING;
4936 case O_CREAT | O_EXCL:
4937 case O_CREAT | O_EXCL | O_TRUNC:
4938 create = CREATE_NEW;
4941 case O_TRUNC | O_EXCL:
4942 create = TRUNCATE_EXISTING;
4944 case O_CREAT | O_TRUNC:
4945 create = CREATE_ALWAYS;
4951 if (oflag & O_CREAT) {
4954 va_start(arg, oflag);
4955 pmode = va_arg(arg,
int);
4958 if (!(pmode & S_IWRITE))
4959 attr = FILE_ATTRIBUTE_READONLY;
4961 oflag &= ~(O_CREAT | O_EXCL | O_TRUNC);
4963 if (oflag & O_TEMPORARY) {
4964 attr |= FILE_FLAG_DELETE_ON_CLOSE;
4967 oflag &= ~O_TEMPORARY;
4969 if (oflag & _O_SHORT_LIVED)
4970 attr |= FILE_ATTRIBUTE_TEMPORARY;
4971 oflag &= ~_O_SHORT_LIVED;
4973 switch (oflag & (O_SEQUENTIAL | O_RANDOM)) {
4977 attr |= FILE_FLAG_SEQUENTIAL_SCAN;
4980 attr |= FILE_FLAG_RANDOM_ACCESS;
4986 oflag &= ~(O_SEQUENTIAL | O_RANDOM);
4988 if (oflag & ~O_APPEND) {
4995 h = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
4996 fd = _open_osfhandle((
intptr_t)h, 0);
5008 h = CreateFileW(file, access, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec,
5009 create, attr,
NULL);
5010 if (h == INVALID_HANDLE_VALUE) {
5017 switch (GetFileType(h)) {
5018 case FILE_TYPE_CHAR:
5021 case FILE_TYPE_PIPE:
5024 case FILE_TYPE_UNKNOWN:
5031 if (!(flags & (
FDEV |
FPIPE)) && (oflag & O_APPEND))
5050 int save_errno =
errno;
5052 if (fflush(fp))
return -1;
5060 if (closesocket(sock) == SOCKET_ERROR) {
5070 static DWORD serial = 0;
5071 char name[] =
"\\\\.\\pipe\\ruby0000000000000000-0000000000000000";
5073 SECURITY_ATTRIBUTES sec;
5074 HANDLE hRead, hWrite, h;
5075 int fdRead, fdWrite;
5080 return _pipe(fds, 65536L, _O_NOINHERIT);
5085 sec.nLength =
sizeof(sec);
5086 sec.lpSecurityDescriptor =
NULL;
5087 sec.bInheritHandle =
FALSE;
5090 hRead = CreateNamedPipe(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
5091 0, 2, 65536, 65536, 0, &sec);
5093 if (hRead == INVALID_HANDLE_VALUE) {
5095 if (err == ERROR_PIPE_BUSY)
5103 hWrite = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, &sec,
5104 OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
NULL);
5106 if (hWrite == INVALID_HANDLE_VALUE) {
5114 h = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
5115 fdRead = _open_osfhandle((
intptr_t)h, 0);
5119 CloseHandle(hWrite);
5134 h = CreateFile(
"NUL", 0, 0,
NULL, OPEN_ALWAYS, 0,
NULL);
5135 fdWrite = _open_osfhandle((
intptr_t)h, 0);
5137 if (fdWrite == -1) {
5139 CloseHandle(hWrite);
5163 int save_errno =
errno;
5176 if (closesocket(sock) == SOCKET_ERROR) {
5193 OVERLAPPED ol, *pol =
NULL;
5195 BOOL islineinput =
FALSE;
5202 if (_get_osfhandle(fd) == -1) {
5207 return _read(fd, buf, size);
5222 GetConsoleMode((HANDLE)
_osfhnd(fd),&mode);
5223 islineinput = (mode & ENABLE_LINE_INPUT) != 0;
5241 memset(&ol, 0,
sizeof(ol));
5244 DWORD low = SetFilePointer((HANDLE)
_osfhnd(fd), 0, &high,
5246 #ifndef INVALID_SET_FILE_POINTER
5247 #define INVALID_SET_FILE_POINTER ((DWORD)-1)
5255 ol.OffsetHigh = high;
5267 if (!ReadFile((HANDLE)
_osfhnd(fd), buf, len, &read, pol)) {
5268 err = GetLastError();
5269 if (err != ERROR_IO_PENDING) {
5270 if (pol) CloseHandle(ol.hEvent);
5271 if (err == ERROR_ACCESS_DENIED)
5273 else if (err == ERROR_BROKEN_PIPE || err == ERROR_HANDLE_EOF) {
5286 if (wait != WAIT_OBJECT_0) {
5287 if (wait == WAIT_OBJECT_0 + 1)
5291 CloseHandle(ol.hEvent);
5297 if (!GetOverlappedResult((HANDLE)
_osfhnd(fd), &ol, &read,
TRUE) &&
5298 (err = GetLastError()) != ERROR_HANDLE_EOF) {
5300 if (err != ERROR_BROKEN_PIPE) {
5304 CloseHandle(ol.hEvent);
5313 CloseHandle(ol.hEvent);
5316 LONG high = ol.OffsetHigh;
5317 DWORD low = ol.Offset + read;
5318 if (low < ol.Offset)
5320 SetFilePointer((HANDLE)
_osfhnd(fd), low, &high, FILE_BEGIN);
5326 buf = (
char *)buf + read;
5327 if (!(isconsole && len == 1 && (!islineinput || *((
char *)buf - 1) ==
'\n')) && size > 0)
5349 OVERLAPPED ol, *pol =
NULL;
5355 if (_get_osfhandle(fd) == -1) {
5361 return _write(fd, buf, size);
5379 memset(&ol, 0,
sizeof(ol));
5383 DWORD low = SetFilePointer((HANDLE)
_osfhnd(fd), 0, &high, method);
5384 #ifndef INVALID_SET_FILE_POINTER
5385 #define INVALID_SET_FILE_POINTER ((DWORD)-1)
5393 ol.OffsetHigh = high;
5405 if (!WriteFile((HANDLE)
_osfhnd(fd), buf, len, &written, pol)) {
5406 err = GetLastError();
5407 if (err != ERROR_IO_PENDING) {
5408 if (pol) CloseHandle(ol.hEvent);
5409 if (err == ERROR_ACCESS_DENIED)
5420 if (wait != WAIT_OBJECT_0) {
5421 if (wait == WAIT_OBJECT_0 + 1)
5425 CloseHandle(ol.hEvent);
5431 if (!GetOverlappedResult((HANDLE)
_osfhnd(fd), &ol, &written,
5434 CloseHandle(ol.hEvent);
5443 CloseHandle(ol.hEvent);
5446 LONG high = ol.OffsetHigh;
5447 DWORD low = ol.Offset + written;
5448 if (low < ol.Offset)
5450 SetFilePointer((HANDLE)
_osfhnd(fd), low, &high, FILE_BEGIN);
5455 if (written == len) {
5456 buf = (
const char *)buf + len;
5471 DWORD dwMode, reslen;
5474 if (disable)
return -1L;
5476 if (!GetConsoleMode(handle, &dwMode) ||
5484 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
5488 return (
long)reslen;
5496 tmp.QuadPart = ((LONG_LONG)time + (LONG_LONG)((1970-1601)*365.2425) * 24 * 60 * 60) * 10 * 1000 * 1000;
5497 ft->dwLowDateTime = tmp.LowPart;
5498 ft->dwHighDateTime = tmp.HighPart;
5506 FILETIME atime, mtime;
5507 struct stati64 stat;
5523 GetSystemTimeAsFileTime(&atime);
5528 const DWORD attr = GetFileAttributesW(path);
5529 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY))
5530 SetFileAttributesW(path, attr & ~FILE_ATTRIBUTE_READONLY);
5531 hFile = CreateFileW(path, GENERIC_WRITE, 0, 0, OPEN_EXISTING,
5532 IsWin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS, 0);
5533 if (hFile == INVALID_HANDLE_VALUE) {
5538 if (!SetFileTime(hFile,
NULL, &atime, &mtime)) {
5544 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY))
5545 SetFileAttributesW(path, attr);
5559 ret =
wutime(wpath, times);
5572 ret =
wutime(wpath, times);
5585 ret = _wchdir(wpath);
5596 if (CreateDirectoryW(wpath,
NULL) ==
FALSE) {
5600 if (_wchmod(wpath, mode) == -1) {
5601 RemoveDirectoryW(wpath);
5617 ret =
wmkdir(wpath, mode);
5630 ret =
wmkdir(wpath, mode);
5640 const DWORD attr = GetFileAttributesW(wpath);
5641 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
5642 SetFileAttributesW(wpath, attr & ~FILE_ATTRIBUTE_READONLY);
5644 if (RemoveDirectoryW(wpath) ==
FALSE) {
5647 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
5648 SetFileAttributesW(wpath, attr);
5686 const DWORD attr = GetFileAttributesW(path);
5687 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
5688 SetFileAttributesW(path, attr & ~FILE_ATTRIBUTE_READONLY);
5690 if (!DeleteFileW(path)) {
5693 if (attr != (
DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
5694 SetFileAttributesW(path, attr);
5735 ret = _wchmod(wpath, mode);
5740 #if !defined(__BORLANDC__)
5747 if (_get_osfhandle(fd) == -1) {
5750 if (!GetConsoleMode((HANDLE)
_osfhnd(fd), &mode)) {
5764 too_many_files(
void)
5767 for (f = _streams; f < _streams + _nfile; f++) {
5768 if (f->fd < 0)
return 0;
5775 rb_w32_fopen(
const char *path,
const char *mode)
5777 FILE *f = (
errno = 0, fopen(path, mode));
5778 if (f == NULL && errno == 0) {
5779 if (too_many_files())
5786 rb_w32_fdopen(
int handle,
const char *
type)
5788 FILE *f = (
errno = 0, _fdopen(handle, (
char *)type));
5789 if (f == NULL && errno == 0) {
5792 else if (too_many_files())
5799 rb_w32_fsopen(
const char *path,
const char *mode,
int shflags)
5801 FILE *f = (
errno = 0, _fsopen(path, mode, shflags));
5802 if (f == NULL && errno == 0) {
5803 if (too_many_files())
5810 #if defined(_MSC_VER) && RT_VER <= 60
5811 extern long _ftol(
double);
5818 _ftol2_sse(
double d)
5828 int *ip = (
int *)(&x + 1) - 1;
5836 typedef char *(WSAAPI inet_ntop_t)(
int,
void *,
char *,
size_t);
5837 inet_ntop_t *pInetNtop;
5840 return pInetNtop(af,addr,numaddr,numaddr_len);
5843 memcpy(&in.s_addr, addr,
sizeof(in.s_addr));
5844 snprintf(numaddr, numaddr_len,
"%s", inet_ntoa(in));