char *tmp_stderr2;
tmp_stderr2 = format("%s.2", tmp_stderr);
- if (x_rename(tmp_stderr, tmp_stderr2)) {
+#ifdef _WIN32
+ // on Windows file descriptor should be closed before rename
+ int prev_stderr_fd = tmp_stderr_fd;
+ close(tmp_stderr_fd);
+#endif
+ int rename_result = x_rename(tmp_stderr, tmp_stderr2);
+#ifdef _WIN32
+ tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+ assert(prev_stderr_fd == tmp_stderr_fd);
+#endif
+ if (rename_result) {
+ const char* err_str = strerror(errno);
cc_log("Failed to rename %s to %s: %s", tmp_stderr, tmp_stderr2,
- strerror(errno));
+ err_str);
failed();
}
fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY);
time_of_compilation = time(NULL);
+ int path_stdout_fd = -1;
+
if (direct_i_file) {
/* We are compiling a .i or .ii file - that means we can skip the cpp stage
* and directly form the correct i_tmpfile. */
status = 0;
} else {
/* Run cpp on the input file to obtain the .i. */
- int path_stdout_fd;
path_stdout = format("%s/%s.stdout", temp_dir(), input_base);
path_stdout_fd = create_tmp_fd(&path_stdout);
add_pending_tmp_file(path_stdout);
/* i_tmpfile needs the proper cpp_extension for the compiler to do its
* thing correctly. */
i_tmpfile = format("%s.%s", path_stdout, conf->cpp_extension);
+#ifdef _WIN32
+ // on Windows rename only if file descriptor closed
+ if (path_stdout_fd != -1)
+ {
+ close(path_stdout_fd);
+ }
+#endif
x_rename(path_stdout, i_tmpfile);
+#ifdef _WIN32
+ if (path_stdout_fd != -1)
+ {
+ int tmp_fd = create_tmp_fd(&path_stdout);
+ assert(tmp_fd == path_stdout_fd);
+ }
+#endif
add_pending_tmp_file(i_tmpfile);
}
hash_delimiter(hash, "ext");
hash_string(hash, conf->cpp_extension);
+#ifdef _WIN32
+ const char* ext = strchr(args->argv[0], '.');
+ char full_path_win_ext[MAX_PATH] = {0};
+ strncat(full_path_win_ext, args->argv[0], MAX_PATH);
+ if (!ext
+ || (strcmp(".exe", ext) != 0
+ && strcmp(".bat", ext) != 0
+ && strcmp(".EXE", ext) != 0
+ && strcmp(".BAT", ext) != 0
+ )
+ )
+ {
+ strncat(full_path_win_ext, ".exe", MAX_PATH);
+ }
+ if (stat(full_path_win_ext, &st) != 0) {
+ cc_log("Couldn't stat compiler %s: %s", args->argv[0], strerror(errno));
+ stats_update(STATS_COMPILER);
+ failed();
+ }
+#else
if (stat(args->argv[0], &st) != 0) {
cc_log("Couldn't stat compiler %s: %s", args->argv[0], strerror(errno));
stats_update(STATS_COMPILER);
failed();
}
+#endif
/*
* Hash information about the compiler.
char *win32argvtos(char *prefix, char **argv);
char *win32getshell(char *path);
int win32execute(char *path, char **argv, int doreturn,
- const char *path_stdout, const char *path_stderr);
+ int fd_stdout, int fd_stderr);
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
# endif
# define mkdir(a,b) mkdir(a)
# define link(src,dst) (CreateHardLink(dst,src,NULL) ? 0 : -1)
# define lstat(a,b) stat(a,b)
-# define execv(a,b) win32execute(a,b,0,NULL,NULL)
-#error TODO: Adapt win32execute to new execute API
+# define execv(a,b) win32execute(a,b,0,0,0)
# define execute(a,b,c) win32execute(*(a),a,1,b,c)
# define PATH_DELIM ";"
# define F_RDLCK 0
int
win32execute(char *path, char **argv, int doreturn,
- const char *path_stdout, const char *path_stderr)
+ int fd_stdout, int fd_stderr)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
path = sh;
si.cb = sizeof(STARTUPINFO);
- if (path_stdout) {
- SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
- si.hStdOutput = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa,
- CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY |
- FILE_FLAG_SEQUENTIAL_SCAN, NULL);
- si.hStdError = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa,
- CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY |
- FILE_FLAG_SEQUENTIAL_SCAN, NULL);
- si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- si.dwFlags = STARTF_USESTDHANDLES;
- if (si.hStdOutput == INVALID_HANDLE_VALUE ||
- si.hStdError == INVALID_HANDLE_VALUE)
+ if (fd_stdout != -1) {
+ si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout);
+ si.hStdError = (HANDLE)_get_osfhandle(fd_stderr);
+
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ if (si.hStdOutput == INVALID_HANDLE_VALUE
+ || si.hStdError == INVALID_HANDLE_VALUE) {
return -1;
+ }
}
args = win32argvtos(sh, argv);
- ret = CreateProcess(path, args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi);
- free(args);
- if (path_stdout) {
- CloseHandle(si.hStdOutput);
- CloseHandle(si.hStdError);
+
+ const char* ext = strchr(path, '.');
+ char full_path_win_ext[MAX_PATH] = { 0 };
+ strncat(full_path_win_ext, path, MAX_PATH);
+ if (!ext
+ || (strcmp(".exe", ext) != 0 && strcmp(".bat", ext) != 0
+ && strcmp(".EXE", ext) != 0 && strcmp(".BAT", ext) != 0)) {
+ strncat(full_path_win_ext, ".exe", MAX_PATH);
}
- if (ret == 0)
+
+ ret = CreateProcess(full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL,
+ &si, &pi);
+ free(args);
+ if (ret == 0) {
+ LPVOID lpMsgBuf;
+ LPVOID lpDisplayBuf;
+ DWORD dw = GetLastError();
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,
+ 0, NULL);
+
+ lpDisplayBuf =
+ (LPVOID) LocalAlloc(LMEM_ZEROINIT,
+ (lstrlen((LPCTSTR) lpMsgBuf)
+ + lstrlen((LPCTSTR) __FILE__) + 200)
+ * sizeof(TCHAR));
+ _snprintf((LPTSTR) lpDisplayBuf,
+ LocalSize(lpDisplayBuf) / sizeof(TCHAR),
+ TEXT("%s failed with error %d: %s"), __FILE__, dw, lpMsgBuf);
+
+ cc_log("can't execute %s\nOS returned error: %s\n",
+ full_path_win_ext, (char*)lpDisplayBuf);
+
+ LocalFree(lpMsgBuf);
+ LocalFree(lpDisplayBuf);
+
return -1;
+ }
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &exitcode);
CloseHandle(pi.hProcess);
const char *
get_hostname(void)
{
- static char hostname[200] = "";
+ static char hostname[260] = "";
if (!hostname[0]) {
strcpy(hostname, "unknown");
#if HAVE_GETHOSTNAME
gethostname(hostname, sizeof(hostname)-1);
+#elif defined(_WIN32)
+
+ const char* computer_name = getenv("COMPUTERNAME");
+ if (computer_name)
+ {
+ strncpy(hostname, computer_name, sizeof(hostname) -1);
+ return hostname;
+ }
+
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD(2, 2);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
+ /* Tell the user that we could not find a usable */
+ /* Winsock DLL. */
+ cc_log("WSAStartup failed with error: %d\n", err);
+ return hostname;
+ }
+
+ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
+ /* Tell the user that we could not find a usable */
+ /* WinSock DLL. */
+ cc_log("Could not find a usable version of Winsock.dll\n");
+ WSACleanup();
+ return hostname;
+ }
+
+ int result = gethostname(hostname, sizeof(hostname)-1);
+ if (result != 0)
+ {
+ int last_error = WSAGetLastError();
+ LPVOID lpMsgBuf;
+ LPVOID lpDisplayBuf;
+ DWORD dw = last_error;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf, 0, NULL);
+
+ lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT,
+ (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) __FILE__)
+ + 200) * sizeof(TCHAR));
+ _snprintf((LPTSTR) lpDisplayBuf,
+ LocalSize(lpDisplayBuf) / sizeof(TCHAR),
+ TEXT("%s failed with error %d: %s"), __FILE__, dw,
+ lpMsgBuf);
+
+ cc_log("can't get hostname OS returned error: %s\n",
+ (char*) lpDisplayBuf);
+
+ LocalFree(lpMsgBuf);
+ LocalFree(lpDisplayBuf);
+ }
+ WSACleanup();
#endif
hostname[sizeof(hostname)-1] = 0;
}
path_handle = CreateFile(
path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
- GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED);
- CloseHandle(path_handle);
- p = ret+4;// strip the \\?\ from the file name
+ if(INVALID_HANDLE_VALUE != path_handle)
+ {
+ GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED);
+ CloseHandle(path_handle);
+ p = ret+4;// strip the \\?\ from the file name
+ } else
+ {
+ strncpy(ret, path, maxlen);
+ p = ret;
+ }
#else
/* yes, there are such systems. This replacement relies on
the fact that when we call x_realpath we only care about symlinks */
/*
* Rename oldpath to newpath (deleting newpath).
*/
+
int
x_rename(const char *oldpath, const char *newpath)
{
#ifdef _WIN32
/* Windows' rename() refuses to overwrite an existing file. */
unlink(newpath); /* not x_unlink, as x_unlink calls x_rename */
-#endif
+ /*If the function succeeds, the return value is nonzero.*/
+ if (MoveFileA(oldpath, newpath) == 0)
+ {
+ LPVOID lpMsgBuf;
+ LPVOID lpDisplayBuf;
+ DWORD dw = GetLastError();
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,
+ 0, NULL);
+
+ lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT,
+ (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) __FILE__) + 40)
+ * sizeof(TCHAR));
+ _snprintf((LPTSTR) lpDisplayBuf,
+ LocalSize(lpDisplayBuf) / sizeof(TCHAR),
+ TEXT("%s failed with error %d: %s"), __FILE__, dw, lpMsgBuf);
+
+ cc_log("can't rename file %s to %s OS returned error: %s\n",
+ oldpath, newpath, (char*) lpDisplayBuf);
+
+ LocalFree(lpMsgBuf);
+ LocalFree(lpDisplayBuf);
+ return -1;
+ } else
+ {
+ return 0;
+ }
+#else
return rename(oldpath, newpath);
+#endif
}
/*