diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-10-07 00:46:05 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-10-07 00:46:05 -0700 |
| commit | b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946 (patch) | |
| tree | 92ce1ffa64bc2d32d5ef73dce66daf3c8e893ee6 /src/stage1/os.cpp | |
| parent | d6d05fc84d33c71434a1f8bae51ca5956e08cdf0 (diff) | |
| parent | f2d374e8465042fa5cb6bf2be7b9b086948f3a94 (diff) | |
| download | zig-b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946.tar.gz zig-b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946.zip | |
Merge remote-tracking branch 'origin/master' into llvm11
Conflicts:
cmake/Findllvm.cmake
The llvm11 branch changed 10's to 11's and master branch added the
"using LLVM_CONFIG_EXE" help message, so the resolution was to merge
these changes together.
I also added a check to make sure LLVM is built with AVR enabled, which
is no longer an experimental target.
Diffstat (limited to 'src/stage1/os.cpp')
| -rw-r--r-- | src/stage1/os.cpp | 1074 |
1 files changed, 22 insertions, 1052 deletions
diff --git a/src/stage1/os.cpp b/src/stage1/os.cpp index 33d98fd416..c8e4a51306 100644 --- a/src/stage1/os.cpp +++ b/src/stage1/os.cpp @@ -94,105 +94,6 @@ static clock_serv_t macos_monotonic_clock; extern char **environ; #endif -#if defined(ZIG_OS_POSIX) -static void populate_termination(Termination *term, int status) { - if (WIFEXITED(status)) { - term->how = TerminationIdClean; - term->code = WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - term->how = TerminationIdSignaled; - term->code = WTERMSIG(status); - } else if (WIFSTOPPED(status)) { - term->how = TerminationIdStopped; - term->code = WSTOPSIG(status); - } else { - term->how = TerminationIdUnknown; - term->code = status; - } -} - -static void os_spawn_process_posix(ZigList<const char *> &args, Termination *term) { - const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1); - for (size_t i = 0; i < args.length; i += 1) { - argv[i] = args.at(i); - } - argv[args.length] = nullptr; - - pid_t pid; - int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast<char *const*>(argv), environ); - if (rc != 0) { - zig_panic("unable to spawn %s: %s", args.at(0), strerror(rc)); - } - - int status; - waitpid(pid, &status, 0); - populate_termination(term, status); -} -#endif - -#if defined(ZIG_OS_WINDOWS) - -static void os_windows_create_command_line(Buf *command_line, ZigList<const char *> &args) { - buf_resize(command_line, 0); - const char *prefix = "\""; - for (size_t arg_i = 0; arg_i < args.length; arg_i += 1) { - const char *arg = args.at(arg_i); - buf_append_str(command_line, prefix); - prefix = " \""; - size_t arg_len = strlen(arg); - for (size_t c_i = 0; c_i < arg_len; c_i += 1) { - if (arg[c_i] == '\"') { - zig_panic("TODO"); - } - buf_append_char(command_line, arg[c_i]); - } - buf_append_char(command_line, '\"'); - } -} - -static void os_spawn_process_windows(ZigList<const char *> &args, Termination *term) { - Buf command_line = BUF_INIT; - os_windows_create_command_line(&command_line, args); - - PROCESS_INFORMATION piProcInfo = {0}; - STARTUPINFOW siStartInfo = {0}; - siStartInfo.cb = sizeof(STARTUPINFOW); - - Slice<uint8_t> exe_slice = str(args.at(0)); - auto exe_utf16_slice = Slice<WCHAR>::alloc(exe_slice.len + 1); - exe_utf16_slice.ptr[utf8_to_utf16le(exe_utf16_slice.ptr, exe_slice)] = 0; - - auto command_line_utf16 = Slice<WCHAR>::alloc(buf_len(&command_line) + 1); - command_line_utf16.ptr[utf8_to_utf16le(command_line_utf16.ptr, buf_to_slice(&command_line))] = 0; - - BOOL success = CreateProcessW(exe_utf16_slice.ptr, command_line_utf16.ptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr, - &siStartInfo, &piProcInfo); - - if (!success) { - zig_panic("CreateProcess failed. exe: %s command_line: %s", args.at(0), buf_ptr(&command_line)); - } - - WaitForSingleObject(piProcInfo.hProcess, INFINITE); - - DWORD exit_code; - if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) { - zig_panic("GetExitCodeProcess failed"); - } - term->how = TerminationIdClean; - term->code = exit_code; -} -#endif - -void os_spawn_process(ZigList<const char *> &args, Termination *term) { -#if defined(ZIG_OS_WINDOWS) - os_spawn_process_windows(args, term); -#elif defined(ZIG_OS_POSIX) - os_spawn_process_posix(args, term); -#else -#error "missing os_spawn_process implementation" -#endif -} - void os_path_dirname(Buf *full_path, Buf *out_dirname) { return os_path_split(full_path, out_dirname, nullptr); } @@ -280,71 +181,27 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) { buf_append_buf(out_full_path, basename); } -Error os_path_real(Buf *rel_path, Buf *out_abs_path) { -#if defined(ZIG_OS_WINDOWS) - PathSpace rel_path_space = slice_to_prefixed_file_w(buf_to_slice(rel_path)); - PathSpace out_abs_path_space; - - if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) { - zig_panic("_wfullpath failed"); - } - utf16le_ptr_to_utf8(out_abs_path, &out_abs_path_space.data.items[0]); - return ErrorNone; -#elif defined(ZIG_OS_POSIX) - buf_resize(out_abs_path, PATH_MAX + 1); - char *result = realpath(buf_ptr(rel_path), buf_ptr(out_abs_path)); - if (!result) { - int err = errno; - if (err == EACCES) { - return ErrorAccess; - } else if (err == ENOENT) { - return ErrorFileNotFound; - } else if (err == ENOMEM) { - return ErrorNoMem; - } else { - return ErrorFileSystem; - } - } - buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path))); - return ErrorNone; -#else -#error "missing os_path_real implementation" -#endif -} - -#if defined(ZIG_OS_WINDOWS) -// Ported from std/os/path.zig -static bool isAbsoluteWindows(Slice<uint8_t> path) { - if (path.ptr[0] == '/') - return true; - - if (path.ptr[0] == '\\') { - return true; - } - if (path.len < 3) { - return false; - } - if (path.ptr[1] == ':') { - if (path.ptr[2] == '/') - return true; - if (path.ptr[2] == '\\') - return true; - } - return false; -} -#endif - -bool os_path_is_absolute(Buf *path) { -#if defined(ZIG_OS_WINDOWS) - return isAbsoluteWindows(buf_to_slice(path)); -#elif defined(ZIG_OS_POSIX) - return buf_ptr(path)[0] == '/'; -#else -#error "missing os_path_is_absolute implementation" -#endif -} -#if defined(ZIG_OS_WINDOWS) +#if defined(ZIG_OS_WINDOWS) +// Ported from std/os/path.zig +static bool isAbsoluteWindows(Slice<uint8_t> path) { + if (path.ptr[0] == '/') + return true; + + if (path.ptr[0] == '\\') { + return true; + } + if (path.len < 3) { + return false; + } + if (path.ptr[1] == ':') { + if (path.ptr[2] == '/') + return true; + if (path.ptr[2] == '\\') + return true; + } + return false; +} enum WindowsPathKind { WindowsPathKindNone, @@ -687,7 +544,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) { size_t max_size = 0; for (size_t i = 0; i < paths_len; i += 1) { Buf *p = paths_ptr[i]; - if (os_path_is_absolute(p)) { + if (buf_ptr(p)[0] == '/') { first_index = i; have_abs = true; max_size = 0; @@ -748,6 +605,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) { Buf return_value = BUF_INIT; buf_init_from_mem(&return_value, (char *)result_ptr, result_index); + heap::c_allocator.deallocate(result_ptr, result_len); return return_value; } #endif @@ -786,256 +644,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf) { zig_unreachable(); } -Error os_file_exists(Buf *full_path, bool *result) { -#if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); - *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES; - return ErrorNone; -#else - *result = access(buf_ptr(full_path), F_OK) != -1; - return ErrorNone; -#endif -} - -#if defined(ZIG_OS_POSIX) -static Error os_exec_process_posix(ZigList<const char *> &args, - Termination *term, Buf *out_stderr, Buf *out_stdout) -{ - int stdin_pipe[2]; - int stdout_pipe[2]; - int stderr_pipe[2]; - int err_pipe[2]; - - int err; - if ((err = pipe(stdin_pipe))) - zig_panic("pipe failed"); - if ((err = pipe(stdout_pipe))) - zig_panic("pipe failed"); - if ((err = pipe(stderr_pipe))) - zig_panic("pipe failed"); - if ((err = pipe(err_pipe))) - zig_panic("pipe failed"); - - pid_t pid = fork(); - if (pid == -1) - zig_panic("fork failed: %s", strerror(errno)); - if (pid == 0) { - // child - if (dup2(stdin_pipe[0], STDIN_FILENO) == -1) - zig_panic("dup2 failed"); - - if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1) - zig_panic("dup2 failed"); - - if (dup2(stderr_pipe[1], STDERR_FILENO) == -1) - zig_panic("dup2 failed"); - - const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1); - argv[args.length] = nullptr; - for (size_t i = 0; i < args.length; i += 1) { - argv[i] = args.at(i); - } - execvp(argv[0], const_cast<char * const *>(argv)); - Error report_err = ErrorUnexpected; - if (errno == ENOENT) { - report_err = ErrorFileNotFound; - } - if (write(err_pipe[1], &report_err, sizeof(Error)) == -1) { - zig_panic("write failed"); - } - exit(1); - } else { - // parent - close(stdin_pipe[0]); - close(stdin_pipe[1]); - close(stdout_pipe[1]); - close(stderr_pipe[1]); - - int status; - waitpid(pid, &status, 0); - populate_termination(term, status); - - FILE *stdout_f = fdopen(stdout_pipe[0], "rb"); - FILE *stderr_f = fdopen(stderr_pipe[0], "rb"); - Error err1 = os_fetch_file(stdout_f, out_stdout); - Error err2 = os_fetch_file(stderr_f, out_stderr); - - fclose(stdout_f); - fclose(stderr_f); - - if (err1) return err1; - if (err2) return err2; - - Error child_err = ErrorNone; - if (write(err_pipe[1], &child_err, sizeof(Error)) == -1) { - zig_panic("write failed"); - } - close(err_pipe[1]); - if (read(err_pipe[0], &child_err, sizeof(Error)) == -1) { - zig_panic("write failed"); - } - close(err_pipe[0]); - return child_err; - } -} -#endif - -#if defined(ZIG_OS_WINDOWS) - -//static void win32_panic(const char *str) { -// DWORD err = GetLastError(); -// LPSTR messageBuffer = nullptr; -// FormatMessageA( -// FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, -// NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); -// zig_panic(str, messageBuffer); -// LocalFree(messageBuffer); -//} - -static Error os_exec_process_windows(ZigList<const char *> &args, - Termination *term, Buf *out_stderr, Buf *out_stdout) -{ - Buf command_line = BUF_INIT; - os_windows_create_command_line(&command_line, args); - - HANDLE g_hChildStd_IN_Rd = NULL; - HANDLE g_hChildStd_IN_Wr = NULL; - HANDLE g_hChildStd_OUT_Rd = NULL; - HANDLE g_hChildStd_OUT_Wr = NULL; - HANDLE g_hChildStd_ERR_Rd = NULL; - HANDLE g_hChildStd_ERR_Wr = NULL; - - SECURITY_ATTRIBUTES saAttr; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) { - zig_panic("StdoutRd CreatePipe"); - } - - if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { - zig_panic("Stdout SetHandleInformation"); - } - - if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) { - zig_panic("stderr CreatePipe"); - } - - if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { - zig_panic("stderr SetHandleInformation"); - } - - if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) { - zig_panic("Stdin CreatePipe"); - } - - if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) { - zig_panic("Stdin SetHandleInformation"); - } - - - PROCESS_INFORMATION piProcInfo = {0}; - STARTUPINFO siStartInfo = {0}; - siStartInfo.cb = sizeof(STARTUPINFO); - siStartInfo.hStdError = g_hChildStd_ERR_Wr; - siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; - siStartInfo.hStdInput = g_hChildStd_IN_Rd; - siStartInfo.dwFlags |= STARTF_USESTDHANDLES; - - const char *exe = args.at(0); - BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr, - &siStartInfo, &piProcInfo); - - if (!success) { - if (GetLastError() == ERROR_FILE_NOT_FOUND) { - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); - return ErrorFileNotFound; - } - zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line)); - } - - if (!CloseHandle(g_hChildStd_IN_Wr)) { - zig_panic("stdinwr closehandle"); - } - - CloseHandle(g_hChildStd_IN_Rd); - CloseHandle(g_hChildStd_ERR_Wr); - CloseHandle(g_hChildStd_OUT_Wr); - - static const size_t BUF_SIZE = 4 * 1024; - { - DWORD dwRead; - char chBuf[BUF_SIZE]; - - buf_resize(out_stdout, 0); - for (;;) { - success = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUF_SIZE, &dwRead, NULL); - if (!success || dwRead == 0) break; - - buf_append_mem(out_stdout, chBuf, dwRead); - } - CloseHandle(g_hChildStd_OUT_Rd); - } - { - DWORD dwRead; - char chBuf[BUF_SIZE]; - - buf_resize(out_stderr, 0); - for (;;) { - success = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUF_SIZE, &dwRead, NULL); - if (!success || dwRead == 0) break; - - buf_append_mem(out_stderr, chBuf, dwRead); - } - CloseHandle(g_hChildStd_ERR_Rd); - } - - WaitForSingleObject(piProcInfo.hProcess, INFINITE); - - DWORD exit_code; - if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) { - zig_panic("GetExitCodeProcess failed"); - } - term->how = TerminationIdClean; - term->code = exit_code; - - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); - - return ErrorNone; -} -#endif - -Error os_execv(const char *exe, const char **argv) { -#if defined(ZIG_OS_WINDOWS) - return ErrorUnsupportedOperatingSystem; -#else - execv(exe, (char *const *)argv); - switch (errno) { - case ENOMEM: - return ErrorSystemResources; - case EIO: - return ErrorFileSystem; - default: - return ErrorUnexpected; - } -#endif -} - -Error os_exec_process(ZigList<const char *> &args, - Termination *term, Buf *out_stderr, Buf *out_stdout) -{ -#if defined(ZIG_OS_WINDOWS) - return os_exec_process_windows(args, term, out_stderr, out_stdout); -#elif defined(ZIG_OS_POSIX) - return os_exec_process_posix(args, term, out_stderr, out_stdout); -#else -#error "missing os_exec_process implementation" -#endif -} - Error os_write_file(Buf *full_path, Buf *contents) { #if defined(ZIG_OS_WINDOWS) PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); @@ -1074,35 +682,6 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) { } } -Error os_dump_file(Buf *src_path, FILE *dest_file) { - Error err; - -#if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(src_path)); - FILE *src_f = _wfopen(&path_space.data.items[0], L"rb"); -#else - FILE *src_f = fopen(buf_ptr(src_path), "rb"); -#endif - if (!src_f) { - int err = errno; - if (err == ENOENT) { - return ErrorFileNotFound; - } else if (err == EACCES || err == EPERM) { - return ErrorAccess; - } else { - return ErrorFileSystem; - } - } - copy_open_files(src_f, dest_file); - if ((err = copy_open_files(src_f, dest_file))) { - fclose(src_f); - return err; - } - - fclose(src_f); - return ErrorNone; -} - #if defined(ZIG_OS_WINDOWS) static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) { mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime; @@ -1116,88 +695,6 @@ static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) { } #endif -static Error set_file_times(OsFile file, OsTimeStamp ts) { -#if defined(ZIG_OS_WINDOWS) - FILETIME ft = windows_os_timestamp_to_filetime(ts); - if (SetFileTime(file, nullptr, &ft, &ft) == 0) { - return ErrorUnexpected; - } - return ErrorNone; -#else - struct timespec times[2] = { - { (time_t)ts.sec, (long)ts.nsec }, - { (time_t)ts.sec, (long)ts.nsec }, - }; - if (futimens(file, times) == -1) { - switch (errno) { - case EBADF: - zig_panic("futimens EBADF"); - default: - return ErrorUnexpected; - } - } - return ErrorNone; -#endif -} - -Error os_update_file(Buf *src_path, Buf *dst_path) { - Error err; - - OsFile src_file; - OsFileAttr src_attr; - if ((err = os_file_open_r(src_path, &src_file, &src_attr))) { - return err; - } - - OsFile dst_file; - OsFileAttr dst_attr; - if ((err = os_file_open_w(dst_path, &dst_file, &dst_attr, src_attr.mode))) { - os_file_close(&src_file); - return err; - } - - if (src_attr.size == dst_attr.size && - src_attr.mode == dst_attr.mode && - src_attr.mtime.sec == dst_attr.mtime.sec && - src_attr.mtime.nsec == dst_attr.mtime.nsec) - { - os_file_close(&src_file); - os_file_close(&dst_file); - return ErrorNone; - } -#if defined(ZIG_OS_WINDOWS) - if (SetEndOfFile(dst_file) == 0) { - return ErrorUnexpected; - } -#else - if (ftruncate(dst_file, 0) == -1) { - return ErrorUnexpected; - } -#endif -#if defined(ZIG_OS_WINDOWS) - FILE *src_libc_file = _fdopen(_open_osfhandle((intptr_t)src_file, _O_RDONLY), "rb"); - FILE *dst_libc_file = _fdopen(_open_osfhandle((intptr_t)dst_file, 0), "wb"); -#else - FILE *src_libc_file = fdopen(src_file, "rb"); - FILE *dst_libc_file = fdopen(dst_file, "wb"); -#endif - assert(src_libc_file); - assert(dst_libc_file); - - if ((err = copy_open_files(src_libc_file, dst_libc_file))) { - fclose(src_libc_file); - fclose(dst_libc_file); - return err; - } - if (fflush(dst_libc_file) == -1) { - return ErrorUnexpected; - } - err = set_file_times(dst_file, src_attr.mtime); - fclose(src_libc_file); - fclose(dst_libc_file); - return err; -} - Error os_copy_file(Buf *src_path, Buf *dest_path) { #if defined(ZIG_OS_WINDOWS) PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path)); @@ -1358,14 +855,6 @@ bool os_stderr_tty(void) { #endif } -Error os_delete_file(Buf *path) { - if (remove(buf_ptr(path))) { - return ErrorFileSystem; - } else { - return ErrorNone; - } -} - Error os_rename(Buf *src_path, Buf *dest_path) { if (buf_eql_buf(src_path, dest_path)) { return ErrorNone; @@ -1384,30 +873,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) { return ErrorNone; } -OsTimeStamp os_timestamp_calendar(void) { - OsTimeStamp result; -#if defined(ZIG_OS_WINDOWS) - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - windows_filetime_to_os_timestamp(&ft, &result); -#elif defined(__MACH__) - mach_timespec_t mts; - - kern_return_t err = clock_get_time(macos_calendar_clock, &mts); - assert(!err); - - result.sec = mts.tv_sec; - result.nsec = mts.tv_nsec; -#else - struct timespec tms; - clock_gettime(CLOCK_REALTIME, &tms); - - result.sec = tms.tv_sec; - result.nsec = tms.tv_nsec; -#endif - return result; -} - OsTimeStamp os_timestamp_monotonic(void) { OsTimeStamp result; #if defined(ZIG_OS_WINDOWS) @@ -1501,49 +966,8 @@ Error os_make_dir(Buf *path) { #endif } -static void init_rand() { -#if defined(ZIG_OS_WINDOWS) - char bytes[sizeof(unsigned)]; - unsigned seed; - RtlGenRandom(bytes, sizeof(unsigned)); - memcpy(&seed, bytes, sizeof(unsigned)); - srand(seed); -#elif defined(ZIG_OS_LINUX) - unsigned char *ptr_random = (unsigned char*)getauxval(AT_RANDOM); - unsigned seed; - memcpy(&seed, ptr_random, sizeof(seed)); - srand(seed); -#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) - unsigned seed; - size_t len = sizeof(seed); - int mib[2] = { CTL_KERN, KERN_ARND }; - if (sysctl(mib, 2, &seed, &len, NULL, 0) != 0) { - zig_panic("unable to query random data from sysctl"); - } - srand(seed); -#else - int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); - if (fd == -1) { - zig_panic("unable to open /dev/urandom"); - } - char bytes[sizeof(unsigned)]; - ssize_t amt_read; - while ((amt_read = read(fd, bytes, sizeof(unsigned))) == -1) { - if (errno == EINTR) continue; - zig_panic("unable to read /dev/urandom"); - } - if (amt_read != sizeof(unsigned)) { - zig_panic("unable to read enough bytes from /dev/urandom"); - } - close(fd); - unsigned seed; - memcpy(&seed, bytes, sizeof(unsigned)); - srand(seed); -#endif -} int os_init(void) { - init_rand(); #if defined(ZIG_OS_WINDOWS) _setmode(fileno(stdout), _O_BINARY); _setmode(fileno(stderr), _O_BINARY); @@ -1580,71 +1004,6 @@ int os_init(void) { return 0; } -Error os_self_exe_path(Buf *out_path) { -#if defined(ZIG_OS_WINDOWS) - PathSpace path_space; - DWORD copied_amt = GetModuleFileNameW(nullptr, &path_space.data.items[0], PATH_MAX_WIDE); - if (copied_amt <= 0) { - return ErrorFileNotFound; - } - utf16le_ptr_to_utf8(out_path, &path_space.data.items[0]); - return ErrorNone; - -#elif defined(ZIG_OS_DARWIN) - // How long is the executable's path? - uint32_t u32_len = 0; - int ret1 = _NSGetExecutablePath(nullptr, &u32_len); - assert(ret1 != 0); - - Buf *tmp = buf_alloc_fixed(u32_len); - - // Fill the executable path. - int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len); - assert(ret2 == 0); - - // According to libuv project, PATH_MAX*2 works around a libc bug where - // the resolved path is sometimes bigger than PATH_MAX. - buf_resize(out_path, PATH_MAX*2); - char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path)); - if (!real_path) { - buf_init_from_buf(out_path, tmp); - return ErrorNone; - } - - // Resize out_path for the correct length. - buf_resize(out_path, strlen(buf_ptr(out_path))); - - return ErrorNone; -#elif defined(ZIG_OS_LINUX) - buf_resize(out_path, PATH_MAX); - ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path)); - if (amt == -1) { - return ErrorUnexpected; - } - buf_resize(out_path, amt); - return ErrorNone; -#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_DRAGONFLY) - buf_resize(out_path, PATH_MAX); - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; - size_t cb = PATH_MAX; - if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { - return ErrorUnexpected; - } - buf_resize(out_path, cb - 1); - return ErrorNone; -#elif defined(ZIG_OS_NETBSD) - buf_resize(out_path, PATH_MAX); - int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; - size_t cb = PATH_MAX; - if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { - return ErrorUnexpected; - } - buf_resize(out_path, cb - 1); - return ErrorNone; -#endif - return ErrorFileNotFound; -} - #define VT_RED "\x1b[31;1m" #define VT_GREEN "\x1b[32;1m" #define VT_CYAN "\x1b[36;1m" @@ -1954,392 +1313,3 @@ PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) { return path_space; } #endif - -// Ported from std.os.getAppDataDir -Error os_get_app_data_dir(Buf *out_path, const char *appname) { -#if defined(ZIG_OS_WINDOWS) - WCHAR *dir_path_ptr; - switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) { - case S_OK: - // defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr)); - utf16le_ptr_to_utf8(out_path, dir_path_ptr); - CoTaskMemFree(dir_path_ptr); - buf_appendf(out_path, "\\%s", appname); - return ErrorNone; - case E_OUTOFMEMORY: - return ErrorNoMem; - default: - return ErrorUnexpected; - } - zig_unreachable(); -#elif defined(ZIG_OS_DARWIN) - const char *home_dir = getenv("HOME"); - if (home_dir == nullptr) { - // TODO use /etc/passwd - return ErrorFileNotFound; - } - buf_resize(out_path, 0); - buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname); - return ErrorNone; -#elif defined(ZIG_OS_POSIX) - const char *cache_dir = getenv("XDG_CACHE_HOME"); - if (cache_dir == nullptr) { - cache_dir = getenv("HOME"); - if (cache_dir == nullptr) { - // TODO use /etc/passwd - return ErrorFileNotFound; - } - if (cache_dir[0] == 0) { - return ErrorFileNotFound; - } - buf_init_from_str(out_path, cache_dir); - if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') { - buf_append_char(out_path, '/'); - } - buf_appendf(out_path, ".cache/%s", appname); - } else { - if (cache_dir[0] == 0) { - return ErrorFileNotFound; - } - buf_init_from_str(out_path, cache_dir); - if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') { - buf_append_char(out_path, '/'); - } - buf_appendf(out_path, "%s", appname); - } - return ErrorNone; -#endif -} - -#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) -static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) { - ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data); - if (info->dlpi_name[0] == '/') { - libs->append(buf_create_from_str(info->dlpi_name)); - } - return 0; -} -#endif - -Error os_self_exe_shared_libs(ZigList<Buf *> &paths) { -#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) - paths.resize(0); - dl_iterate_phdr(self_exe_shared_libs_callback, &paths); - return ErrorNone; -#elif defined(ZIG_OS_DARWIN) - paths.resize(0); - uint32_t img_count = _dyld_image_count(); - for (uint32_t i = 0; i != img_count; i += 1) { - const char *name = _dyld_get_image_name(i); - paths.append(buf_create_from_str(name)); - } - return ErrorNone; -#elif defined(ZIG_OS_WINDOWS) - // zig is built statically on windows, so we can return an empty list - paths.resize(0); - return ErrorNone; -#else -#error unimplemented -#endif -} - -Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) { -#if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); - HANDLE result = CreateFileW(&path_space.data.items[0], - need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ, - need_write ? 0 : FILE_SHARE_READ, - nullptr, - need_write ? OPEN_ALWAYS : OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, nullptr); - - if (result == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); - switch (err) { - case ERROR_SHARING_VIOLATION: - return ErrorSharingViolation; - case ERROR_ALREADY_EXISTS: - return ErrorPathAlreadyExists; - case ERROR_FILE_EXISTS: - return ErrorPathAlreadyExists; - case ERROR_FILE_NOT_FOUND: - return ErrorFileNotFound; - case ERROR_PATH_NOT_FOUND: - return ErrorFileNotFound; - case ERROR_ACCESS_DENIED: - return ErrorAccess; - case ERROR_PIPE_BUSY: - return ErrorPipeBusy; - default: - return ErrorUnexpected; - } - } - *out_file = result; - - if (attr != nullptr) { - BY_HANDLE_FILE_INFORMATION file_info; - if (!GetFileInformationByHandle(result, &file_info)) { - CloseHandle(result); - return ErrorUnexpected; - } - windows_filetime_to_os_timestamp(&file_info.ftLastWriteTime, &attr->mtime); - attr->inode = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow; - attr->mode = 0; - attr->size = (((uint64_t)file_info.nFileSizeHigh) << 32) | file_info.nFileSizeLow; - } - - return ErrorNone; -#else - for (;;) { - int fd = open(buf_ptr(full_path), - need_write ? (O_RDWR|O_CLOEXEC|O_CREAT) : (O_RDONLY|O_CLOEXEC), mode); - if (fd == -1) { - switch (errno) { - case EINTR: - continue; - case EINVAL: - zig_unreachable(); - case EFAULT: - zig_unreachable(); - case EACCES: - case EPERM: - return ErrorAccess; - case EISDIR: - return ErrorIsDir; - case ENOENT: - return ErrorFileNotFound; - default: - return ErrorFileSystem; - } - } - struct stat statbuf; - if (fstat(fd, &statbuf) == -1) { - close(fd); - return ErrorFileSystem; - } - if (S_ISDIR(statbuf.st_mode)) { - close(fd); - return ErrorIsDir; - } - *out_file = fd; - - if (attr != nullptr) { - attr->inode = statbuf.st_ino; -#if defined(ZIG_OS_DARWIN) - attr->mtime.sec = statbuf.st_mtimespec.tv_sec; - attr->mtime.nsec = statbuf.st_mtimespec.tv_nsec; -#else - attr->mtime.sec = statbuf.st_mtim.tv_sec; - attr->mtime.nsec = statbuf.st_mtim.tv_nsec; -#endif - attr->mode = statbuf.st_mode; - attr->size = statbuf.st_size; - } - return ErrorNone; - } -#endif -} - -Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) { - return os_file_open_rw(full_path, out_file, attr, false, 0); -} - -Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode) { - return os_file_open_rw(full_path, out_file, attr, true, mode); -} - -Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) { -#if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); - for (;;) { - HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE, - 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - - if (result == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); - switch (err) { - case ERROR_SHARING_VIOLATION: - // TODO wait for the lock instead of sleeping - Sleep(10); - continue; - case ERROR_ALREADY_EXISTS: - return ErrorPathAlreadyExists; - case ERROR_FILE_EXISTS: - return ErrorPathAlreadyExists; - case ERROR_FILE_NOT_FOUND: - return ErrorFileNotFound; - case ERROR_PATH_NOT_FOUND: - return ErrorFileNotFound; - case ERROR_ACCESS_DENIED: - return ErrorAccess; - case ERROR_PIPE_BUSY: - return ErrorPipeBusy; - default: - return ErrorUnexpected; - } - } - *out_file = result; - return ErrorNone; - } -#else - int fd; - for (;;) { - fd = open(buf_ptr(full_path), O_RDWR|O_CLOEXEC|O_CREAT, 0666); - if (fd == -1) { - switch (errno) { - case EINTR: - continue; - case EINVAL: - zig_unreachable(); - case EFAULT: - zig_unreachable(); - case EACCES: - case EPERM: - return ErrorAccess; - case EISDIR: - return ErrorIsDir; - case ENOENT: - return ErrorFileNotFound; - case ENOTDIR: - return ErrorNotDir; - default: - return ErrorFileSystem; - } - } - break; - } - for (;;) { - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - if (fcntl(fd, F_SETLKW, &lock) == -1) { - switch (errno) { - case EINTR: - continue; - case EBADF: - zig_unreachable(); - case EFAULT: - zig_unreachable(); - case EINVAL: - zig_unreachable(); - default: - close(fd); - return ErrorFileSystem; - } - } - break; - } - *out_file = fd; - return ErrorNone; -#endif -} - -Error os_file_read(OsFile file, void *ptr, size_t *len) { -#if defined(ZIG_OS_WINDOWS) - DWORD amt_read; - if (ReadFile(file, ptr, *len, &amt_read, nullptr) == 0) - return ErrorUnexpected; - *len = amt_read; - return ErrorNone; -#else - for (;;) { - ssize_t rc = read(file, ptr, *len); - if (rc == -1) { - switch (errno) { - case EINTR: - continue; - case EBADF: - zig_unreachable(); - case EFAULT: - zig_unreachable(); - case EISDIR: - return ErrorIsDir; - default: - return ErrorFileSystem; - } - } - *len = rc; - return ErrorNone; - } -#endif -} - -Error os_file_read_all(OsFile file, Buf *contents) { - Error err; - size_t index = 0; - for (;;) { - size_t amt = buf_len(contents) - index; - - if (amt < 4096) { - buf_resize(contents, buf_len(contents) + (4096 - amt)); - amt = buf_len(contents) - index; - } - - if ((err = os_file_read(file, buf_ptr(contents) + index, &amt))) - return err; - - if (amt == 0) { - buf_resize(contents, index); - return ErrorNone; - } - - index += amt; - } -} - -Error os_file_overwrite(OsFile file, Buf *contents) { -#if defined(ZIG_OS_WINDOWS) - if (SetFilePointer(file, 0, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return ErrorFileSystem; - if (!SetEndOfFile(file)) - return ErrorFileSystem; - DWORD bytes_written; - if (!WriteFile(file, buf_ptr(contents), buf_len(contents), &bytes_written, nullptr)) - return ErrorFileSystem; - return ErrorNone; -#else - if (lseek(file, 0, SEEK_SET) == -1) - return ErrorUnexpectedSeekFailure; - if (ftruncate(file, 0) == -1) - return ErrorUnexpectedFileTruncationFailure; - for (;;) { - if (write(file, buf_ptr(contents), buf_len(contents)) == -1) { - switch (errno) { - case EINTR: - continue; - case EINVAL: - zig_unreachable(); - case EBADF: - zig_unreachable(); - case EFAULT: - zig_unreachable(); - case EDQUOT: - return ErrorDiskQuota; - case ENOSPC: - return ErrorDiskSpace; - case EFBIG: - return ErrorFileTooBig; - case EIO: - return ErrorFileSystem; - case EPERM: - return ErrorAccess; - default: - return ErrorUnexpectedWriteFailure; - } - } - return ErrorNone; - } -#endif -} - -void os_file_close(OsFile *file) { -#if defined(ZIG_OS_WINDOWS) - CloseHandle(*file); - *file = NULL; -#else - close(*file); - *file = -1; -#endif -} |
