progress toward tests passing on MacOS

This commit is contained in:
Andrew Kelley 2017-08-27 00:11:09 -04:00
parent 105a09e1d6
commit 29a418c9d5
15 changed files with 441 additions and 380 deletions

View File

@ -297,7 +297,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/net.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/child_process.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/darwin.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/darwin_x86_64.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/errno.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/index.zig" DESTINATION "${ZIG_STD_DEST}/os")
install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux.zig" DESTINATION "${ZIG_STD_DEST}/os")

View File

@ -2891,6 +2891,10 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
}
static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) {
if (src_use_node->data.use.resolution == TldResolutionUnresolved) {
preview_use_decl(g, src_use_node);
}
IrInstruction *use_target_value = src_use_node->data.use.value;
if (use_target_value->value.type->id == TypeTableEntryIdInvalid) {
dst_use_node->owner->any_imports_failed = true;

View File

@ -709,10 +709,6 @@ int os_delete_file(Buf *path) {
}
}
void os_init(void) {
srand((unsigned)time(NULL));
}
int os_rename(Buf *src_path, Buf *dest_path) {
if (rename(buf_ptr(src_path), buf_ptr(dest_path)) == -1) {
return ErrorFileSystem;
@ -805,7 +801,8 @@ int os_make_dir(Buf *path) {
#endif
}
int zig_os_init(void) {
int os_init(void) {
srand((unsigned)time(NULL));
#if defined(ZIG_OS_WINDOWS)
unsigned __int64 frequency;
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) {

View File

@ -27,8 +27,8 @@ struct Termination {
int code;
};
int os_init(void);
void os_init(void);
void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);
int os_exec_process(const char *exe, ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout);

View File

@ -1,4 +1,32 @@
pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize) -> c_int;
fn extern "c" __error() -> &c_int;
extern "c" fn __error() -> &c_int;
pub const _errno = __error;
/// Renamed to Stat to not conflict with the stat function.
pub const Stat = extern struct {
dev: u32,
mode: u16,
nlink: u16,
ino: u64,
uid: u32,
gid: u32,
rdev: u64,
atim: timespec,
mtim: timespec,
ctim: timespec,
size: u64,
blocks: u64,
blksize: u32,
flags: u32,
gen: u32,
lspare: i32,
qspare: [2]u64,
};
pub const timespec = extern struct {
tv_sec: isize,
tv_nsec: isize,
};

View File

@ -8,7 +8,32 @@ pub use switch(builtin.os) {
Os.darwin, Os.macosx, Os.ios => @import("darwin.zig"),
else => empty_import,
};
const empty_import = @import("../empty.zig");
pub extern "c" fn abort() -> noreturn;
const empty_import = @import("../empty.zig");
pub extern "c" fn exit(code: c_int) -> noreturn;
pub extern "c" fn isatty(fd: c_int) -> c_int;
pub extern "c" fn close(fd: c_int) -> c_int;
pub extern "c" fn fstat(fd: c_int, buf: &stat) -> c_int;
pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) -> isize;
pub extern "c" fn open(path: &const u8, oflag: c_int, ...) -> c_int;
pub extern "c" fn raise(sig: c_int) -> c_int;
pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) -> isize;
pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) -> c_int;
pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) -> c_int;
pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int,
fd: c_int, offset: isize) -> ?&c_void;
pub extern "c" fn munmap(addr: &c_void, len: usize) -> c_int;
pub extern "c" fn unlink(path: &const u8) -> c_int;
pub extern "c" fn getcwd(buf: &u8, size: usize) -> ?&u8;
pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) -> c_int;
pub extern "c" fn fork() -> c_int;
pub extern "c" fn pipe(fds: &c_int) -> c_int;
pub extern "c" fn mkdir(path: &const u8, mode: c_uint) -> c_int;
pub extern "c" fn symlink(existing: &const u8, new: &const u8) -> c_int;
pub extern "c" fn rename(old: &const u8, new: &const u8) -> c_int;
pub extern "c" fn chdir(path: &const u8) -> c_int;
pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8,
envp: &const ?&const u8) -> c_int;
pub extern "c" fn dup(fd: c_int) -> c_int;
pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) -> c_int;

View File

@ -2,10 +2,11 @@ const builtin = @import("builtin");
const Os = builtin.Os;
const system = switch(builtin.os) {
Os.linux => @import("os/linux.zig"),
Os.darwin => @import("os/darwin.zig"),
Os.darwin, Os.macosx, Os.ios => @import("os/darwin.zig"),
Os.windows => @import("os/windows/index.zig"),
else => @compileError("Unsupported OS"),
};
const c = @import("c/index.zig");
const errno = @import("os/errno.zig");
const math = @import("math/index.zig");
@ -180,7 +181,11 @@ pub const OutStream = struct {
pub fn isTty(self: &OutStream) -> %bool {
if (is_posix) {
return system.isatty(self.fd);
if (builtin.link_libc) {
return c.isatty(self.fd) == 0;
} else {
return system.isatty(self.fd);
}
} else if (is_windows) {
return os.windowsIsTty(%return self.getHandle());
} else {
@ -417,7 +422,11 @@ pub const InStream = struct {
pub fn isTty(self: &InStream) -> %bool {
if (is_posix) {
return system.isatty(self.fd);
if (builtin.link_libc) {
return c.isatty(self.fd) == 0;
} else {
return system.isatty(self.fd);
}
} else if (is_windows) {
return os.windowsIsTty(%return self.getHandle());
} else {

View File

@ -229,42 +229,15 @@ fn forkChildErrReport(fd: i32, err: error) -> noreturn {
}
const ErrInt = @IntType(false, @sizeOf(error) * 8);
fn writeIntFd(fd: i32, value: ErrInt) -> %void {
var bytes: [@sizeOf(ErrInt)]u8 = undefined;
mem.writeInt(bytes[0..], value, true);
var index: usize = 0;
while (index < bytes.len) {
const amt_written = posix.write(fd, &bytes[index], bytes.len - index);
const err = posix.getErrno(amt_written);
if (err > 0) {
switch (err) {
errno.EINTR => continue,
errno.EINVAL => unreachable,
else => return error.SystemResources,
}
}
index += amt_written;
}
os.posixWrite(fd, bytes[0..]) %% return error.SystemResources;
}
fn readIntFd(fd: i32) -> %ErrInt {
var bytes: [@sizeOf(ErrInt)]u8 = undefined;
var index: usize = 0;
while (index < bytes.len) {
const amt_written = posix.read(fd, &bytes[index], bytes.len - index);
const err = posix.getErrno(amt_written);
if (err > 0) {
switch (err) {
errno.EINTR => continue,
errno.EINVAL => unreachable,
else => return error.SystemResources,
}
}
index += amt_written;
}
os.posixRead(fd, bytes[0..]) %% return error.SystemResources;
return mem.readInt(bytes[0..], ErrInt, true);
}

View File

@ -1,18 +1,41 @@
const builtin = @import("builtin");
const arch = switch (builtin.arch) {
builtin.Arch.x86_64 => @import("darwin_x86_64.zig"),
else => @compileError("unsupported arch"),
};
const errno = @import("errno.zig");
const c = @import("../c/index.zig");
const assert = @import("../debug.zig").assert;
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;
pub const STDERR_FILENO = 2;
pub const PROT_NONE = 0x00; /// [MC2] no permissions
pub const PROT_READ = 0x01; /// [MC2] pages can be read
pub const PROT_WRITE = 0x02; /// [MC2] pages can be written
pub const PROT_EXEC = 0x04; /// [MC2] pages can be executed
pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
pub const MAP_FILE = 0x0000; /// map from file (default)
pub const MAP_FIXED = 0x0010; /// interpret addr exactly
pub const MAP_HASSEMAPHORE = 0x0200; /// region may contain semaphores
pub const MAP_PRIVATE = 0x0002; /// changes are private
pub const MAP_SHARED = 0x0001; /// share changes
pub const MAP_NOCACHE = 0x0400; /// don't cache pages for this mapping
pub const MAP_NORESERVE = 0x0040; /// don't reserve needed swap area
pub const MAP_FAILED = @maxValue(usize);
pub const O_LARGEFILE = 0x0000;
pub const O_RDONLY = 0x0000;
pub const O_RDONLY = 0x0000; /// open for reading only
pub const O_WRONLY = 0x0001; /// open for writing only
pub const O_RDWR = 0x0002; /// open for reading and writing
pub const O_NONBLOCK = 0x0004; /// do not block on open or for data to become available
pub const O_APPEND = 0x0008; /// append on each write
pub const O_CREAT = 0x0200; /// create file if it does not exist
pub const O_TRUNC = 0x0400; /// truncate size to 0
pub const O_EXCL = 0x0800; /// error if O_CREAT and the file exists
pub const O_SHLOCK = 0x0010; /// atomically obtain a shared lock
pub const O_EXLOCK = 0x0020; /// atomically obtain an exclusive lock
pub const O_NOFOLLOW = 0x0100; /// do not follow symlinks
pub const O_SYMLINK = 0x200000; /// allow open of symlinks
pub const O_EVTONLY = 0x8000; /// descriptor requested for event notifications only
pub const O_CLOEXEC = 0x1000000; /// mark as close-on-exec
pub const SEEK_SET = 0x0;
pub const SEEK_CUR = 0x1;
@ -53,64 +76,133 @@ pub const SIGPWR = 30;
pub const SIGSYS = 31;
pub const SIGUNUSED = SIGSYS;
pub fn exit(status: usize) -> noreturn {
_ = arch.syscall1(arch.SYS_exit, status);
unreachable
}
fn wstatus(x: i32) -> i32 { x & 0o177 }
const wstopped = 0o177;
pub fn WEXITSTATUS(x: i32) -> i32 { x >> 8 }
pub fn WTERMSIG(x: i32) -> i32 { wstatus(x) }
pub fn WSTOPSIG(x: i32) -> i32 { x >> 8 }
pub fn WIFEXITED(x: i32) -> bool { wstatus(x) == 0 }
pub fn WIFSTOPPED(x: i32) -> bool { wstatus(x) == wstopped and WSTOPSIG(x) != 0x13 }
pub fn WIFSIGNALED(x: i32) -> bool { wstatus(x) != wstopped and wstatus(x) != 0 }
/// Get the errno from a syscall return value, or 0 for no error.
pub fn getErrno(r: usize) -> usize {
const signed_r = *@ptrCast(&const isize, &r);
const signed_r = @bitCast(isize, r);
if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0
}
pub fn write(fd: i32, buf: &const u8, count: usize) -> usize {
arch.syscall3(arch.SYS_write, usize(fd), usize(buf), count)
}
pub fn close(fd: i32) -> usize {
arch.syscall1(arch.SYS_close, usize(fd))
errnoWrap(c.close(fd))
}
pub fn open(path: &const u8, flags: usize, perm: usize) -> usize {
arch.syscall3(arch.SYS_open, usize(path), flags, perm)
pub fn abort() -> noreturn {
c.abort()
}
pub fn read(fd: i32, buf: &u8, count: usize) -> usize {
arch.syscall3(arch.SYS_read, usize(fd), usize(buf), count)
pub fn exit(code: i32) -> noreturn {
c.exit(code)
}
pub fn lseek(fd: i32, offset: usize, ref_pos: usize) -> usize {
arch.syscall3(arch.SYS_lseek, usize(fd), offset, ref_pos)
pub fn isatty(fd: i32) -> bool {
c.isatty(fd) == 0
}
pub const stat = arch.stat;
pub const timespec = arch.timespec;
pub fn fstat(fd: i32, stat_buf: &stat) -> usize {
arch.syscall2(arch.SYS_fstat, usize(fd), usize(stat_buf))
pub fn fstat(fd: i32, buf: &c.stat) -> usize {
errnoWrap(c.fstat(fd, buf))
}
error Unexpected;
pub fn getrandom(buf: &u8, count: usize) -> usize {
const rr = open_c(c"/dev/urandom", O_LARGEFILE | O_RDONLY, 0);
if(getErrno(rr) > 0) return rr;
var fd: i32 = i32(rr);
const readRes = read(fd, buf, count);
readRes
pub fn lseek(fd: i32, offset: isize, whence: c_int) -> usize {
errnoWrap(c.lseek(fd, buf, whence))
}
pub fn raise(sig: i32) -> i32 {
// TODO investigate whether we need to block signals before calling kill
// like we do in the linux version of raise
//var set: sigset_t = undefined;
//blockAppSignals(&set);
const pid = i32(arch.syscall0(arch.SYS_getpid));
const ret = i32(arch.syscall2(arch.SYS_kill, usize(pid), usize(sig)));
//restoreSignals(&set);
return ret;
pub fn open(path: &const u8, flags: u32, mode: usize) -> usize {
errnoWrap(c.open(path, @bitCast(c_int, flags), mode))
}
pub fn raise(sig: i32) -> usize {
errnoWrap(c.raise(sig))
}
pub fn read(fd: i32, buf: &u8, nbyte: usize) -> usize {
errnoWrap(c.read(fd, @ptrCast(&c_void, buf), nbyte))
}
pub fn stat(noalias path: &const u8, noalias buf: &stat) -> usize {
errnoWrap(c.stat(path, buf))
}
pub fn write(fd: i32, buf: &const u8, nbyte: usize) -> usize {
errnoWrap(c.write(fd, @ptrCast(&const c_void, buf), nbyte))
}
pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32,
offset: isize) -> usize
{
const ptr_result = c.mmap(@ptrCast(&c_void, address), length,
@bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset);
const isize_result = @bitCast(isize, @ptrToInt(ptr_result));
return errnoWrap(isize_result);
}
pub fn munmap(address: &u8, length: usize) -> usize {
errnoWrap(c.munmap(@ptrCast(&c_void, address), length))
}
pub fn unlink(path: &const u8) -> usize {
errnoWrap(c.unlink(path))
}
pub fn getcwd(buf: &u8, size: usize) -> usize {
if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(*c._errno())) else 0
}
pub fn waitpid(pid: i32, status: &i32, options: u32) -> usize {
comptime assert(i32.bit_count == c_int.bit_count);
errnoWrap(c.waitpid(pid, @ptrCast(&c_int, status), @bitCast(c_int, options)))
}
pub fn fork() -> usize {
errnoWrap(c.fork())
}
pub fn pipe(fds: &[2]i32) -> usize {
comptime assert(i32.bit_count == c_int.bit_count);
errnoWrap(c.pipe(@ptrCast(&c_int, &(*fds)[0])))
}
pub fn mkdir(path: &const u8, mode: u32) -> usize {
errnoWrap(c.mkdir(path, mode))
}
pub fn symlink(existing: &const u8, new: &const u8) -> usize {
errnoWrap(c.symlink(existing, new))
}
pub fn rename(old: &const u8, new: &const u8) -> usize {
errnoWrap(c.rename(old, new))
}
pub fn chdir(path: &const u8) -> usize {
errnoWrap(c.chdir(path))
}
pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8)
-> usize
{
errnoWrap(c.execve(path, argv, envp))
}
pub fn dup2(old: i32, new: i32) -> usize {
errnoWrap(c.dup2(old, new))
}
/// Takes the return value from a syscall and formats it back in the way
/// that the kernel represents it to libc. Errno was a mistake, let's make
/// it go away forever.
fn errnoWrap(value: isize) -> usize {
@bitCast(usize, if (value == -1) {
-isize(*c._errno())
} else {
value
})
}

View File

@ -1,87 +0,0 @@
pub const SYSCALL_CLASS_SHIFT = 24;
pub const SYSCALL_CLASS_MASK = 0xFF << SYSCALL_CLASS_SHIFT;
// pub const SYSCALL_NUMBER_MASK = ~SYSCALL_CLASS_MASK; // ~ modifier not supported yet
pub const SYSCALL_CLASS_NONE = 0; // Invalid
pub const SYSCALL_CLASS_MACH = 1; // Mach
pub const SYSCALL_CLASS_UNIX = 2; // Unix/BSD
pub const SYSCALL_CLASS_MDEP = 3; // Machine-dependent
pub const SYSCALL_CLASS_DIAG = 4; // Diagnostics
// TODO: use the above constants to create the below values
pub const SYS_exit = 0x2000001;
pub const SYS_read = 0x2000003;
pub const SYS_write = 0x2000004;
pub const SYS_open = 0x2000005;
pub const SYS_close = 0x2000006;
pub const SYS_kill = 0x2000025;
pub const SYS_getpid = 0x2000030;
pub const SYS_fstat = 0x20000BD;
pub const SYS_lseek = 0x20000C7;
pub inline fn syscall0(number: usize) -> usize {
asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [number] "{rax}" (number)
: "rcx", "r11")
}
pub inline fn syscall1(number: usize, arg1: usize) -> usize {
asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [number] "{rax}" (number),
[arg1] "{rdi}" (arg1)
: "rcx", "r11")
}
pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize {
asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [number] "{rax}" (number),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2)
: "rcx", "r11")
}
pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {
asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [number] "{rax}" (number),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3)
: "rcx", "r11")
}
pub const stat = extern struct {
dev: u32,
mode: u16,
nlink: u16,
ino: u64,
uid: u32,
gid: u32,
rdev: u64,
atim: timespec,
mtim: timespec,
ctim: timespec,
size: u64,
blocks: u64,
blksize: u32,
flags: u32,
gen: u32,
lspare: i32,
qspare: [2]u64,
};
pub const timespec = extern struct {
tv_sec: isize,
tv_nsec: isize,
};

View File

@ -1,146 +1,146 @@
pub const EPERM = 1; // Operation not permitted
pub const ENOENT = 2; // No such file or directory
pub const ESRCH = 3; // No such process
pub const EINTR = 4; // Interrupted system call
pub const EIO = 5; // I/O error
pub const ENXIO = 6; // No such device or address
pub const E2BIG = 7; // Arg list too long
pub const ENOEXEC = 8; // Exec format error
pub const EBADF = 9; // Bad file number
pub const ECHILD = 10; // No child processes
pub const EAGAIN = 11; // Try again
pub const ENOMEM = 12; // Out of memory
pub const EACCES = 13; // Permission denied
pub const EFAULT = 14; // Bad address
pub const ENOTBLK = 15; // Block device required
pub const EBUSY = 16; // Device or resource busy
pub const EEXIST = 17; // File exists
pub const EXDEV = 18; // Cross-device link
pub const ENODEV = 19; // No such device
pub const ENOTDIR = 20; // Not a directory
pub const EISDIR = 21; // Is a directory
pub const EINVAL = 22; // Invalid argument
pub const ENFILE = 23; // File table overflow
pub const EMFILE = 24; // Too many open files
pub const ENOTTY = 25; // Not a typewriter
pub const ETXTBSY = 26; // Text file busy
pub const EFBIG = 27; // File too large
pub const ENOSPC = 28; // No space left on device
pub const ESPIPE = 29; // Illegal seek
pub const EROFS = 30; // Read-only file system
pub const EMLINK = 31; // Too many links
pub const EPIPE = 32; // Broken pipe
pub const EDOM = 33; // Math argument out of domain of func
pub const ERANGE = 34; // Math result not representable
pub const EDEADLK = 35; // Resource deadlock would occur
pub const ENAMETOOLONG = 36; // File name too long
pub const ENOLCK = 37; // No record locks available
pub const ENOSYS = 38; // Function not implemented
pub const ENOTEMPTY = 39; // Directory not empty
pub const ELOOP = 40; // Too many symbolic links encountered
pub const EWOULDBLOCK = EAGAIN; // Operation would block
pub const ENOMSG = 42; // No message of desired type
pub const EIDRM = 43; // Identifier removed
pub const ECHRNG = 44; // Channel number out of range
pub const EL2NSYNC = 45; // Level 2 not synchronized
pub const EL3HLT = 46; // Level 3 halted
pub const EL3RST = 47; // Level 3 reset
pub const ELNRNG = 48; // Link number out of range
pub const EUNATCH = 49; // Protocol driver not attached
pub const ENOCSI = 50; // No CSI structure available
pub const EL2HLT = 51; // Level 2 halted
pub const EBADE = 52; // Invalid exchange
pub const EBADR = 53; // Invalid request descriptor
pub const EXFULL = 54; // Exchange full
pub const ENOANO = 55; // No anode
pub const EBADRQC = 56; // Invalid request code
pub const EBADSLT = 57; // Invalid slot
pub const EPERM = 1; /// Operation not permitted
pub const ENOENT = 2; /// No such file or directory
pub const ESRCH = 3; /// No such process
pub const EINTR = 4; /// Interrupted system call
pub const EIO = 5; /// I/O error
pub const ENXIO = 6; /// No such device or address
pub const E2BIG = 7; /// Arg list too long
pub const ENOEXEC = 8; /// Exec format error
pub const EBADF = 9; /// Bad file number
pub const ECHILD = 10; /// No child processes
pub const EAGAIN = 11; /// Try again
pub const ENOMEM = 12; /// Out of memory
pub const EACCES = 13; /// Permission denied
pub const EFAULT = 14; /// Bad address
pub const ENOTBLK = 15; /// Block device required
pub const EBUSY = 16; /// Device or resource busy
pub const EEXIST = 17; /// File exists
pub const EXDEV = 18; /// Cross-device link
pub const ENODEV = 19; /// No such device
pub const ENOTDIR = 20; /// Not a directory
pub const EISDIR = 21; /// Is a directory
pub const EINVAL = 22; /// Invalid argument
pub const ENFILE = 23; /// File table overflow
pub const EMFILE = 24; /// Too many open files
pub const ENOTTY = 25; /// Not a typewriter
pub const ETXTBSY = 26; /// Text file busy
pub const EFBIG = 27; /// File too large
pub const ENOSPC = 28; /// No space left on device
pub const ESPIPE = 29; /// Illegal seek
pub const EROFS = 30; /// Read-only file system
pub const EMLINK = 31; /// Too many links
pub const EPIPE = 32; /// Broken pipe
pub const EDOM = 33; /// Math argument out of domain of func
pub const ERANGE = 34; /// Math result not representable
pub const EDEADLK = 35; /// Resource deadlock would occur
pub const ENAMETOOLONG = 36; /// File name too long
pub const ENOLCK = 37; /// No record locks available
pub const ENOSYS = 38; /// Function not implemented
pub const ENOTEMPTY = 39; /// Directory not empty
pub const ELOOP = 40; /// Too many symbolic links encountered
pub const EWOULDBLOCK = EAGAIN; /// Operation would block
pub const ENOMSG = 42; /// No message of desired type
pub const EIDRM = 43; /// Identifier removed
pub const ECHRNG = 44; /// Channel number out of range
pub const EL2NSYNC = 45; /// Level 2 not synchronized
pub const EL3HLT = 46; /// Level 3 halted
pub const EL3RST = 47; /// Level 3 reset
pub const ELNRNG = 48; /// Link number out of range
pub const EUNATCH = 49; /// Protocol driver not attached
pub const ENOCSI = 50; /// No CSI structure available
pub const EL2HLT = 51; /// Level 2 halted
pub const EBADE = 52; /// Invalid exchange
pub const EBADR = 53; /// Invalid request descriptor
pub const EXFULL = 54; /// Exchange full
pub const ENOANO = 55; /// No anode
pub const EBADRQC = 56; /// Invalid request code
pub const EBADSLT = 57; /// Invalid slot
pub const EBFONT = 59; // Bad font file format
pub const ENOSTR = 60; // Device not a stream
pub const ENODATA = 61; // No data available
pub const ETIME = 62; // Timer expired
pub const ENOSR = 63; // Out of streams resources
pub const ENONET = 64; // Machine is not on the network
pub const ENOPKG = 65; // Package not installed
pub const EREMOTE = 66; // Object is remote
pub const ENOLINK = 67; // Link has been severed
pub const EADV = 68; // Advertise error
pub const ESRMNT = 69; // Srmount error
pub const ECOMM = 70; // Communication error on send
pub const EPROTO = 71; // Protocol error
pub const EMULTIHOP = 72; // Multihop attempted
pub const EDOTDOT = 73; // RFS specific error
pub const EBADMSG = 74; // Not a data message
pub const EOVERFLOW = 75; // Value too large for defined data type
pub const ENOTUNIQ = 76; // Name not unique on network
pub const EBADFD = 77; // File descriptor in bad state
pub const EREMCHG = 78; // Remote address changed
pub const ELIBACC = 79; // Can not access a needed shared library
pub const ELIBBAD = 80; // Accessing a corrupted shared library
pub const ELIBSCN = 81; // .lib section in a.out corrupted
pub const ELIBMAX = 82; // Attempting to link in too many shared libraries
pub const ELIBEXEC = 83; // Cannot exec a shared library directly
pub const EILSEQ = 84; // Illegal byte sequence
pub const ERESTART = 85; // Interrupted system call should be restarted
pub const ESTRPIPE = 86; // Streams pipe error
pub const EUSERS = 87; // Too many users
pub const ENOTSOCK = 88; // Socket operation on non-socket
pub const EDESTADDRREQ = 89; // Destination address required
pub const EMSGSIZE = 90; // Message too long
pub const EPROTOTYPE = 91; // Protocol wrong type for socket
pub const ENOPROTOOPT = 92; // Protocol not available
pub const EPROTONOSUPPORT = 93; // Protocol not supported
pub const ESOCKTNOSUPPORT = 94; // Socket type not supported
pub const EOPNOTSUPP = 95; // Operation not supported on transport endpoint
pub const EPFNOSUPPORT = 96; // Protocol family not supported
pub const EAFNOSUPPORT = 97; // Address family not supported by protocol
pub const EADDRINUSE = 98; // Address already in use
pub const EADDRNOTAVAIL = 99; // Cannot assign requested address
pub const ENETDOWN = 100; // Network is down
pub const ENETUNREACH = 101; // Network is unreachable
pub const ENETRESET = 102; // Network dropped connection because of reset
pub const ECONNABORTED = 103; // Software caused connection abort
pub const ECONNRESET = 104; // Connection reset by peer
pub const ENOBUFS = 105; // No buffer space available
pub const EISCONN = 106; // Transport endpoint is already connected
pub const ENOTCONN = 107; // Transport endpoint is not connected
pub const ESHUTDOWN = 108; // Cannot send after transport endpoint shutdown
pub const ETOOMANYREFS = 109; // Too many references: cannot splice
pub const ETIMEDOUT = 110; // Connection timed out
pub const ECONNREFUSED = 111; // Connection refused
pub const EHOSTDOWN = 112; // Host is down
pub const EHOSTUNREACH = 113; // No route to host
pub const EALREADY = 114; // Operation already in progress
pub const EINPROGRESS = 115; // Operation now in progress
pub const ESTALE = 116; // Stale NFS file handle
pub const EUCLEAN = 117; // Structure needs cleaning
pub const ENOTNAM = 118; // Not a XENIX named type file
pub const ENAVAIL = 119; // No XENIX semaphores available
pub const EISNAM = 120; // Is a named type file
pub const EREMOTEIO = 121; // Remote I/O error
pub const EDQUOT = 122; // Quota exceeded
pub const EBFONT = 59; /// Bad font file format
pub const ENOSTR = 60; /// Device not a stream
pub const ENODATA = 61; /// No data available
pub const ETIME = 62; /// Timer expired
pub const ENOSR = 63; /// Out of streams resources
pub const ENONET = 64; /// Machine is not on the network
pub const ENOPKG = 65; /// Package not installed
pub const EREMOTE = 66; /// Object is remote
pub const ENOLINK = 67; /// Link has been severed
pub const EADV = 68; /// Advertise error
pub const ESRMNT = 69; /// Srmount error
pub const ECOMM = 70; /// Communication error on send
pub const EPROTO = 71; /// Protocol error
pub const EMULTIHOP = 72; /// Multihop attempted
pub const EDOTDOT = 73; /// RFS specific error
pub const EBADMSG = 74; /// Not a data message
pub const EOVERFLOW = 75; /// Value too large for defined data type
pub const ENOTUNIQ = 76; /// Name not unique on network
pub const EBADFD = 77; /// File descriptor in bad state
pub const EREMCHG = 78; /// Remote address changed
pub const ELIBACC = 79; /// Can not access a needed shared library
pub const ELIBBAD = 80; /// Accessing a corrupted shared library
pub const ELIBSCN = 81; /// .lib section in a.out corrupted
pub const ELIBMAX = 82; /// Attempting to link in too many shared libraries
pub const ELIBEXEC = 83; /// Cannot exec a shared library directly
pub const EILSEQ = 84; /// Illegal byte sequence
pub const ERESTART = 85; /// Interrupted system call should be restarted
pub const ESTRPIPE = 86; /// Streams pipe error
pub const EUSERS = 87; /// Too many users
pub const ENOTSOCK = 88; /// Socket operation on non-socket
pub const EDESTADDRREQ = 89; /// Destination address required
pub const EMSGSIZE = 90; /// Message too long
pub const EPROTOTYPE = 91; /// Protocol wrong type for socket
pub const ENOPROTOOPT = 92; /// Protocol not available
pub const EPROTONOSUPPORT = 93; /// Protocol not supported
pub const ESOCKTNOSUPPORT = 94; /// Socket type not supported
pub const EOPNOTSUPP = 95; /// Operation not supported on transport endpoint
pub const EPFNOSUPPORT = 96; /// Protocol family not supported
pub const EAFNOSUPPORT = 97; /// Address family not supported by protocol
pub const EADDRINUSE = 98; /// Address already in use
pub const EADDRNOTAVAIL = 99; /// Cannot assign requested address
pub const ENETDOWN = 100; /// Network is down
pub const ENETUNREACH = 101; /// Network is unreachable
pub const ENETRESET = 102; /// Network dropped connection because of reset
pub const ECONNABORTED = 103; /// Software caused connection abort
pub const ECONNRESET = 104; /// Connection reset by peer
pub const ENOBUFS = 105; /// No buffer space available
pub const EISCONN = 106; /// Transport endpoint is already connected
pub const ENOTCONN = 107; /// Transport endpoint is not connected
pub const ESHUTDOWN = 108; /// Cannot send after transport endpoint shutdown
pub const ETOOMANYREFS = 109; /// Too many references: cannot splice
pub const ETIMEDOUT = 110; /// Connection timed out
pub const ECONNREFUSED = 111; /// Connection refused
pub const EHOSTDOWN = 112; /// Host is down
pub const EHOSTUNREACH = 113; /// No route to host
pub const EALREADY = 114; /// Operation already in progress
pub const EINPROGRESS = 115; /// Operation now in progress
pub const ESTALE = 116; /// Stale NFS file handle
pub const EUCLEAN = 117; /// Structure needs cleaning
pub const ENOTNAM = 118; /// Not a XENIX named type file
pub const ENAVAIL = 119; /// No XENIX semaphores available
pub const EISNAM = 120; /// Is a named type file
pub const EREMOTEIO = 121; /// Remote I/O error
pub const EDQUOT = 122; /// Quota exceeded
pub const ENOMEDIUM = 123; // No medium found
pub const EMEDIUMTYPE = 124; // Wrong medium type
pub const ENOMEDIUM = 123; /// No medium found
pub const EMEDIUMTYPE = 124; /// Wrong medium type
// nameserver query return codes
pub const ENSROK = 0; // DNS server returned answer with no data
pub const ENSRNODATA = 160; // DNS server returned answer with no data
pub const ENSRFORMERR = 161; // DNS server claims query was misformatted
pub const ENSRSERVFAIL = 162; // DNS server returned general failure
pub const ENSRNOTFOUND = 163; // Domain name not found
pub const ENSRNOTIMP = 164; // DNS server does not implement requested operation
pub const ENSRREFUSED = 165; // DNS server refused query
pub const ENSRBADQUERY = 166; // Misformatted DNS query
pub const ENSRBADNAME = 167; // Misformatted domain name
pub const ENSRBADFAMILY = 168; // Unsupported address family
pub const ENSRBADRESP = 169; // Misformatted DNS reply
pub const ENSRCONNREFUSED = 170; // Could not contact DNS servers
pub const ENSRTIMEOUT = 171; // Timeout while contacting DNS servers
pub const ENSROF = 172; // End of file
pub const ENSRFILE = 173; // Error reading file
pub const ENSRNOMEM = 174; // Out of memory
pub const ENSRDESTRUCTION = 175; // Application terminated lookup
pub const ENSRQUERYDOMAINTOOLONG = 176; // Domain name is too long
pub const ENSRCNAMELOOP = 177; // Domain name is too long
pub const ENSROK = 0; /// DNS server returned answer with no data
pub const ENSRNODATA = 160; /// DNS server returned answer with no data
pub const ENSRFORMERR = 161; /// DNS server claims query was misformatted
pub const ENSRSERVFAIL = 162; /// DNS server returned general failure
pub const ENSRNOTFOUND = 163; /// Domain name not found
pub const ENSRNOTIMP = 164; /// DNS server does not implement requested operation
pub const ENSRREFUSED = 165; /// DNS server refused query
pub const ENSRBADQUERY = 166; /// Misformatted DNS query
pub const ENSRBADNAME = 167; /// Misformatted domain name
pub const ENSRBADFAMILY = 168; /// Unsupported address family
pub const ENSRBADRESP = 169; /// Misformatted DNS reply
pub const ENSRCONNREFUSED = 170; /// Could not contact DNS servers
pub const ENSRTIMEOUT = 171; /// Timeout while contacting DNS servers
pub const ENSROF = 172; /// End of file
pub const ENSRFILE = 173; /// Error reading file
pub const ENSRNOMEM = 174; /// Out of memory
pub const ENSRDESTRUCTION = 175; /// Application terminated lookup
pub const ENSRQUERYDOMAINTOOLONG = 176; /// Domain name is too long
pub const ENSRCNAMELOOP = 177; /// Domain name is too long

View File

@ -56,43 +56,40 @@ error WouldBlock;
/// appropriate OS-specific library call. Otherwise it uses the zig standard
/// library implementation.
pub fn getRandomBytes(buf: []u8) -> %void {
while (true) {
const err = switch (builtin.os) {
Os.linux => {
// TODO check libc version and potentially call c.getrandom.
// See #397
posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0))
},
Os.darwin, Os.macosx, Os.ios => {
if (builtin.link_libc) {
if (posix.getrandom(buf.ptr, buf.len) == -1) *c._errno() else 0
} else {
posix.getErrno(posix.getrandom(buf.ptr, buf.len))
switch (builtin.os) {
Os.linux => while (true) {
// TODO check libc version and potentially call c.getrandom.
// See #397
const err = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
if (err > 0) {
return switch (err) {
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.EINTR => continue,
else => error.Unexpected,
}
},
Os.windows => {
var hCryptProv: windows.HCRYPTPROV = undefined;
if (!windows.CryptAcquireContext(&hCryptProv, null, null, windows.PROV_RSA_FULL, 0)) {
return error.Unexpected;
}
defer _ = windows.CryptReleaseContext(hCryptProv, 0);
if (!windows.CryptGenRandom(hCryptProv, windows.DWORD(buf.len), buf.ptr)) {
return error.Unexpected;
}
return;
},
else => @compileError("Unsupported OS"),
};
if (err > 0) {
return switch (err) {
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.EINTR => continue,
else => error.Unexpected,
}
}
return;
return;
},
Os.darwin, Os.macosx, Os.ios => {
const fd = %return posixOpen("/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC,
0, null);
defer posixClose(fd);
%return posixRead(fd, buf);
},
Os.windows => {
var hCryptProv: windows.HCRYPTPROV = undefined;
if (!windows.CryptAcquireContext(&hCryptProv, null, null, windows.PROV_RSA_FULL, 0)) {
return error.Unexpected;
}
defer _ = windows.CryptReleaseContext(hCryptProv, 0);
if (!windows.CryptGenRandom(hCryptProv, windows.DWORD(buf.len), buf.ptr)) {
return error.Unexpected;
}
},
else => @compileError("Unsupported OS"),
}
}
@ -128,12 +125,34 @@ pub fn posixClose(fd: i32) {
}
}
/// Calls POSIX read, and keeps trying if it gets interrupted.
pub fn posixRead(fd: i32, buf: []u8) -> %void {
var index: usize = 0;
while (index < buf.len) {
const amt_written = posix.read(fd, &buf[index], buf.len - index);
const err = posix.getErrno(amt_written);
if (err > 0) {
return switch (err) {
errno.EINTR => continue,
errno.EINVAL, errno.EFAULT => unreachable,
errno.EAGAIN => error.WouldBlock,
errno.EBADF => error.FileClosed,
errno.EIO => error.InputOutput,
errno.EISDIR => error.IsDir,
errno.ENOBUFS, errno.ENOMEM => error.SystemResources,
else => return error.Unexpected,
}
}
index += amt_written;
}
}
error WouldBlock;
error FileClosed;
error DestinationAddressRequired;
error DiskQuota;
error FileTooBig;
error FileSystem;
error InputOutput;
error NoSpaceLeft;
error BrokenPipe;
error Unexpected;
@ -152,7 +171,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
errno.EDESTADDRREQ => error.DestinationAddressRequired,
errno.EDQUOT => error.DiskQuota,
errno.EFBIG => error.FileTooBig,
errno.EIO => error.FileSystem,
errno.EIO => error.InputOutput,
errno.ENOSPC => error.NoSpaceLeft,
errno.EPERM => error.AccessDenied,
errno.EPIPE => error.BrokenPipe,
@ -213,7 +232,7 @@ pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool {
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
/// Calls POSIX open, keeps trying if it gets interrupted, and translates
/// the return value into zig errors.
pub fn posixOpen(file_path: []const u8, flags: usize, perm: usize, allocator: ?&Allocator) -> %i32 {
pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Allocator) -> %i32 {
var stack_buf: [max_noalloc_path_len]u8 = undefined;
var path0: []u8 = undefined;
var need_free = false;

View File

@ -309,8 +309,8 @@ pub const TIOCGPKT = 0x80045438;
pub const TIOCGPTLCK = 0x80045439;
pub const TIOCGEXCL = 0x80045440;
fn unsigned(s: i32) -> u32 { *@ptrCast(&u32, &s) }
fn signed(s: u32) -> i32 { *@ptrCast(&i32, &s) }
fn unsigned(s: i32) -> u32 { @bitCast(u32, s) }
fn signed(s: u32) -> i32 { @bitCast(i32, s) }
pub fn WEXITSTATUS(s: i32) -> i32 { signed((unsigned(s) & 0xff00) >> 8) }
pub fn WTERMSIG(s: i32) -> i32 { signed(unsigned(s) & 0x7f) }
pub fn WSTOPSIG(s: i32) -> i32 { WEXITSTATUS(s) }
@ -328,7 +328,7 @@ pub const winsize = extern struct {
/// Get the errno from a syscall return value, or 0 for no error.
pub fn getErrno(r: usize) -> usize {
const signed_r = *@ptrCast(&const isize, &r);
const signed_r = @bitCast(isize, r);
if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0
}
@ -353,7 +353,7 @@ pub fn getcwd(buf: &u8, size: usize) -> usize {
}
pub fn getdents(fd: i32, dirp: &u8, count: usize) -> usize {
arch.syscall3(arch.SYS_getdents, usize(fd), @ptrToInt(dirp), usize(count))
arch.syscall3(arch.SYS_getdents, usize(fd), @ptrToInt(dirp), count)
}
pub fn isatty(fd: i32) -> bool {
@ -365,14 +365,15 @@ pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -
arch.syscall3(arch.SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len)
}
pub fn mkdir(path: &const u8, mode: usize) -> usize {
pub fn mkdir(path: &const u8, mode: u32) -> usize {
arch.syscall2(arch.SYS_mkdir, @ptrToInt(path), mode)
}
pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: usize)
pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize)
-> usize
{
arch.syscall6(arch.SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), offset)
arch.syscall6(arch.SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd),
@bitCast(usize, offset))
}
pub fn munmap(address: &u8, length: usize) -> usize {
@ -415,7 +416,7 @@ pub fn rename(old: &const u8, new: &const u8) -> usize {
arch.syscall2(arch.SYS_rename, @ptrToInt(old), @ptrToInt(new))
}
pub fn open(path: &const u8, flags: usize, perm: usize) -> usize {
pub fn open(path: &const u8, flags: u32, perm: usize) -> usize {
arch.syscall3(arch.SYS_open, @ptrToInt(path), flags, perm)
}
@ -431,12 +432,12 @@ pub fn close(fd: i32) -> usize {
arch.syscall1(arch.SYS_close, usize(fd))
}
pub fn lseek(fd: i32, offset: usize, ref_pos: usize) -> usize {
arch.syscall3(arch.SYS_lseek, usize(fd), offset, ref_pos)
pub fn lseek(fd: i32, offset: isize, ref_pos: usize) -> usize {
arch.syscall3(arch.SYS_lseek, usize(fd), @bitCast(usize, offset), ref_pos)
}
pub fn exit(status: i32) -> noreturn {
_ = arch.syscall1(arch.SYS_exit, usize(status));
_ = arch.syscall1(arch.SYS_exit, @bitCast(usize, isize(status)));
unreachable
}
@ -453,7 +454,7 @@ pub fn unlink(path: &const u8) -> usize {
}
pub fn waitpid(pid: i32, status: &i32, options: i32) -> usize {
arch.syscall4(arch.SYS_wait4, usize(pid), @ptrToInt(status), usize(options), 0)
arch.syscall4(arch.SYS_wait4, usize(pid), @ptrToInt(status), @bitCast(usize, isize(options)), 0)
}
const NSIG = 65;
@ -461,11 +462,11 @@ const sigset_t = [128]u8;
const all_mask = []u8 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
const app_mask = []u8 { 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, };
pub fn raise(sig: i32) -> i32 {
pub fn raise(sig: i32) -> usize {
var set: sigset_t = undefined;
blockAppSignals(&set);
const tid = i32(arch.syscall0(arch.SYS_gettid));
const ret = i32(arch.syscall2(arch.SYS_tkill, usize(tid), usize(sig)));
const ret = arch.syscall2(arch.SYS_tkill, usize(tid), usize(sig));
restoreSignals(&set);
return ret;
}
@ -630,9 +631,9 @@ pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags:
// return ifr.ifr_ifindex;
// }
pub const stat = arch.stat;
pub const Stat = arch.Stat;
pub const timespec = arch.timespec;
pub fn fstat(fd: i32, stat_buf: &stat) -> usize {
pub fn fstat(fd: i32, stat_buf: &Stat) -> usize {
arch.syscall2(arch.SYS_fstat, usize(fd), @ptrToInt(stat_buf))
}

View File

@ -454,7 +454,8 @@ pub const msghdr = extern struct {
msg_flags: i32,
};
pub const stat = extern struct {
/// Renamed to Stat to not conflict with the stat function.
pub const Stat = extern struct {
dev: u64,
ino: u64,
nlink: usize,

View File

@ -2,7 +2,7 @@ const config = @import("builtin");
const assert = @import("std").debug.assert;
comptime {
if (config.arch == config.Arch.x86_64) {
if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
asm volatile (
\\.globl aoeu;
\\.type aoeu, @function;
@ -12,7 +12,7 @@ comptime {
}
test "module level assembly" {
if (config.arch == config.Arch.x86_64) {
if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
assert(aoeu() == 1234);
}
}