aboutsummaryrefslogtreecommitdiff
path: root/src/stage1/os.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-12-06 18:52:39 -0500
committerGitHub <noreply@github.com>2022-12-06 18:52:39 -0500
commite7d28344fa3ee81d6ad7ca5ce1f83d50d8502118 (patch)
tree012b2556f2bda10ae663fab8efb235efe30e02f4 /src/stage1/os.cpp
parent817cf6a82efa7ed274371a28621bbf88a723d9b7 (diff)
parent20d86d9c63476b6312b87dc5b0e4aa4822eb7717 (diff)
downloadzig-e7d28344fa3ee81d6ad7ca5ce1f83d50d8502118.tar.gz
zig-e7d28344fa3ee81d6ad7ca5ce1f83d50d8502118.zip
Merge pull request #13560 from ziglang/wasi-bootstrap
Nuke the C++ implementation of Zig from orbit using WASI
Diffstat (limited to 'src/stage1/os.cpp')
-rw-r--r--src/stage1/os.cpp1282
1 files changed, 0 insertions, 1282 deletions
diff --git a/src/stage1/os.cpp b/src/stage1/os.cpp
deleted file mode 100644
index 776d2a2915..0000000000
--- a/src/stage1/os.cpp
+++ /dev/null
@@ -1,1282 +0,0 @@
-/*
- * Copyright (c) 2015 Andrew Kelley
- *
- * This file is part of zig, which is MIT licensed.
- * See http://opensource.org/licenses/MIT
- */
-
-#include "os.hpp"
-#include "buffer.hpp"
-#include "heap.hpp"
-#include "util.hpp"
-#include "error.hpp"
-#include "util_base.hpp"
-#include <stdint.h>
-#include <stdio.h>
-
-#if defined(_WIN32)
-
-#if !defined(NOMINMAX)
-#define NOMINMAX
-#endif
-
-#if !defined(VC_EXTRALEAN)
-#define VC_EXTRALEAN
-#endif
-
-#if !defined(WIN32_LEAN_AND_MEAN)
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#if !defined(_WIN32_WINNT)
-#define _WIN32_WINNT 0x600
-#endif
-
-#if !defined(NTDDI_VERSION)
-#define NTDDI_VERSION 0x06000000
-#endif
-
-#include <windows.h>
-#include <shlobj.h>
-#include <io.h>
-#include <fcntl.h>
-#include <ntsecapi.h>
-#include <math.h>
-
-// Workaround an upstream LLVM issue.
-// See https://github.com/ziglang/zig/issues/7614#issuecomment-752939981
-#if defined(_MSC_VER) && defined(_WIN64)
-typedef SSIZE_T ssize_t;
-#endif
-#else
-#define ZIG_OS_POSIX
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/resource.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <spawn.h>
-
-#endif
-
-#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) || defined(ZIG_OS_OPENBSD) || defined(ZIG_OS_HAIKU)
-#include <link.h>
-#endif
-
-#if defined(ZIG_OS_LINUX)
-#include <sys/auxv.h>
-#endif
-
-#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) || defined(ZIG_OS_OPENBSD)
-#include <sys/sysctl.h>
-#endif
-
-#if defined(__MACH__)
-#include <mach/clock.h>
-#include <mach/mach.h>
-#include <mach-o/dyld.h>
-#endif
-
-#if defined(ZIG_OS_WINDOWS)
-static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le);
-static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8);
-static uint64_t windows_perf_freq;
-#elif defined(__MACH__)
-static clock_serv_t macos_calendar_clock;
-static clock_serv_t macos_monotonic_clock;
-#endif
-
-#include <stdlib.h>
-#include <errno.h>
-#include <time.h>
-
-#if !defined(environ)
-extern char **environ;
-#endif
-
-void os_path_dirname(Buf *full_path, Buf *out_dirname) {
- return os_path_split(full_path, out_dirname, nullptr);
-}
-
-bool os_is_sep(uint8_t c) {
-#if defined(ZIG_OS_WINDOWS)
- return c == '\\' || c == '/';
-#else
- return c == '/';
-#endif
-}
-
-void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
- size_t len = buf_len(full_path);
- if (len != 0) {
- size_t last_index = len - 1;
- char last_char = buf_ptr(full_path)[last_index];
- if (os_is_sep(last_char)) {
- if (last_index == 0) {
- if (out_dirname) buf_init_from_mem(out_dirname, &last_char, 1);
- if (out_basename) buf_init_from_str(out_basename, "");
- return;
- }
- last_index -= 1;
- }
- for (size_t i = last_index;;) {
- uint8_t c = buf_ptr(full_path)[i];
- if (os_is_sep(c)) {
- if (out_dirname) {
- buf_init_from_mem(out_dirname, buf_ptr(full_path), (i == 0) ? 1 : i);
- }
- if (out_basename) {
- buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1));
- }
- return;
- }
- if (i == 0) break;
- i -= 1;
- }
- }
- if (out_dirname) buf_init_from_mem(out_dirname, ".", 1);
- if (out_basename) buf_init_from_buf(out_basename, full_path);
-}
-
-void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) {
- if (buf_len(full_path) == 0) {
- if (out_basename) buf_init_from_str(out_basename, "");
- if (out_extname) buf_init_from_str(out_extname, "");
- return;
- }
- size_t i = buf_len(full_path) - 1;
- while (true) {
- if (buf_ptr(full_path)[i] == '.') {
- if (out_basename) {
- buf_resize(out_basename, 0);
- buf_append_mem(out_basename, buf_ptr(full_path), i);
- }
-
- if (out_extname) {
- buf_resize(out_extname, 0);
- buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i);
- }
- return;
- }
-
- if (i == 0) {
- if (out_basename) buf_init_from_buf(out_basename, full_path);
- if (out_extname) buf_init_from_str(out_extname, "");
- return;
- }
- i -= 1;
- }
-}
-
-void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
- if (buf_len(dirname) == 0) {
- buf_init_from_buf(out_full_path, basename);
- return;
- }
-
- buf_init_from_buf(out_full_path, dirname);
- uint8_t c = *(buf_ptr(out_full_path) + buf_len(out_full_path) - 1);
- if (!os_is_sep(c))
- buf_append_char(out_full_path, ZIG_OS_SEP_CHAR);
- buf_append_buf(out_full_path, basename);
-}
-
-
-#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,
- WindowsPathKindDrive,
- WindowsPathKindNetworkShare,
-};
-
-struct WindowsPath {
- Slice<uint8_t> disk_designator;
- WindowsPathKind kind;
- bool is_abs;
-};
-
-
-// Ported from std/os/path.zig
-static WindowsPath windowsParsePath(Slice<uint8_t> path) {
- if (path.len >= 2 && path.ptr[1] == ':') {
- return WindowsPath{
- path.slice(0, 2),
- WindowsPathKindDrive,
- isAbsoluteWindows(path),
- };
- }
- if (path.len >= 1 && (path.ptr[0] == '/' || path.ptr[0] == '\\') &&
- (path.len == 1 || (path.ptr[1] != '/' && path.ptr[1] != '\\')))
- {
- return WindowsPath{
- path.slice(0, 0),
- WindowsPathKindNone,
- true,
- };
- }
- WindowsPath relative_path = {
- str(""),
- WindowsPathKindNone,
- false,
- };
- if (path.len < strlen("//a/b")) {
- return relative_path;
- }
-
- {
- if (memStartsWith(path, str("//"))) {
- if (path.ptr[2] == '/') {
- return relative_path;
- }
-
- SplitIterator it = memSplit(path, str("/"));
- {
- Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
- if (!opt_component.is_some) return relative_path;
- }
- {
- Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
- if (!opt_component.is_some) return relative_path;
- }
- return WindowsPath{
- path.slice(0, it.index),
- WindowsPathKindNetworkShare,
- isAbsoluteWindows(path),
- };
- }
- }
- {
- if (memStartsWith(path, str("\\\\"))) {
- if (path.ptr[2] == '\\') {
- return relative_path;
- }
-
- SplitIterator it = memSplit(path, str("\\"));
- {
- Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
- if (!opt_component.is_some) return relative_path;
- }
- {
- Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
- if (!opt_component.is_some) return relative_path;
- }
- return WindowsPath{
- path.slice(0, it.index),
- WindowsPathKindNetworkShare,
- isAbsoluteWindows(path),
- };
- }
- }
- return relative_path;
-}
-
-// Ported from std/os/path.zig
-static uint8_t asciiUpper(uint8_t byte) {
- if (byte >= 'a' && byte <= 'z') {
- return 'A' + (byte - 'a');
- }
- return byte;
-}
-
-// Ported from std/os/path.zig
-static bool asciiEqlIgnoreCase(Slice<uint8_t> s1, Slice<uint8_t> s2) {
- if (s1.len != s2.len)
- return false;
- for (size_t i = 0; i < s1.len; i += 1) {
- if (asciiUpper(s1.ptr[i]) != asciiUpper(s2.ptr[i]))
- return false;
- }
- return true;
-}
-
-// Ported from std/os/path.zig
-static bool compareDiskDesignators(WindowsPathKind kind, Slice<uint8_t> p1, Slice<uint8_t> p2) {
- switch (kind) {
- case WindowsPathKindNone:
- assert(p1.len == 0);
- assert(p2.len == 0);
- return true;
- case WindowsPathKindDrive:
- return asciiUpper(p1.ptr[0]) == asciiUpper(p2.ptr[0]);
- case WindowsPathKindNetworkShare:
- uint8_t sep1 = p1.ptr[0];
- uint8_t sep2 = p2.ptr[0];
-
- SplitIterator it1 = memSplit(p1, {&sep1, 1});
- SplitIterator it2 = memSplit(p2, {&sep2, 1});
-
- // TODO ASCII is wrong, we actually need full unicode support to compare paths.
- return asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value) &&
- asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value);
- }
- zig_unreachable();
-}
-
-// Ported from std/os/path.zig
-static Buf os_path_resolve_windows(Buf **paths_ptr, size_t paths_len) {
- if (paths_len == 0) {
- Buf cwd = BUF_INIT;
- int err;
- if ((err = os_get_cwd(&cwd))) {
- zig_panic("get cwd failed");
- }
- return cwd;
- }
-
- // determine which disk designator we will result with, if any
- char result_drive_buf[3] = {'_', ':', '\0'}; // 0 needed for strlen later
- Slice<uint8_t> result_disk_designator = str("");
- WindowsPathKind have_drive_kind = WindowsPathKindNone;
- bool have_abs_path = false;
- size_t first_index = 0;
- size_t max_size = 0;
- for (size_t i = 0; i < paths_len; i += 1) {
- Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
- WindowsPath parsed = windowsParsePath(p);
- if (parsed.is_abs) {
- have_abs_path = true;
- first_index = i;
- max_size = result_disk_designator.len;
- }
- switch (parsed.kind) {
- case WindowsPathKindDrive:
- result_drive_buf[0] = asciiUpper(parsed.disk_designator.ptr[0]);
- result_disk_designator = str(result_drive_buf);
- have_drive_kind = WindowsPathKindDrive;
- break;
- case WindowsPathKindNetworkShare:
- result_disk_designator = parsed.disk_designator;
- have_drive_kind = WindowsPathKindNetworkShare;
- break;
- case WindowsPathKindNone:
- break;
- }
- max_size += p.len + 1;
- }
-
- // if we will result with a disk designator, loop again to determine
- // which is the last time the disk designator is absolutely specified, if any
- // and count up the max bytes for paths related to this disk designator
- if (have_drive_kind != WindowsPathKindNone) {
- have_abs_path = false;
- first_index = 0;
- max_size = result_disk_designator.len;
- bool correct_disk_designator = false;
-
- for (size_t i = 0; i < paths_len; i += 1) {
- Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
- WindowsPath parsed = windowsParsePath(p);
- if (parsed.kind != WindowsPathKindNone) {
- if (parsed.kind == have_drive_kind) {
- correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
- } else {
- continue;
- }
- }
- if (!correct_disk_designator) {
- continue;
- }
- if (parsed.is_abs) {
- first_index = i;
- max_size = result_disk_designator.len;
- have_abs_path = true;
- }
- max_size += p.len + 1;
- }
- }
-
- // Allocate result and fill in the disk designator, calling getCwd if we have to.
- Slice<uint8_t> result;
- size_t result_index = 0;
-
- if (have_abs_path) {
- switch (have_drive_kind) {
- case WindowsPathKindDrive: {
- result = Slice<uint8_t>::alloc(max_size);
-
- memCopy(result, result_disk_designator);
- result_index += result_disk_designator.len;
- break;
- }
- case WindowsPathKindNetworkShare: {
- result = Slice<uint8_t>::alloc(max_size);
- SplitIterator it = memSplit(buf_to_slice(paths_ptr[first_index]), str("/\\"));
- Slice<uint8_t> server_name = SplitIterator_next(&it).value;
- Slice<uint8_t> other_name = SplitIterator_next(&it).value;
-
- result.ptr[result_index] = '\\';
- result_index += 1;
- result.ptr[result_index] = '\\';
- result_index += 1;
- memCopy(result.sliceFrom(result_index), server_name);
- result_index += server_name.len;
- result.ptr[result_index] = '\\';
- result_index += 1;
- memCopy(result.sliceFrom(result_index), other_name);
- result_index += other_name.len;
-
- result_disk_designator = result.slice(0, result_index);
- break;
- }
- case WindowsPathKindNone: {
- Buf cwd = BUF_INIT;
- int err;
- if ((err = os_get_cwd(&cwd))) {
- zig_panic("get cwd failed");
- }
- WindowsPath parsed_cwd = windowsParsePath(buf_to_slice(&cwd));
- result = Slice<uint8_t>::alloc(max_size + parsed_cwd.disk_designator.len + 1);
- memCopy(result, parsed_cwd.disk_designator);
- result_index += parsed_cwd.disk_designator.len;
- result_disk_designator = result.slice(0, parsed_cwd.disk_designator.len);
- if (parsed_cwd.kind == WindowsPathKindDrive) {
- result.ptr[0] = asciiUpper(result.ptr[0]);
- }
- have_drive_kind = parsed_cwd.kind;
- break;
- }
- }
- } else {
- // TODO call get cwd for the result_disk_designator instead of the global one
- Buf cwd = BUF_INIT;
- int err;
- if ((err = os_get_cwd(&cwd))) {
- zig_panic("get cwd failed");
- }
- result = Slice<uint8_t>::alloc(max_size + buf_len(&cwd) + 1);
-
- memCopy(result, buf_to_slice(&cwd));
- result_index += buf_len(&cwd);
- WindowsPath parsed_cwd = windowsParsePath(result.slice(0, result_index));
- result_disk_designator = parsed_cwd.disk_designator;
- if (parsed_cwd.kind == WindowsPathKindDrive) {
- result.ptr[0] = asciiUpper(result.ptr[0]);
- // Remove the trailing slash if present, eg. if the cwd is a root
- // directory.
- if (buf_ends_with_mem(&cwd, "\\", 1)) {
- result_index -= 1;
- }
- }
- have_drive_kind = parsed_cwd.kind;
- }
-
- // Now we know the disk designator to use, if any, and what kind it is. And our result
- // is big enough to append all the paths to.
- bool correct_disk_designator = true;
- for (size_t i = first_index; i < paths_len; i += 1) {
- Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
- WindowsPath parsed = windowsParsePath(p);
-
- if (parsed.kind != WindowsPathKindNone) {
- if (parsed.kind == have_drive_kind) {
- correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
- } else {
- continue;
- }
- }
- if (!correct_disk_designator) {
- continue;
- }
- SplitIterator it = memSplit(p.sliceFrom(parsed.disk_designator.len), str("/\\"));
- while (true) {
- Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
- if (!opt_component.is_some) break;
- Slice<uint8_t> component = opt_component.value;
- if (memEql(component, str("."))) {
- continue;
- } else if (memEql(component, str(".."))) {
- while (true) {
- if (result_index == 0 || result_index == result_disk_designator.len)
- break;
- result_index -= 1;
- if (result.ptr[result_index] == '\\' || result.ptr[result_index] == '/')
- break;
- }
- } else {
- result.ptr[result_index] = '\\';
- result_index += 1;
- memCopy(result.sliceFrom(result_index), component);
- result_index += component.len;
- }
- }
- }
-
- if (result_index == result_disk_designator.len) {
- result.ptr[result_index] = '\\';
- result_index += 1;
- }
-
- Buf return_value = BUF_INIT;
- buf_init_from_mem(&return_value, (char *)result.ptr, result_index);
- return return_value;
-}
-#endif
-
-#if defined(ZIG_OS_POSIX)
-// Ported from std/os/path.zig
-static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
- if (paths_len == 0) {
- Buf cwd = BUF_INIT;
- int err;
- if ((err = os_get_cwd(&cwd))) {
- zig_panic("get cwd failed");
- }
- return cwd;
- }
-
- size_t first_index = 0;
- bool have_abs = false;
- size_t max_size = 0;
- for (size_t i = 0; i < paths_len; i += 1) {
- Buf *p = paths_ptr[i];
- if (buf_ptr(p)[0] == '/') {
- first_index = i;
- have_abs = true;
- max_size = 0;
- }
- max_size += buf_len(p) + 1;
- }
-
- uint8_t *result_ptr;
- size_t result_len;
- size_t result_index = 0;
-
- if (have_abs) {
- result_len = max_size;
- result_ptr = heap::c_allocator.allocate_nonzero<uint8_t>(result_len);
- } else {
- Buf cwd = BUF_INIT;
- int err;
- if ((err = os_get_cwd(&cwd))) {
- zig_panic("get cwd failed");
- }
- result_len = max_size + buf_len(&cwd) + 1;
- result_ptr = heap::c_allocator.allocate_nonzero<uint8_t>(result_len);
- memcpy(result_ptr, buf_ptr(&cwd), buf_len(&cwd));
- result_index += buf_len(&cwd);
- }
-
- for (size_t i = first_index; i < paths_len; i += 1) {
- Buf *p = paths_ptr[i];
- SplitIterator it = memSplit(buf_to_slice(p), str("/"));
- while (true) {
- Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
- if (!opt_component.is_some) break;
- Slice<uint8_t> component = opt_component.value;
-
- if (memEql<uint8_t>(component, str("."))) {
- continue;
- } else if (memEql<uint8_t>(component, str(".."))) {
- while (true) {
- if (result_index == 0)
- break;
- result_index -= 1;
- if (result_ptr[result_index] == '/')
- break;
- }
- } else {
- result_ptr[result_index] = '/';
- result_index += 1;
- memcpy(result_ptr + result_index, component.ptr, component.len);
- result_index += component.len;
- }
- }
- }
-
- if (result_index == 0) {
- result_ptr[0] = '/';
- result_index += 1;
- }
-
- 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
-
-// Ported from std/os/path.zig
-Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
-#if defined(ZIG_OS_WINDOWS)
- return os_path_resolve_windows(paths_ptr, paths_len);
-#elif defined(ZIG_OS_POSIX)
- return os_path_resolve_posix(paths_ptr, paths_len);
-#else
-#error "missing os_path_resolve implementation"
-#endif
-}
-
-Error os_fetch_file(FILE *f, Buf *out_buf) {
- static const ssize_t buf_size = 0x2000;
- buf_resize(out_buf, buf_size);
- ssize_t actual_buf_len = 0;
-
- for (;;) {
- size_t amt_read = fread(buf_ptr(out_buf) + actual_buf_len, 1, buf_size, f);
- actual_buf_len += amt_read;
-
- if (amt_read != buf_size) {
- if (feof(f)) {
- buf_resize(out_buf, actual_buf_len);
- return ErrorNone;
- } else {
- return ErrorFileSystem;
- }
- }
-
- buf_resize(out_buf, actual_buf_len + buf_size);
- }
- zig_unreachable();
-}
-
-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));
- FILE *f = _wfopen(&path_space.data.items[0], L"wb");
-#else
- FILE *f = fopen(buf_ptr(full_path), "wb");
-#endif
- if (!f) {
- zig_panic("os_write_file failed for %s", buf_ptr(full_path));
- }
- size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f);
- if (amt_written != (size_t)buf_len(contents))
- zig_panic("write failed: %s", strerror(errno));
- if (fclose(f))
- zig_panic("close failed");
- return ErrorNone;
-}
-
-static Error copy_open_files(FILE *src_f, FILE *dest_f) {
- static const size_t buf_size = 2048;
- char buf[buf_size];
- for (;;) {
- size_t amt_read = fread(buf, 1, buf_size, src_f);
- if (amt_read != buf_size) {
- if (ferror(src_f)) {
- return ErrorFileSystem;
- }
- }
- size_t amt_written = fwrite(buf, 1, amt_read, dest_f);
- if (amt_written != amt_read) {
- return ErrorFileSystem;
- }
- if (feof(src_f)) {
- return ErrorNone;
- }
- }
-}
-
-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));
- FILE *src_f = _wfopen(&src_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;
- }
- }
-#if defined(ZIG_OS_WINDOWS)
- PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
- FILE *dest_f = _wfopen(&dest_path_space.data.items[0], L"wb");
-#else
- FILE *dest_f = fopen(buf_ptr(dest_path), "wb");
-#endif
- if (!dest_f) {
- int err = errno;
- if (err == ENOENT) {
- fclose(src_f);
- return ErrorFileNotFound;
- } else if (err == EACCES || err == EPERM) {
- fclose(src_f);
- return ErrorAccess;
- } else {
- fclose(src_f);
- return ErrorFileSystem;
- }
- }
- Error err = copy_open_files(src_f, dest_f);
- fclose(src_f);
- fclose(dest_f);
- return err;
-}
-
-Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
- FILE *f = _wfopen(&path_space.data.items[0], L"rb");
-#else
- FILE *f = fopen(buf_ptr(full_path), "rb");
-#endif
- if (!f) {
- switch (errno) {
- case EACCES:
- return ErrorAccess;
- case EINTR:
- return ErrorInterrupted;
- case EINVAL:
- return ErrorInvalidFilename;
- case ENFILE:
- case ENOMEM:
- return ErrorSystemResources;
- case ENOENT:
- return ErrorFileNotFound;
- default:
- return ErrorFileSystem;
- }
- }
- Error result = os_fetch_file(f, out_contents);
- fclose(f);
- return result;
-}
-
-Error os_get_cwd(Buf *out_cwd) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space;
- if (GetCurrentDirectoryW(PATH_MAX_WIDE, &path_space.data.items[0]) == 0) {
- zig_panic("GetCurrentDirectory failed");
- }
- utf16le_ptr_to_utf8(out_cwd, &path_space.data.items[0]);
- return ErrorNone;
-#elif defined(ZIG_OS_POSIX)
- char buf[PATH_MAX];
- char *res = getcwd(buf, PATH_MAX);
- if (res == nullptr) {
- zig_panic("unable to get cwd: %s", strerror(errno));
- }
- buf_init_from_str(out_cwd, res);
- return ErrorNone;
-#else
-#error "missing os_get_cwd implementation"
-#endif
-}
-
-#if defined(ZIG_OS_WINDOWS)
-#define is_wprefix(s, prefix) \
- (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
-static bool is_stderr_cyg_pty(void) {
- HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
- if (stderr_handle == INVALID_HANDLE_VALUE)
- return false;
-
- const int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
- FILE_NAME_INFO *nameinfo;
- WCHAR *p = NULL;
-
- // Cygwin/msys's pty is a pipe.
- if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) {
- return 0;
- }
- nameinfo = reinterpret_cast<FILE_NAME_INFO *>(heap::c_allocator.allocate<char>(size));
- if (nameinfo == NULL) {
- return 0;
- }
- // Check the name of the pipe:
- // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'
- if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) {
- nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
- p = nameinfo->FileName;
- if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
- p += 8;
- } else if (is_wprefix(p, L"\\msys-")) { /* MSYS and MSYS2 */
- p += 6;
- } else {
- p = NULL;
- }
- if (p != NULL) {
- while (*p && isxdigit(*p)) /* Skip 16-digit hexadecimal. */
- ++p;
- if (is_wprefix(p, L"-pty")) {
- p += 4;
- } else {
- p = NULL;
- }
- }
- if (p != NULL) {
- while (*p && isdigit(*p)) /* Skip pty number. */
- ++p;
- if (is_wprefix(p, L"-from-master")) {
- //p += 12;
- } else if (is_wprefix(p, L"-to-master")) {
- //p += 10;
- } else {
- p = NULL;
- }
- }
- }
- heap::c_allocator.deallocate(reinterpret_cast<char *>(nameinfo), size);
- return (p != NULL);
-}
-#endif
-
-bool os_stderr_supports_color(void) {
- if (getenv("NO_COLOR") != NULL) return false;
-#if defined(ZIG_OS_WINDOWS)
- return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty();
-#elif defined(ZIG_OS_POSIX)
- return isatty(STDERR_FILENO) != 0;
-#else
-#error "missing os_stderr_supports_color implementation"
-#endif
-}
-
-Error os_rename(Buf *src_path, Buf *dest_path) {
- if (buf_eql_buf(src_path, dest_path)) {
- return ErrorNone;
- }
-#if defined(ZIG_OS_WINDOWS)
- PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
- PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
- if (!MoveFileExW(&src_path_space.data.items[0], &dest_path_space.data.items[0], MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
- return ErrorFileSystem;
- }
-#else
- if (rename(buf_ptr(src_path), buf_ptr(dest_path)) == -1) {
- return ErrorFileSystem;
- }
-#endif
- return ErrorNone;
-}
-
-OsTimeStamp os_timestamp_monotonic(void) {
- OsTimeStamp result;
-#if defined(ZIG_OS_WINDOWS)
- uint64_t counts;
- QueryPerformanceCounter((LARGE_INTEGER*)&counts);
- result.sec = counts / windows_perf_freq;
- result.nsec = (counts % windows_perf_freq) * 1000000000u / windows_perf_freq;
-#elif defined(__MACH__)
- mach_timespec_t mts;
-
- kern_return_t err = clock_get_time(macos_monotonic_clock, &mts);
- assert(!err);
-
- result.sec = mts.tv_sec;
- result.nsec = mts.tv_nsec;
-#else
- struct timespec tms;
- clock_gettime(CLOCK_MONOTONIC, &tms);
-
- result.sec = tms.tv_sec;
- result.nsec = tms.tv_nsec;
-#endif
- return result;
-}
-
-Error os_make_path(Buf *path) {
- Buf resolved_path = os_path_resolve(&path, 1);
-
- size_t end_index = buf_len(&resolved_path);
- Error err;
- while (true) {
- if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {
- if (err == ErrorPathAlreadyExists) {
- if (end_index == buf_len(&resolved_path))
- return ErrorNone;
- } else if (err == ErrorFileNotFound) {
- // march end_index backward until next path component
- while (true) {
- end_index -= 1;
- if (os_is_sep(buf_ptr(&resolved_path)[end_index]))
- break;
- }
- continue;
- } else {
- return err;
- }
- }
- if (end_index == buf_len(&resolved_path))
- return ErrorNone;
- // march end_index forward until next path component
- while (true) {
- end_index += 1;
- if (end_index == buf_len(&resolved_path) || os_is_sep(buf_ptr(&resolved_path)[end_index]))
- break;
- }
- }
- return ErrorNone;
-}
-
-Error os_make_dir(Buf *path) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(path));
-
- if (!CreateDirectoryW(&path_space.data.items[0], NULL)) {
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- return ErrorPathAlreadyExists;
- if (GetLastError() == ERROR_PATH_NOT_FOUND)
- return ErrorFileNotFound;
- if (GetLastError() == ERROR_ACCESS_DENIED)
- return ErrorAccess;
- return ErrorUnexpected;
- }
- return ErrorNone;
-#else
- if (mkdir(buf_ptr(path), 0755) == -1) {
- if (errno == EEXIST)
- return ErrorPathAlreadyExists;
- if (errno == ENOENT)
- return ErrorFileNotFound;
- if (errno == EACCES)
- return ErrorAccess;
- return ErrorUnexpected;
- }
- return ErrorNone;
-#endif
-}
-
-
-int os_init(void) {
-#if defined(ZIG_OS_WINDOWS)
- _setmode(fileno(stdout), _O_BINARY);
- _setmode(fileno(stderr), _O_BINARY);
- if (!QueryPerformanceFrequency((LARGE_INTEGER*)&windows_perf_freq)) {
- return ErrorSystemResources;
- }
-#elif defined(__MACH__)
- host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &macos_monotonic_clock);
- host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &macos_calendar_clock);
-#endif
- return 0;
-}
-
-#define VT_RED "\x1b[31;1m"
-#define VT_GREEN "\x1b[32;1m"
-#define VT_CYAN "\x1b[36;1m"
-#define VT_WHITE "\x1b[37;1m"
-#define VT_BOLD "\x1b[0;1m"
-#define VT_RESET "\x1b[0m"
-
-static void set_color_posix(TermColor color) {
- switch (color) {
- case TermColorRed:
- fprintf(stderr, VT_RED);
- break;
- case TermColorGreen:
- fprintf(stderr, VT_GREEN);
- break;
- case TermColorCyan:
- fprintf(stderr, VT_CYAN);
- break;
- case TermColorWhite:
- fprintf(stderr, VT_WHITE);
- break;
- case TermColorBold:
- fprintf(stderr, VT_BOLD);
- break;
- case TermColorReset:
- fprintf(stderr, VT_RESET);
- break;
- }
-}
-
-
-#if defined(ZIG_OS_WINDOWS)
-bool got_orig_console_attrs = false;
-WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
-#endif
-
-void os_stderr_set_color(TermColor color) {
-#if defined(ZIG_OS_WINDOWS)
- if (is_stderr_cyg_pty()) {
- set_color_posix(color);
- return;
- }
- HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
- if (stderr_handle == INVALID_HANDLE_VALUE)
- zig_panic("unable to get stderr handle");
- fflush(stderr);
-
- if (!got_orig_console_attrs) {
- got_orig_console_attrs = true;
- CONSOLE_SCREEN_BUFFER_INFO info;
- if (GetConsoleScreenBufferInfo(stderr_handle, &info)) {
- original_console_attributes = info.wAttributes;
- }
- }
-
- switch (color) {
- case TermColorRed:
- SetConsoleTextAttribute(stderr_handle, FOREGROUND_RED|FOREGROUND_INTENSITY);
- break;
- case TermColorGreen:
- SetConsoleTextAttribute(stderr_handle, FOREGROUND_GREEN|FOREGROUND_INTENSITY);
- break;
- case TermColorCyan:
- SetConsoleTextAttribute(stderr_handle, FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
- break;
- case TermColorWhite:
- case TermColorBold:
- SetConsoleTextAttribute(stderr_handle,
- FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
- break;
- case TermColorReset:
- SetConsoleTextAttribute(stderr_handle, original_console_attributes);
- break;
- }
-#else
- set_color_posix(color);
-#endif
-}
-
-#if defined(ZIG_OS_WINDOWS)
-// Ported from std/unicode.zig
-struct Utf16LeIterator {
- uint8_t *bytes;
- size_t i;
-};
-
-// Ported from std/unicode.zig
-static Utf16LeIterator Utf16LeIterator_init(WCHAR *ptr) {
- return {(uint8_t*)ptr, 0};
-}
-
-// Ported from std/unicode.zig
-static Optional<uint32_t> Utf16LeIterator_nextCodepoint(Utf16LeIterator *it) {
- if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0)
- return {};
- uint32_t c0 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
- if ((c0 & ~((uint32_t)0x03ff)) == 0xd800) {
- // surrogate pair
- it->i += 2;
- assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0);
- uint32_t c1 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
- assert((c1 & ~((uint32_t)0x03ff)) == 0xdc00);
- it->i += 2;
- return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)));
- } else {
- assert((c0 & ~((uint32_t)0x03ff)) != 0xdc00);
- it->i += 2;
- return Optional<uint32_t>::some(c0);
- }
-}
-
-// Ported from std/unicode.zig
-static uint8_t utf8CodepointSequenceLength(uint32_t c) {
- if (c < 0x80) return 1;
- if (c < 0x800) return 2;
- if (c < 0x10000) return 3;
- if (c < 0x110000) return 4;
- zig_unreachable();
-}
-
-// Ported from std.unicode.utf8ByteSequenceLength
-static uint8_t utf8ByteSequenceLength(uint8_t first_byte) {
- if (first_byte < 0b10000000) return 1;
- if ((first_byte & 0b11100000) == 0b11000000) return 2;
- if ((first_byte & 0b11110000) == 0b11100000) return 3;
- if ((first_byte & 0b11111000) == 0b11110000) return 4;
- zig_unreachable();
-}
-
-// Ported from std/unicode.zig
-static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
- size_t length = utf8CodepointSequenceLength(c);
- assert(out.len >= length);
- switch (length) {
- // The pattern for each is the same
- // - Increasing the initial shift by 6 each time
- // - Each time after the first shorten the shifted
- // value to a max of 0b111111 (63)
- case 1:
- out.ptr[0] = c; // Can just do 0 + codepoint for initial range
- break;
- case 2:
- out.ptr[0] = 0b11000000 | (c >> 6);
- out.ptr[1] = 0b10000000 | (c & 0b111111);
- break;
- case 3:
- assert(!(0xd800 <= c && c <= 0xdfff));
- out.ptr[0] = 0b11100000 | (c >> 12);
- out.ptr[1] = 0b10000000 | ((c >> 6) & 0b111111);
- out.ptr[2] = 0b10000000 | (c & 0b111111);
- break;
- case 4:
- out.ptr[0] = 0b11110000 | (c >> 18);
- out.ptr[1] = 0b10000000 | ((c >> 12) & 0b111111);
- out.ptr[2] = 0b10000000 | ((c >> 6) & 0b111111);
- out.ptr[3] = 0b10000000 | (c & 0b111111);
- break;
- default:
- zig_unreachable();
- }
- return length;
-}
-
-// Ported from std.unicode.utf8Decode2
-static uint32_t utf8Decode2(Slice<uint8_t> bytes) {
- assert(bytes.len == 2);
- assert((bytes.at(0) & 0b11100000) == 0b11000000);
-
- uint32_t value = bytes.at(0) & 0b00011111;
- assert((bytes.at(1) & 0b11000000) == 0b10000000);
- value <<= 6;
- value |= bytes.at(1) & 0b00111111;
-
- assert(value >= 0x80);
- return value;
-}
-
-// Ported from std.unicode.utf8Decode3
-static uint32_t utf8Decode3(Slice<uint8_t> bytes) {
- assert(bytes.len == 3);
- assert((bytes.at(0) & 0b11110000) == 0b11100000);
-
- uint32_t value = bytes.at(0) & 0b00001111;
- assert((bytes.at(1) & 0b11000000) == 0b10000000);
- value <<= 6;
- value |= bytes.at(1) & 0b00111111;
-
- assert((bytes.at(2) & 0b11000000) == 0b10000000);
- value <<= 6;
- value |= bytes.at(2) & 0b00111111;
-
- assert(value >= 0x80);
- assert(value < 0xd800 || value > 0xdfff);
- return value;
-}
-
-// Ported from std.unicode.utf8Decode4
-static uint32_t utf8Decode4(Slice<uint8_t> bytes) {
- assert(bytes.len == 4);
- assert((bytes.at(0) & 0b11111000) == 0b11110000);
-
- uint32_t value = bytes.at(0) & 0b00000111;
- assert((bytes.at(1) & 0b11000000) == 0b10000000);
- value <<= 6;
- value |= bytes.at(1) & 0b00111111;
-
- assert((bytes.at(2) & 0b11000000) == 0b10000000);
- value <<= 6;
- value |= bytes.at(2) & 0b00111111;
-
- assert((bytes.at(3) & 0b11000000) == 0b10000000);
- value <<= 6;
- value |= bytes.at(3) & 0b00111111;
-
- assert(value >= 0x10000 && value <= 0x10FFFF);
- return value;
-}
-
-// Ported from std.unicode.utf8Decode
-static uint32_t utf8Decode(Slice<uint8_t> bytes) {
- switch (bytes.len) {
- case 1:
- return bytes.at(0);
- break;
- case 2:
- return utf8Decode2(bytes);
- break;
- case 3:
- return utf8Decode3(bytes);
- break;
- case 4:
- return utf8Decode4(bytes);
- break;
- default:
- zig_unreachable();
- }
-}
-// Ported from std.unicode.utf16leToUtf8Alloc
-static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
- // optimistically guess that it will all be ascii.
- buf_resize(out, 0);
- size_t out_index = 0;
- Utf16LeIterator it = Utf16LeIterator_init(utf16le);
- for (;;) {
- Optional<uint32_t> opt_codepoint = Utf16LeIterator_nextCodepoint(&it);
- if (!opt_codepoint.is_some) break;
- uint32_t codepoint = opt_codepoint.value;
-
- size_t utf8_len = utf8CodepointSequenceLength(codepoint);
- buf_resize(out, buf_len(out) + utf8_len);
- utf8Encode(codepoint, {(uint8_t*)buf_ptr(out)+out_index, buf_len(out)-out_index});
- out_index += utf8_len;
- }
-}
-
-// Ported from std.unicode.utf8ToUtf16Le
-static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8) {
- size_t dest_i = 0;
- size_t src_i = 0;
- while (src_i < utf8.len) {
- uint8_t n = utf8ByteSequenceLength(utf8.at(src_i));
- size_t next_src_i = src_i + n;
- uint32_t codepoint = utf8Decode(utf8.slice(src_i, next_src_i));
- if (codepoint < 0x10000) {
- utf16_le[dest_i] = codepoint;
- dest_i += 1;
- } else {
- WCHAR high = ((codepoint - 0x10000) >> 10) + 0xD800;
- WCHAR low = (codepoint & 0x3FF) + 0xDC00;
- utf16_le[dest_i] = high;
- utf16_le[dest_i + 1] = low;
- dest_i += 2;
- }
- src_i = next_src_i;
- }
- return dest_i;
-}
-
-// Ported from std.os.windows.sliceToPrefixedFileW
-PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {
- PathSpace path_space;
- for (size_t idx = 0; idx < path.len; idx++) {
- assert(path.ptr[idx] != '*' && path.ptr[idx] != '?' && path.ptr[idx] != '"' &&
- path.ptr[idx] != '<' && path.ptr[idx] != '>' && path.ptr[idx] != '|');
- }
-
- size_t start_index;
- if (memStartsWith(path, str("\\?")) || !isAbsoluteWindows(path)) {
- start_index = 0;
- } else {
- static WCHAR prefix[4] = { u'\\', u'?', u'?', u'\\' };
- memCopy(path_space.data.slice(), Slice<WCHAR> { prefix, 4 });
- start_index = 4;
- }
-
- path_space.len = start_index + utf8_to_utf16le(path_space.data.slice().sliceFrom(start_index).ptr, path);
- assert(path_space.len <= path_space.data.len);
-
- Slice<WCHAR> path_slice = path_space.data.slice().slice(0, path_space.len);
- for (size_t elem_idx = 0; elem_idx < path_slice.len; elem_idx += 1) {
- if (path_slice.at(elem_idx) == '/') {
- path_slice.at(elem_idx) = '\\';
- }
- }
-
- path_space.data.items[path_space.len] = 0;
- return path_space;
-}
-#endif