nativity/lib/std/os.nat
2023-11-30 17:33:45 -06:00

130 lines
3.8 KiB
Plaintext

const std = #import("std");
const Allocator = std.Allocator;
const current = #import("builtin").os;
const system = switch (current) {
.linux => linux,
.macos => macos,
.windows => windows,
};
const write = fn (file_descriptor: FileDescriptor, bytes_ptr: [&]const u8, bytes_len: usize) ssize {
switch (current) {
.linux => return #syscall(1, file_descriptor, #cast(bytes_ptr), bytes_len),
.macos => return macos.write(file_descriptor, #cast(bytes_ptr), bytes_len),
.windows => {
var written_bytes: u32 = 0;
if (windows.WriteFile(file_descriptor, bytes_ptr, bytes_len, written_bytes.&, false) != 0) {
return written_bytes;
} else {
unreachable;
}
},
}
}
const FileDescriptor = system.FileDescriptor;
const print = fn(bytes_ptr: [&]const u8, bytes_len: usize) void {
const file_descriptor = switch (current) {
.linux, .macos => 2,
.windows => windows.GetStdHandle(windows.STD_OUTPUT_HANDLE),
};
_ = write(file_descriptor, bytes_ptr, bytes_len);
}
const exit = fn(exit_code: s32) noreturn {
switch (current) {
.linux => _ = #syscall(231, exit_code),
.macos => macos.exit(exit_code),
.windows => windows.ExitProcess(exit_code),
}
unreachable;
}
const ProtectionFlags = struct(u32){
read: bool,
write: bool,
execute: bool,
};
const MapFlags = struct(u32){
reserve: bool,
commit: bool,
};
const allocate_virtual_memory = fn(address: ?[&]u8, length: usize, general_protection_flags: ProtectionFlags, general_map_flags: MapFlags) ?[&]u8 {
const protection_flags = system.get_protection_flags(flags = general_protection_flags);
const map_flags = system.get_map_flags(flags = general_map_flags);
switch (current) {
.linux => {
if (linux.unwrapSyscall(syscall_result = linux.mmap(address, length, protection_flags, map_flags, fd = -1, offset = 0))) |result_address| {
const pointer: [&]u8 = #cast(result_address);
return pointer;
} else {
return null;
}
},
else => #error("OS not supported"),
}
}
const free_virtual_memory = fn(bytes_ptr: [&]const u8, bytes_len: usize) bool {
switch (current) {
.linux => {
if (linux.unwrapSyscall(syscall_result = linux.munmap(bytes_ptr, bytes_len))) |result| {
return result == 0;
} else {
return false;
}
},
else => #error("OS not supported"),
}
}
const readlink = fn(file_path: [&:0]const u8, buffer: []u8) ?[]u8 {
switch (current) {
.linux => {
const raw_result = linux.readlink(file_path, bytes_ptr = buffer.ptr, bytes_len = buffer.len);
if (linux.unwrapSyscall(syscall_result = raw_result)) |byte_count| {
const bytes = buffer[0..byte_count];
return bytes;
} else {
return null;
}
},
else => #error("OS not supported"),
}
}
const max_path_byte_count = switch (current) {
.linux => 0x1000,
else => #error("OS not supported"),
};
const currentExecutablePath = fn(allocator: &Allocator) ?[]u8 {
switch (current) {
.linux => {
var buffer: [max_path_byte_count]u8 = undefined;
if (readlink(file_path = "/proc/self/exe", buffer = buffer.&)) |bytes| {
if (allocator.duplicateBytes(bytes)) |result| {
return result;
} else {
return null;
}
} else {
return null;
}
},
else => #error("OS not supported"),
}
}
const linux = #import("os/linux.nat");
const macos = #import("os/macos.nat");
const windows = #import("os/windows.nat");