authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-17 15:56:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-17 19:53:30-07:00
loga7b6fa5bee58f40aafa64665b73ff3efc68f7930
tree89bd22ea66360e6b89700f533296350379a24e47
parent06398a22d0905e7e45ee7bdf4755aeee3b3fc1b0

os: implement windows os layer


4 files changed, 218 insertions(+), 16 deletions(-)

src/link.cpp+5-1
......@@ -802,7 +802,11 @@ void codegen_link(CodeGen *g, const char *out_file) {
802802 int return_code;
803803 Buf ld_stderr = BUF_INIT;
804804 Buf ld_stdout = BUF_INIT;
805 os_exec_process(buf_ptr(g->linker_path), lj.args, &return_code, &ld_stderr, &ld_stdout);
805 int err = os_exec_process(buf_ptr(g->linker_path), lj.args, &return_code, &ld_stderr, &ld_stdout);
806 if (err) {
807 fprintf(stderr, "linker not found: '%s'\n", buf_ptr(g->linker_path));
808 exit(1);
809 }
806810
807811 if (return_code != 0) {
808812 fprintf(stderr, "linker failed with return code %d\n", return_code);
src/main.cpp+2
......@@ -98,6 +98,8 @@ enum Cmd {
9898};
9999
100100int main(int argc, char **argv) {
101 os_init();
102
101103 char *arg0 = argv[0];
102104 Cmd cmd = CmdInvalid;
103105 const char *in_file = nullptr;
src/os.cpp+209-14
......@@ -24,10 +24,6 @@
2424#define WIN32_LEAN_AND_MEAN
2525#endif
2626
27#if !defined(UNICODE)
28#define UNICODE
29#endif
30
3127#include <windows.h>
3228#include <io.h>
3329#else
......@@ -44,6 +40,11 @@
4440
4541#include <stdlib.h>
4642#include <errno.h>
43#include <time.h>
44
45// these implementations are lazy. But who cares, we'll make a robust
46// implementation in the zig standard library and then this code all gets
47// deleted when we self-host. it works for now.
4748
4849
4950#if defined(ZIG_OS_POSIX)
......@@ -70,7 +71,13 @@ static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args,
7071
7172#if defined(ZIG_OS_WINDOWS)
7273static void os_spawn_process_windows(const char *exe, ZigList<const char *> &args, int *return_code) {
73 zig_panic("TODO os_spawn_process_windows");
74 Buf stderr_buf = BUF_INIT;
75 Buf stdout_buf = BUF_INIT;
76
77 // TODO this is supposed to inherit stdout/stderr instead of capturing it
78 os_exec_process(exe, args, return_code, &stderr_buf, &stdout_buf);
79 fwrite(buf_ptr(&stderr_buf), 1, buf_len(&stderr_buf), stderr);
80 fwrite(buf_ptr(&stdout_buf), 1, buf_len(&stdout_buf), stdout);
7481}
7582#endif
7683
......@@ -111,7 +118,12 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
111118
112119int os_path_real(Buf *rel_path, Buf *out_abs_path) {
113120#if defined(ZIG_OS_WINDOWS)
114 zig_panic("TODO os_path_real for windows");
121 buf_resize(out_abs_path, 4096);
122 if (_fullpath(buf_ptr(out_abs_path), buf_ptr(rel_path), buf_len(out_abs_path)) == nullptr) {
123 zig_panic("_fullpath failed");
124 }
125 buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path)));
126 return ErrorNone;
115127#elif defined(ZIG_OS_POSIX)
116128 buf_resize(out_abs_path, PATH_MAX + 1);
117129 char *result = realpath(buf_ptr(rel_path), buf_ptr(out_abs_path));
......@@ -157,7 +169,7 @@ int os_fetch_file(FILE *f, Buf *out_buf) {
157169
158170
159171#if defined(ZIG_OS_POSIX)
160static void os_exec_process_posix(const char *exe, ZigList<const char *> &args,
172static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,
161173 int *return_code, Buf *out_stderr, Buf *out_stdout)
162174{
163175 int stdin_pipe[2];
......@@ -193,7 +205,11 @@ static void os_exec_process_posix(const char *exe, ZigList<const char *> &args,
193205 argv[i + 1] = args.at(i);
194206 }
195207 execvp(exe, const_cast<char * const *>(argv));
196 zig_panic("execvp failed: %s", strerror(errno));
208 if (errno == ENOENT) {
209 return ErrorFileNotFound;
210 } else {
211 zig_panic("execvp failed: %s", strerror(errno));
212 }
197213 } else {
198214 // parent
199215 close(stdin_pipe[0]);
......@@ -205,19 +221,158 @@ static void os_exec_process_posix(const char *exe, ZigList<const char *> &args,
205221 os_fetch_file(fdopen(stdout_pipe[0], "rb"), out_stdout);
206222 os_fetch_file(fdopen(stderr_pipe[0], "rb"), out_stderr);
207223
224 return 0;
208225 }
209226}
210227#endif
211228
212229#if defined(ZIG_OS_WINDOWS)
213static void os_exec_process_windows(const char *exe, ZigList<const char *> &args,
230
231/*
232static void win32_panic(const char *str) {
233 DWORD err = GetLastError();
234 LPSTR messageBuffer = nullptr;
235 FormatMessageA(
236 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
237 NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
238 zig_panic(str, messageBuffer);
239 LocalFree(messageBuffer);
240}
241*/
242
243static int os_exec_process_windows(const char *exe, ZigList<const char *> &args,
214244 int *return_code, Buf *out_stderr, Buf *out_stdout)
215245{
216 zig_panic("TODO implement os_exec_process_windows");
246 Buf command_line = BUF_INIT;
247 buf_resize(&command_line, 0);
248
249 buf_append_char(&command_line, '\"');
250 buf_append_str(&command_line, exe);
251 buf_append_char(&command_line, '\"');
252
253 for (int arg_i = 0; arg_i < args.length; arg_i += 1) {
254 buf_append_str(&command_line, " \"");
255 const char *arg = args.at(arg_i);
256 int arg_len = strlen(arg);
257 for (int c_i = 0; c_i < arg_len; c_i += 1) {
258 if (arg[c_i] == '\"') {
259 zig_panic("TODO");
260 }
261 buf_append_char(&command_line, arg[c_i]);
262 }
263 buf_append_char(&command_line, '\"');
264 }
265
266
267 HANDLE g_hChildStd_IN_Rd = NULL;
268 HANDLE g_hChildStd_IN_Wr = NULL;
269 HANDLE g_hChildStd_OUT_Rd = NULL;
270 HANDLE g_hChildStd_OUT_Wr = NULL;
271 HANDLE g_hChildStd_ERR_Rd = NULL;
272 HANDLE g_hChildStd_ERR_Wr = NULL;
273
274 SECURITY_ATTRIBUTES saAttr;
275 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
276 saAttr.bInheritHandle = TRUE;
277 saAttr.lpSecurityDescriptor = NULL;
278
279 if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) {
280 zig_panic("StdoutRd CreatePipe");
281 }
282
283 if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) {
284 zig_panic("Stdout SetHandleInformation");
285 }
286
287 if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) {
288 zig_panic("stderr CreatePipe");
289 }
290
291 if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) {
292 zig_panic("stderr SetHandleInformation");
293 }
294
295 if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) {
296 zig_panic("Stdin CreatePipe");
297 }
298
299 if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) {
300 zig_panic("Stdin SetHandleInformation");
301 }
302
303
304 PROCESS_INFORMATION piProcInfo = {0};
305 STARTUPINFO siStartInfo = {0};
306 siStartInfo.cb = sizeof(STARTUPINFO);
307 siStartInfo.hStdError = g_hChildStd_ERR_Wr;
308 siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
309 siStartInfo.hStdInput = g_hChildStd_IN_Rd;
310 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
311
312 BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
313 &siStartInfo, &piProcInfo);
314
315 if (!success) {
316 if (GetLastError() == ERROR_FILE_NOT_FOUND) {
317 CloseHandle(piProcInfo.hProcess);
318 CloseHandle(piProcInfo.hThread);
319 return ErrorFileNotFound;
320 }
321 zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line));
322 }
323
324 if (!CloseHandle(g_hChildStd_IN_Wr)) {
325 zig_panic("stdinwr closehandle");
326 }
327
328 CloseHandle(g_hChildStd_IN_Rd);
329 CloseHandle(g_hChildStd_ERR_Wr);
330 CloseHandle(g_hChildStd_OUT_Wr);
331
332 static const int BUF_SIZE = 4 * 1024;
333 {
334 DWORD dwRead;
335 char chBuf[BUF_SIZE];
336
337 buf_resize(out_stdout, 0);
338 for (;;) {
339 success = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
340 if (!success || dwRead == 0) break;
341
342 buf_append_mem(out_stdout, chBuf, dwRead);
343 }
344 CloseHandle(g_hChildStd_OUT_Rd);
345 }
346 {
347 DWORD dwRead;
348 char chBuf[BUF_SIZE];
349
350 buf_resize(out_stderr, 0);
351 for (;;) {
352 success = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
353 if (!success || dwRead == 0) break;
354
355 buf_append_mem(out_stderr, chBuf, dwRead);
356 }
357 CloseHandle(g_hChildStd_ERR_Rd);
358 }
359
360 WaitForSingleObject(piProcInfo.hProcess, INFINITE);
361
362 DWORD exit_code;
363 if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) {
364 zig_panic("GetExitCodeProcess failed");
365 }
366 *return_code = exit_code;
367
368 CloseHandle(piProcInfo.hProcess);
369 CloseHandle(piProcInfo.hThread);
370
371 return 0;
217372}
218373#endif
219374
220void os_exec_process(const char *exe, ZigList<const char *> &args,
375int os_exec_process(const char *exe, ZigList<const char *> &args,
221376 int *return_code, Buf *out_stderr, Buf *out_stdout)
222377{
223378#if defined(ZIG_OS_WINDOWS)
......@@ -267,7 +422,11 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents) {
267422
268423int os_get_cwd(Buf *out_cwd) {
269424#if defined(ZIG_OS_WINDOWS)
270 zig_panic("TODO os_get_cwd for windows");
425 buf_resize(out_cwd, 4096);
426 if (GetCurrentDirectory(buf_len(out_cwd), buf_ptr(out_cwd)) == 0) {
427 zig_panic("GetCurrentDirectory failed");
428 }
429 return 0;
271430#elif defined(ZIG_OS_POSIX)
272431 int err = ERANGE;
273432 buf_resize(out_cwd, 512);
......@@ -296,8 +455,12 @@ bool os_stderr_tty(void) {
296455
297456#if defined(ZIG_OS_POSIX)
298457static int os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
458 const char *tmp_dir = getenv("TMPDIR");
459 if (!tmp_dir) {
460 tmp_dir = P_tmpdir;
461 }
299462 buf_resize(out_tmp_path, 0);
300 buf_appendf(out_tmp_path, "/tmp/XXXXXX%s", buf_ptr(suffix));
463 buf_appendf(out_tmp_path, "%s/XXXXXX%s", tmp_dir, buf_ptr(suffix));
301464
302465 int fd = mkstemps(buf_ptr(out_tmp_path), buf_len(suffix));
303466 if (fd < 0) {
......@@ -321,7 +484,35 @@ static int os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_pat
321484
322485#if defined(ZIG_OS_WINDOWS)
323486static int os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
324 zig_panic("TODO implement os_buf_to_tmp_file_windows");
487 char tmp_dir[MAX_PATH + 1];
488 if (GetTempPath(MAX_PATH, tmp_dir) == 0) {
489 zig_panic("GetTempPath failed");
490 }
491 buf_init_from_str(out_tmp_path, tmp_dir);
492
493 const char base64[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
494 assert(array_length(base64) == 64 + 1);
495 for (int i = 0; i < 8; i += 1) {
496 buf_append_char(out_tmp_path, base64[rand() % 64]);
497 }
498
499 buf_append_buf(out_tmp_path, suffix);
500
501 FILE *f = fopen(buf_ptr(out_tmp_path), "wb");
502
503 if (!f) {
504 zig_panic("unable to open %s: %s", buf_ptr(out_tmp_path), strerror(errno));
505 }
506
507 size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f);
508 if (amt_written != (size_t)buf_len(contents)) {
509 zig_panic("write failed: %s", strerror(errno));
510 }
511
512 if (fclose(f)) {
513 zig_panic("fclose failed");
514 }
515 return 0;
325516}
326517#endif
327518
......@@ -342,3 +533,7 @@ int os_delete_file(Buf *path) {
342533 return 0;
343534 }
344535}
536
537void os_init(void) {
538 srand(time(NULL));
539}
src/os.hpp+2-1
......@@ -13,8 +13,9 @@
1313
1414#include <stdio.h>
1515
16void os_init(void);
1617void os_spawn_process(const char *exe, ZigList<const char *> &args, int *return_code);
17void os_exec_process(const char *exe, ZigList<const char *> &args,
18int os_exec_process(const char *exe, ZigList<const char *> &args,
1819 int *return_code, Buf *out_stderr, Buf *out_stdout);
1920
2021void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);