aboutsummaryrefslogtreecommitdiff
path: root/std/os/linux_random.zig
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-02-05 09:26:39 -0500
committerAndrew Kelley <superjoe30@gmail.com>2018-02-05 09:26:39 -0500
commit44d8d654a0ba463a1d4cf34d435c8422bfcd1c81 (patch)
tree8ef92e3af15a5daf359163d46404171695ae89a1 /std/os/linux_random.zig
parentec59f765266749a29d5ba1804f4ab5afdcabee1d (diff)
downloadzig-44d8d654a0ba463a1d4cf34d435c8422bfcd1c81.tar.gz
zig-44d8d654a0ba463a1d4cf34d435c8422bfcd1c81.zip
fix test failure, organize code, add new compile error
Diffstat (limited to 'std/os/linux_random.zig')
-rw-r--r--std/os/linux_random.zig246
1 files changed, 0 insertions, 246 deletions
diff --git a/std/os/linux_random.zig b/std/os/linux_random.zig
deleted file mode 100644
index 0fb10d1ee9..0000000000
--- a/std/os/linux_random.zig
+++ /dev/null
@@ -1,246 +0,0 @@
-const std = @import("../index.zig");
-const builtin = @import("builtin");
-const assert = std.debug.assert;
-const linux = std.os.linux;
-const math = std.math;
-const mem = std.mem;
-const os = std.os;
-
-use @import("linux_errno.zig");
-
-const arch = switch (builtin.arch) {
- builtin.Arch.x86_64 => @import("linux_x86_64.zig"),
- builtin.Arch.i386 => @import("linux_i386.zig"),
- else => @compileError("unsupported arch"),
-};
-
-const Method = enum {
- Syscall,
- Sysctl,
- Urandom,
-};
-
-const Callback = fn(&i32, []u8) usize;
-
-const Context = struct {
- syscall: Callback,
- sysctl: Callback,
- urandom: Callback,
-};
-
-pub fn getRandomBytes(buf: []u8) usize {
- const ctx = Context {
- .syscall = syscall,
- .sysctl = sysctl,
- .urandom = urandom,
- };
- return withContext(ctx, buf);
-}
-
-fn withContext(comptime ctx: Context, buf: []u8) usize {
- if (buf.len == 0) return 0;
-
- var fd: i32 = -1;
- defer if (fd != -1) {
- const _ = linux.close(fd); // Ignore errors, can't do anything sensible.
- };
-
- // TODO(bnoordhuis) Remember the method across invocations so we don't make
- // unnecessary system calls that are going to fail with ENOSYS anyway.
- var method = Method.Syscall;
- var i: usize = 0;
- while (i < buf.len) {
- const rc = switch (method) {
- Method.Syscall => ctx.syscall(&fd, buf[i..]),
- Method.Sysctl => ctx.sysctl(&fd, buf[i..]),
- Method.Urandom => ctx.urandom(&fd, buf[i..]),
- };
- if (rc == 0) return usize(-EIO); // Can't really happen.
- if (!isErr(rc)) {
- i += rc;
- continue;
- }
- if (rc == usize(-EINTR)) continue;
- if (rc == usize(-ENOSYS) and method == Method.Syscall) {
- method = Method.Urandom;
- continue;
- }
- if (method == Method.Urandom) {
- method = Method.Sysctl;
- continue;
- }
- return rc; // Unexpected error.
- }
-
- return i;
-}
-
-fn syscall(_: &i32, buf: []u8) usize {
- return arch.syscall3(arch.SYS_getrandom, @ptrToInt(&buf[0]), buf.len, 0);
-}
-
-// Note: reads only 14 bytes at a time.
-fn sysctl(_: &i32, buf: []u8) usize {
- const __sysctl_args = extern struct {
- name: &c_int,
- nlen: c_int,
- oldval: &u8,
- oldlenp: &usize,
- newval: ?&u8,
- newlen: usize,
- unused: [4]usize,
- };
-
- var name = [3]c_int { 1, 40, 6 }; // { CTL_KERN, KERN_RANDOM, RANDOM_UUID }
- var uuid: [16]u8 = undefined;
-
- const expected: usize = @sizeOf(@typeOf(uuid));
- var len = expected;
-
- var args = __sysctl_args {
- .name = &name[0],
- .nlen = c_int(name.len),
- .oldval = &uuid[0],
- .oldlenp = &len,
- .newval = null,
- .newlen = 0,
- .unused = []usize {0} ** 4,
- };
-
- const rc = arch.syscall1(arch.SYS__sysctl, @ptrToInt(&args));
- if (rc != 0) return rc;
- if (len != expected) return 0; // Can't happen.
-
- // uuid[] is now a type 4 UUID; bytes 6 and 8 (counting from zero)
- // contain 4 and 5 bits of entropy, respectively. For ease of use,
- // we skip those and only use 14 of the 16 bytes.
- uuid[6] = uuid[14];
- uuid[8] = uuid[15];
-
- const n = math.min(buf.len, usize(14));
- @memcpy(&buf[0], &uuid[0], n);
- return n;
-}
-
-fn urandom(fd: &i32, buf: []u8) usize {
- if (*fd == -1) {
- const flags = linux.O_CLOEXEC|linux.O_RDONLY;
- const rc = linux.open(c"/dev/urandom", flags, 0);
- if (isErr(rc)) return rc;
- *fd = i32(rc);
- }
- // read() doesn't like reads > INT_MAX.
- const n = math.min(buf.len, usize(0x7FFFFFFF));
- return linux.read(*fd, &buf[0], n);
-}
-
-fn isErr(rc: usize) bool {
- return rc > usize(-4096);
-}
-
-test "os.linux.getRandomBytes" {
- try check(42, getRandomBytesTrampoline);
-}
-
-test "os.linux.getRandomBytes syscall" {
- try check(42, syscall);
-}
-
-test "os.linux.getRandomBytes sysctl" {
- try check(14, sysctl);
-}
-
-test "os.linux.getRandomBytes /dev/urandom" {
- try check(42, urandom);
-}
-
-test "os.linux.getRandomBytes state machine" {
- const ctx = Context {
- .syscall = fortytwo,
- .urandom = fail,
- .sysctl = fail,
- };
- var buf = []u8 {0};
- assert(1 == withContext(ctx, buf[0..]));
- assert(42 == buf[0]);
-}
-
-test "os.linux.getRandomBytes no-syscall state machine" {
- const ctx = Context {
- .syscall = enosys,
- .urandom = fortytwo,
- .sysctl = fail,
- };
- var buf = []u8 {0};
- assert(1 == withContext(ctx, buf[0..]));
- assert(42 == buf[0]);
-}
-
-test "os.linux.getRandomBytes no-urandom state machine" {
- const ctx = Context {
- .syscall = enosys,
- .urandom = einval,
- .sysctl = fortytwo,
- };
- var buf = []u8 {0};
- assert(1 == withContext(ctx, buf[0..]));
- assert(42 == buf[0]);
-}
-
-test "os.linux.getRandomBytes no-sysctl state machine" {
- const ctx = Context {
- .syscall = enosys,
- .urandom = einval,
- .sysctl = einval,
- };
- var buf = []u8 {0};
- assert(usize(-EINVAL) == withContext(ctx, buf[0..]));
- assert(0 == buf[0]);
-}
-
-fn einval(_: &i32, buf: []u8) usize {
- return usize(-EINVAL);
-}
-
-fn enosys(_: &i32, buf: []u8) usize {
- return usize(-ENOSYS);
-}
-
-fn fail(_: &i32, buf: []u8) usize {
- os.abort();
-}
-
-fn fortytwo(_: &i32, buf: []u8) usize {
- assert(buf.len == 1);
- buf[0] = 42;
- return 1;
-}
-
-fn check(comptime N: usize, cb: Callback) %void {
- if (builtin.os == builtin.Os.linux) {
- var fd: i32 = -1;
- defer if (fd != -1) {
- const _ = linux.close(fd); // Ignore errors, can't do anything sensible.
- };
-
- var bufs = [3][N]u8 {
- []u8 {0} ** N,
- []u8 {0} ** N,
- []u8 {0} ** N,
- };
-
- for (bufs) |*buf| {
- const err = cb(&fd, (*buf)[0..]);
- assert(err == N);
- }
-
- for (bufs) |*a|
- for (bufs) |*b|
- if (a != b)
- assert(!mem.eql(u8, *a, *b));
- }
-}
-
-fn getRandomBytesTrampoline(_: &i32, buf: []u8) usize {
- return getRandomBytes(buf);
-}