diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig index 3d5736d37b..71dd4705f8 100644 --- a/std/c/freebsd.zig +++ b/std/c/freebsd.zig @@ -6,4 +6,4 @@ pub const _errno = __error; pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; -pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int; +pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; diff --git a/std/c/linux.zig b/std/c/linux.zig index a69f3c18b2..b3b3cbdde7 100644 --- a/std/c/linux.zig +++ b/std/c/linux.zig @@ -7,7 +7,7 @@ pub const _errno = __errno_location; pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize)); -pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int; +pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int; pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int; pub extern "c" fn epoll_ctl(epfd: fd_t, op: c_uint, fd: fd_t, event: ?*epoll_event) c_int; diff --git a/std/io.zig b/std/io.zig index 3a8da3ed3e..dcf2ec5f61 100644 --- a/std/io.zig +++ b/std/io.zig @@ -146,7 +146,7 @@ pub fn InStream(comptime ReadError: type) type { /// Same as `readFull` but end of stream returns `error.EndOfStream`. pub fn readNoEof(self: *Self, buf: []u8) !void { - const amt_read = try self.read(buf); + const amt_read = try self.readFull(buf); if (amt_read < buf.len) return error.EndOfStream; } diff --git a/std/os.zig b/std/os.zig index 0a826c26c2..0291282a77 100644 --- a/std/os.zig +++ b/std/os.zig @@ -99,19 +99,30 @@ pub const GetRandomError = OpenError; /// When linking against libc, this calls the /// appropriate OS-specific library call. Otherwise it uses the zig standard /// library implementation. -pub fn getrandom(buf: []u8) GetRandomError!void { +pub fn getrandom(buffer: []u8) GetRandomError!void { if (windows.is_the_target) { - return windows.RtlGenRandom(buf); + return windows.RtlGenRandom(buffer); } - if (linux.is_the_target) { - while (true) { - const err = if (std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok) blk: { - break :blk errno(std.c.getrandom(buf.ptr, buf.len, 0)); + if (linux.is_the_target or freebsd.is_the_target) { + var buf = buffer; + const use_c = !linux.is_the_target or + std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok; + + while (buf.len != 0) { + var err: u16 = undefined; + + const num_read = if (use_c) blk: { + const rc = std.c.getrandom(buf.ptr, buf.len, 0); + err = std.c.getErrno(rc); + break :blk @bitCast(usize, rc); } else blk: { - break :blk linux.getErrno(linux.getrandom(buf.ptr, buf.len, 0)); + const rc = linux.getrandom(buf.ptr, buf.len, 0); + err = linux.getErrno(rc); + break :blk rc; }; + switch (err) { - 0 => return, + 0 => buf = buf[num_read..], EINVAL => unreachable, EFAULT => unreachable, EINTR => continue, @@ -119,27 +130,15 @@ pub fn getrandom(buf: []u8) GetRandomError!void { else => return unexpectedErrno(err), } } - } - if (freebsd.is_the_target) { - while (true) { - const err = std.c.getErrno(std.c.getrandom(buf.ptr, buf.len, 0)); - - switch (err) { - 0 => return, - EINVAL => unreachable, - EFAULT => unreachable, - EINTR => continue, - else => return unexpectedErrno(err), - } - } + return; } if (wasi.is_the_target) { - switch (wasi.random_get(buf.ptr, buf.len)) { + switch (wasi.random_get(buffer.ptr, buffer.len)) { 0 => return, else => |err| return unexpectedErrno(err), } } - return getRandomBytesDevURandom(buf); + return getRandomBytesDevURandom(buffer); } fn getRandomBytesDevURandom(buf: []u8) !void {