commit 816565dd077f561a46a9f31d9ecce32f152f9553 (tree)
parent 867501d9d2f757f99af59b1904b251aa63262e23
Author: Andrew Kelley <andrew@ziglang.org>
Date: Sun, 4 Jan 2026 12:14:03 -0800
std: move entropy to Io
Diffstat:
9 files changed, 263 insertions(+), 306 deletions(-)
diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig
@@ -21,7 +21,6 @@ pub const dependencies = @import("@dependencies");
pub const std_options: std.Options = .{
.side_channels_mitigations = .none,
.http_disable_tls = true,
- .crypto_fork_safety = false,
};
pub fn main(init: process.Init.Minimal) !void {
diff --git a/lib/std/Io.zig b/lib/std/Io.zig
@@ -731,6 +731,8 @@ pub const VTable = struct {
now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,
sleep: *const fn (?*anyopaque, Timeout) SleepError!void,
+ random: *const fn (?*anyopaque, buffer: []u8) RandomError!void,
+
netListenIp: *const fn (?*anyopaque, address: net.IpAddress, net.IpAddress.ListenOptions) net.IpAddress.ListenError!net.Server,
netAccept: *const fn (?*anyopaque, server: net.Socket.Handle) net.Server.AcceptError!net.Stream,
netBindIp: *const fn (?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.BindOptions) net.IpAddress.BindError!net.Socket,
@@ -2242,3 +2244,10 @@ pub fn tryLockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancel
pub fn unlockStderr(io: Io) void {
return io.vtable.unlockStderr(io.userdata);
}
+
+pub const RandomError = error{EntropyUnavailable} || Cancelable;
+
+/// Threadsafe.
+pub fn random(io: Io, buffer: []u8) RandomError!void {
+ return io.vtable.random(io.userdata, buffer);
+}
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
@@ -65,6 +65,7 @@ argv0: Argv0,
environ: Environ,
null_file: NullFile = .{},
+dev_urandom_fd: dev_urandom_fd_t,
pub const Argv0 = switch (native_os) {
.openbsd, .haiku => struct {
@@ -585,6 +586,10 @@ const Thread = struct {
/// Always released when `Status.cancelation` is set to `.parked`.
futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn,
+ random_buffer: [128]u8,
+ /// How many bytes of `random_buffer` are filled.
+ random_i: usize,
+
const Handle = Handle: {
if (std.Thread.use_pthreads) break :Handle std.c.pthread_t;
if (builtin.target.os.tag == .windows) break :Handle windows.HANDLE;
@@ -1285,6 +1290,9 @@ pub fn deinit(t: *Threaded) void {
if (have_sig_pipe) posix.sigaction(.PIPE, &t.old_sig_pipe, null);
}
t.null_file.deinit();
+ if (use_dev_urandom and t.dev_urandom_fd != -1) {
+ posix.close(t.dev_urandom_fd);
+ }
t.* = undefined;
}
@@ -1466,6 +1474,8 @@ pub fn io(t: *Threaded) Io {
.now = now,
.sleep = sleep,
+ .random = random,
+
.netListenIp = switch (native_os) {
.windows => netListenIpWindows,
else => netListenIpPosix,
@@ -1614,6 +1624,8 @@ pub fn ioBasic(t: *Threaded) Io {
.now = now,
.sleep = sleep,
+ .random = random,
+
.netListenIp = netListenIpUnavailable,
.netListenUnix = netListenUnixUnavailable,
.netAccept = netAcceptUnavailable,
@@ -1704,6 +1716,26 @@ const linux_copy_file_range_use_c = std.c.versionCheck(if (builtin.abi.isAndroid
});
const linux_copy_file_range_sys = if (linux_copy_file_range_use_c) std.c else std.os.linux;
+const statx_use_c = std.c.versionCheck(if (builtin.abi.isAndroid())
+ .{ .major = 30, .minor = 0, .patch = 0 }
+else
+ .{ .major = 2, .minor = 28, .patch = 0 });
+
+const getrandom_use_libc = @TypeOf(posix.system.getrandom) != void and (native_os != .linux or
+ std.c.versionCheck(if (builtin.abi.isAndroid()) .{
+ .major = 28,
+ .minor = 0,
+ .patch = 0,
+ } else .{
+ .major = 2,
+ .minor = 25,
+ .patch = 0,
+ }));
+
+const use_dev_urandom = getrandom_use_libc and native_os == .linux;
+
+const dev_urandom_fd_t = if (use_dev_urandom) posix.fd_t else void;
+
fn async(
userdata: ?*anyopaque,
result: []u8,
@@ -2538,11 +2570,7 @@ fn dirStatFileLinux(
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
const linux = std.os.linux;
- const use_c = std.c.versionCheck(if (builtin.abi.isAndroid())
- .{ .major = 30, .minor = 0, .patch = 0 }
- else
- .{ .major = 2, .minor = 28, .patch = 0 });
- const sys = if (use_c) std.c else std.os.linux;
+ const sys = if (statx_use_c) std.c else std.os.linux;
var path_buffer: [posix.PATH_MAX]u8 = undefined;
const sub_path_posix = try pathToPosix(sub_path, &path_buffer);
@@ -2778,11 +2806,7 @@ fn fileStatLinux(userdata: ?*anyopaque, file: File) File.StatError!File.Stat {
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
const linux = std.os.linux;
- const use_c = std.c.versionCheck(if (builtin.abi.isAndroid())
- .{ .major = 30, .minor = 0, .patch = 0 }
- else
- .{ .major = 2, .minor = 28, .patch = 0 });
- const sys = if (use_c) std.c else std.os.linux;
+ const sys = if (statx_use_c) std.c else std.os.linux;
const syscall: Syscall = try .start();
while (true) {
@@ -6318,11 +6342,6 @@ fn fchmodatFallback(
mode: posix.mode_t,
) Dir.SetFilePermissionsError!void {
comptime assert(native_os == .linux);
- const use_c = std.c.versionCheck(if (builtin.abi.isAndroid())
- .{ .major = 30, .minor = 0, .patch = 0 }
- else
- .{ .major = 2, .minor = 28, .patch = 0 });
- const sys = if (use_c) std.c else std.os.linux;
// Fallback to changing permissions using procfs:
//
@@ -6369,6 +6388,7 @@ fn fchmodatFallback(
defer posix.close(path_fd);
const path_mode = mode: {
+ const sys = if (statx_use_c) std.c else std.os.linux;
const syscall: Syscall = try .start();
while (true) {
var statx = std.mem.zeroes(std.os.linux.Statx);
@@ -14935,6 +14955,213 @@ pub fn environString(t: *Threaded, comptime name: []const u8) ?[:0]const u8 {
return @field(t.environ.string, name);
}
+fn random(userdata: ?*anyopaque, buffer: []u8) Io.RandomError!void {
+ const t: *Threaded = @ptrCast(@alignCast(userdata));
+
+ if (is_windows) {
+ // Call RtlGenRandom() instead of CryptGetRandom() on Windows
+ // https://github.com/rust-lang-nursery/rand/issues/111
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=504270
+ const max_read_size: windows.ULONG = std.math.maxInt(windows.ULONG);
+ var i: usize = 0;
+ while (i < buffer.len) {
+ const buf = buffer[i..];
+ const request_n: windows.ULONG = @min(buf.len, max_read_size);
+ const syscall: Syscall = try .start();
+ const result = windows.advapi32.RtlGenRandom(buf.ptr, request_n);
+ syscall.finish();
+ if (result == 0) {
+ // `RtlGenRandom` has been observed to fail in situations where
+ // the system is under heavy load. Unfortunately, it does not
+ // call `SetLastError`, so it is not possible to get more
+ // specific error information; it could actually be due to an
+ // out-of-memory condition, for example.
+ return error.EntropyUnavailable;
+ }
+ i += request_n;
+ }
+ return;
+ }
+
+ if (builtin.link_libc and @TypeOf(posix.system.arc4random_buf) != void) {
+ posix.system.arc4random_buf(buffer.ptr, buffer.len);
+ return;
+ }
+
+ if (native_os == .wasi) {
+ const syscall: Syscall = try .start();
+ while (true) switch (std.os.wasi.random_get(buffer.ptr, buffer.len)) {
+ .SUCCESS => return syscall.finish(),
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => return syscall.fail(error.EntropyUnavailable),
+ };
+ }
+
+ if (@TypeOf(posix.system.getrandom) != void) {
+ const getrandom = if (getrandom_use_libc) std.c.getrandom else std.os.linux.getrandom;
+ var i: usize = 0;
+ const syscall: Syscall = try .start();
+ while (i < buffer.len) {
+ const buf = buffer[i..];
+ const rc = getrandom(buf.ptr, buf.len, 0);
+ switch (posix.errno(rc)) {
+ .SUCCESS => {
+ syscall.finish();
+ const n: usize = @intCast(rc);
+ i += n;
+ continue;
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => return syscall.fail(error.EntropyUnavailable),
+ }
+ }
+ return;
+ }
+
+ if (native_os == .emscripten) {
+ const err = posix.errno(std.c.getentropy(buffer.ptr, buffer.len));
+ switch (err) {
+ .SUCCESS => return,
+ else => return error.EntropyUnavailable,
+ }
+ }
+
+ const urandom_fd = try getRandomFd(t);
+
+ var i: usize = 0;
+ while (buffer.len - i != 0) {
+ const syscall: Syscall = try .start();
+ const rc = posix.system.read(urandom_fd, buffer[i..].ptr, buffer.len - i);
+ switch (posix.errno(rc)) {
+ .SUCCESS => {
+ syscall.finish();
+ const n: usize = @intCast(rc);
+ if (n == 0) {
+ if (buffer.len - i != 0) {
+ return error.EntropyUnavailable;
+ } else {
+ return;
+ }
+ }
+ i += n;
+ continue;
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => return syscall.fail(error.EntropyUnavailable),
+ }
+ }
+}
+
+fn getRandomFd(t: *Threaded) posix.fd_t {
+ {
+ t.mutex.lock();
+ defer t.mutex.unlock();
+
+ if (t.dev_urandom_fd == -2) return error.EntropyUnavailable;
+ if (t.dev_urandom_fd != -1) return t.dev_urandom_fd;
+ }
+
+ const fd: posix.fd_t = fd: {
+ const syscall: Syscall = try .start();
+ while (true) {
+ const rc = openat_sym(posix.AT.FDCWD, "/dev/urandom", .{
+ .ACCMODE = .RDONLY,
+ .CLOEXEC = true,
+ }, 0);
+ switch (posix.errno(rc)) {
+ .SUCCESS => {
+ syscall.finish();
+ break :fd @intCast(rc);
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => {
+ syscall.endSyscall();
+ t.dev_urandom_fd = -2;
+ return error.EntropyUnavailable;
+ },
+ }
+ }
+ };
+ errdefer posix.close(fd);
+
+ switch (native_os) {
+ .linux => {
+ const sys = if (statx_use_c) std.c else std.os.linux;
+ const syscall: Syscall = try .start();
+ while (true) {
+ var statx = std.mem.zeroes(std.os.linux.Statx);
+ switch (sys.errno(sys.statx(fd, "", std.os.linux.AT.EMPTY_PATH, .{ .TYPE = true }, &statx))) {
+ .SUCCESS => {
+ syscall.finish();
+ if (!statx.mask.TYPE) return error.Unexpected;
+ t.mutex.lock(); // Another thread might have won the race.
+ defer t.mutex.unlock();
+ if (t.dev_urandom_fd >= 0) {
+ posix.close(fd);
+ return t.dev_urandom_fd;
+ } else if (!posix.S.ISCHR(statx.mode)) {
+ t.dev_urandom_fd = -2;
+ return error.EntropyUnavailable;
+ } else {
+ t.dev_urandom_fd = fd;
+ return fd;
+ }
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => {
+ t.dev_urandom_fd = -2;
+ return error.EntropyUnavailable;
+ },
+ }
+ }
+ },
+ else => {
+ const syscall: Syscall = try .start();
+ while (true) {
+ var stat = std.mem.zeroes(posix.Stat);
+ switch (posix.errno(fstat_sym(fd, &stat))) {
+ .SUCCESS => {
+ syscall.finish();
+ if (t.dev_urandom_fd >= 0) {
+ posix.close(fd);
+ return t.dev_urandom_fd;
+ } else if (!posix.S.ISCHR(stat.mode)) {
+ t.dev_urandom_fd = -2;
+ return error.EntropyUnavailable;
+ } else {
+ t.dev_urandom_fd = fd;
+ return fd;
+ }
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => {
+ t.dev_urandom_fd = -2;
+ return error.EntropyUnavailable;
+ },
+ }
+ }
+ },
+ }
+}
+
test {
_ = @import("Threaded/test.zig");
}
diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig
@@ -564,3 +564,14 @@ test "tasks spawned in group after Group.cancel are canceled" {
try io.sleep(.fromMilliseconds(10), .awake); // let that first sleep start up
try group.concurrent(io, global.waitThenSpawn, .{ io, &group });
}
+
+test "CSPRNG" {
+ const io = testing.io;
+
+ var random = io.random();
+
+ const a = random.int(u64);
+ const b = random.int(u64);
+ const c = random.int(u64);
+ try std.testing.expect(a ^ b ^ c != 0);
+}
diff --git a/lib/std/Random.zig b/lib/std/Random.zig
@@ -1,15 +1,13 @@
//! The engines provided here should be initialized from an external source.
-//! For a thread-local cryptographically secure pseudo random number generator,
-//! use `std.crypto.random`.
//! Be sure to use a CSPRNG when required, otherwise using a normal PRNG will
//! be faster and use substantially less stack space.
+const Random = @This();
const std = @import("std.zig");
const math = std.math;
const mem = std.mem;
const assert = std.debug.assert;
const maxInt = std.math.maxInt;
-const Random = @This();
/// Fast unbiased random numbers.
pub const DefaultPrng = Xoshiro256;
diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig
@@ -235,9 +235,6 @@ pub const nacl = struct {
/// Finite-field arithmetic.
pub const ff = @import("crypto/ff.zig");
-/// This is a thread-local, cryptographically secure pseudo random number generator.
-pub const random = @import("crypto/tlcsprng.zig").interface;
-
/// Encoding and decoding
pub const codecs = @import("crypto/codecs.zig");
@@ -364,20 +361,12 @@ test {
_ = secureZero;
_ = timing_safe;
_ = ff;
- _ = random;
_ = errors;
_ = tls;
_ = Certificate;
_ = codecs;
}
-test "CSPRNG" {
- const a = random.int(u64);
- const b = random.int(u64);
- const c = random.int(u64);
- try std.testing.expect(a ^ b ^ c != 0);
-}
-
test "issue #4532: no index out of bounds" {
const types = [_]type{
hash.Md5,
diff --git a/lib/std/crypto/tlcsprng.zig b/lib/std/crypto/tlcsprng.zig
@@ -1,169 +0,0 @@
-//! Thread-local cryptographically secure pseudo-random number generator.
-//! This file has public declarations that are intended to be used internally
-//! by the standard library; this namespace is not intended to be exposed
-//! directly to standard library users.
-
-const std = @import("std");
-const builtin = @import("builtin");
-const mem = std.mem;
-const native_os = builtin.os.tag;
-const posix = std.posix;
-
-/// We use this as a layer of indirection because global const pointers cannot
-/// point to thread-local variables.
-pub const interface: std.Random = .{
- .ptr = undefined,
- .fillFn = tlsCsprngFill,
-};
-
-const os_has_fork = @TypeOf(posix.fork) != void;
-const os_has_arc4random = builtin.link_libc and (@TypeOf(std.c.arc4random_buf) != void);
-const want_fork_safety = os_has_fork and !os_has_arc4random and std.options.crypto_fork_safety;
-const maybe_have_wipe_on_fork = builtin.os.isAtLeast(.linux, .{
- .major = 4,
- .minor = 14,
- .patch = 0,
-}) orelse true;
-
-const Rng = std.Random.DefaultCsprng;
-
-const Context = struct {
- init_state: enum(u8) { uninitialized = 0, initialized, failed },
- rng: Rng,
-};
-
-var install_atfork_handler = std.once(struct {
- // Install the global handler only once.
- // The same handler is shared among threads and is inherinted by fork()-ed
- // processes.
- fn do() void {
- const r = std.c.pthread_atfork(null, null, childAtForkHandler);
- std.debug.assert(r == 0);
- }
-}.do);
-
-threadlocal var wipe_mem: []align(std.heap.page_size_min) u8 = &[_]u8{};
-
-fn tlsCsprngFill(_: *anyopaque, buffer: []u8) void {
- if (os_has_arc4random) {
- // arc4random is already a thread-local CSPRNG.
- return std.c.arc4random_buf(buffer.ptr, buffer.len);
- }
- // Allow applications to decide they would prefer to have every call to
- // std.crypto.random always make an OS syscall, rather than rely on an
- // application implementation of a CSPRNG.
- if (std.options.crypto_always_getrandom) {
- return std.options.cryptoRandomSeed(buffer);
- }
-
- if (wipe_mem.len == 0) {
- // Not initialized yet.
- if (want_fork_safety and maybe_have_wipe_on_fork) {
- // Allocate a per-process page, madvise operates with page
- // granularity.
- wipe_mem = posix.mmap(
- null,
- @sizeOf(Context),
- posix.PROT.READ | posix.PROT.WRITE,
- .{ .TYPE = .PRIVATE, .ANONYMOUS = true },
- -1,
- 0,
- ) catch {
- // Could not allocate memory for the local state, fall back to
- // the OS syscall.
- return std.options.cryptoRandomSeed(buffer);
- };
- // The memory is already zero-initialized.
- } else {
- // Use a static thread-local buffer.
- const S = struct {
- threadlocal var buf: Context align(std.heap.page_size_min) = .{
- .init_state = .uninitialized,
- .rng = undefined,
- };
- };
- wipe_mem = mem.asBytes(&S.buf);
- }
- }
- const ctx: *Context = @ptrCast(wipe_mem.ptr);
-
- switch (ctx.init_state) {
- .uninitialized => {
- if (!want_fork_safety) {
- return initAndFill(buffer);
- }
-
- if (maybe_have_wipe_on_fork) wof: {
- // Qemu user-mode emulation ignores any valid/invalid madvise
- // hint and returns success. Check if this is the case by
- // passing bogus parameters, we expect EINVAL as result.
- if (posix.madvise(wipe_mem.ptr, 0, 0xffffffff)) |_| {
- break :wof;
- } else |_| {}
-
- if (posix.madvise(wipe_mem.ptr, wipe_mem.len, posix.MADV.WIPEONFORK)) |_| {
- return initAndFill(buffer);
- } else |_| {}
- }
-
- if (std.Thread.use_pthreads) {
- return setupPthreadAtforkAndFill(buffer);
- }
-
- // Since we failed to set up fork safety, we fall back to always
- // calling getrandom every time.
- ctx.init_state = .failed;
- return std.options.cryptoRandomSeed(buffer);
- },
- .initialized => {
- return fillWithCsprng(buffer);
- },
- .failed => {
- if (want_fork_safety) {
- return std.options.cryptoRandomSeed(buffer);
- } else {
- unreachable;
- }
- },
- }
-}
-
-fn setupPthreadAtforkAndFill(buffer: []u8) void {
- install_atfork_handler.call();
- return initAndFill(buffer);
-}
-
-fn childAtForkHandler() callconv(.c) void {
- // The atfork handler is global, this function may be called after
- // fork()-ing threads that never initialized the CSPRNG context.
- if (wipe_mem.len == 0) return;
- std.crypto.secureZero(u8, wipe_mem);
-}
-
-fn fillWithCsprng(buffer: []u8) void {
- const ctx: *Context = @ptrCast(wipe_mem.ptr);
- return ctx.rng.fill(buffer);
-}
-
-pub fn defaultRandomSeed(buffer: []u8) void {
- posix.getrandom(buffer) catch @panic("getrandom() failed to provide entropy");
-}
-
-fn initAndFill(buffer: []u8) void {
- var seed: [Rng.secret_seed_length]u8 = undefined;
- // Because we panic on getrandom() failing, we provide the opportunity
- // to override the default seed function. This also makes
- // `std.crypto.random` available on freestanding targets, provided that
- // the `std.options.cryptoRandomSeed` function is provided.
- std.options.cryptoRandomSeed(&seed);
-
- const ctx: *Context = @ptrCast(wipe_mem.ptr);
- ctx.rng = Rng.init(seed);
- std.crypto.secureZero(u8, &seed);
-
- // This is at the end so that accidental recursive dependencies result
- // in stack overflows instead of invalid random data.
- ctx.init_state = .initialized;
-
- return fillWithCsprng(buffer);
-}
diff --git a/lib/std/posix.zig b/lib/std/posix.zig
@@ -361,107 +361,6 @@ pub fn reboot(cmd: RebootCommand) RebootError!void {
}
}
-pub const GetRandomError = OpenError;
-
-/// Obtain a series of random bytes. These bytes can be used to seed user-space
-/// random number generators or for cryptographic purposes.
-/// When linking against libc, this calls the
-/// appropriate OS-specific library call. Otherwise it uses the zig standard
-/// library implementation.
-pub fn getrandom(buffer: []u8) GetRandomError!void {
- if (native_os == .windows) {
- return windows.ProcessPrng(buffer);
- }
- if (builtin.link_libc and @TypeOf(system.arc4random_buf) != void) {
- system.arc4random_buf(buffer.ptr, buffer.len);
- return;
- }
- if (native_os == .wasi) switch (wasi.random_get(buffer.ptr, buffer.len)) {
- .SUCCESS => return,
- else => |err| return unexpectedErrno(err),
- };
- if (@TypeOf(system.getrandom) != void) {
- var buf = buffer;
- const use_c = native_os != .linux or
- std.c.versionCheck(if (builtin.abi.isAndroid()) .{ .major = 28, .minor = 0, .patch = 0 } else .{ .major = 2, .minor = 25, .patch = 0 });
-
- while (buf.len != 0) {
- const num_read: usize, const err = if (use_c) res: {
- const rc = std.c.getrandom(buf.ptr, buf.len, 0);
- break :res .{ @bitCast(rc), errno(rc) };
- } else res: {
- const rc = linux.getrandom(buf.ptr, buf.len, 0);
- break :res .{ rc, linux.errno(rc) };
- };
-
- switch (err) {
- .SUCCESS => buf = buf[num_read..],
- .INVAL => unreachable,
- .FAULT => unreachable,
- .INTR => continue,
- else => return unexpectedErrno(err),
- }
- }
- return;
- }
- if (native_os == .emscripten) {
- const err = errno(std.c.getentropy(buffer.ptr, buffer.len));
- switch (err) {
- .SUCCESS => return,
- else => return unexpectedErrno(err),
- }
- }
- return getRandomBytesDevURandom(buffer);
-}
-
-fn getRandomBytesDevURandom(buf: []u8) GetRandomError!void {
- const fd = try openZ("/dev/urandom", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0);
- defer close(fd);
-
- switch (native_os) {
- .linux => {
- var stx = std.mem.zeroes(linux.Statx);
- const rc = linux.statx(
- fd,
- "",
- linux.AT.EMPTY_PATH,
- .{ .TYPE = true },
- &stx,
- );
- switch (errno(rc)) {
- .SUCCESS => {},
- .ACCES => unreachable,
- .BADF => unreachable,
- .FAULT => unreachable,
- .INVAL => unreachable,
- .LOOP => unreachable,
- .NAMETOOLONG => unreachable,
- .NOENT => unreachable,
- .NOMEM => return error.SystemResources,
- .NOTDIR => unreachable,
- else => |err| return unexpectedErrno(err),
- }
- if (!S.ISCHR(stx.mode)) {
- return error.NoDevice;
- }
- },
- else => {
- const st = fstat(fd) catch |err| switch (err) {
- error.Streaming => return error.NoDevice,
- else => |e| return e,
- };
- if (!S.ISCHR(st.mode)) {
- return error.NoDevice;
- }
- },
- }
-
- var i: usize = 0;
- while (i < buf.len) {
- i += read(fd, buf[i..]) catch return error.Unexpected;
- }
-}
-
pub const RaiseError = UnexpectedError;
pub fn raise(sig: SIG) RaiseError!void {
diff --git a/lib/std/std.zig b/lib/std/std.zig
@@ -137,12 +137,6 @@ pub const Options = struct {
fmt_max_depth: usize = fmt.default_max_depth,
- cryptoRandomSeed: fn (buffer: []u8) void = @import("crypto/tlcsprng.zig").defaultRandomSeed,
-
- crypto_always_getrandom: bool = false,
-
- crypto_fork_safety: bool = true,
-
/// By default, std.http.Client will support HTTPS connections. Set this option to `true` to
/// disable TLS support.
///