From 369d11587339ce74f8ebc76f2607fe55545eaf7d Mon Sep 17 00:00:00 2001 From: garhve Date: Tue, 20 Dec 2022 11:04:25 +0800 Subject: Build small project following the book --- .../target/doc/src/getrandom/error.rs.html | 385 ++++++++++++++ .../target/doc/src/getrandom/error_impls.rs.html | 51 ++ .../target/doc/src/getrandom/lib.rs.html | 585 +++++++++++++++++++++ .../target/doc/src/getrandom/linux_android.rs.html | 97 ++++ .../target/doc/src/getrandom/use_file.rs.html | 281 ++++++++++ .../target/doc/src/getrandom/util.rs.html | 131 +++++ .../target/doc/src/getrandom/util_libc.rs.html | 323 ++++++++++++ 7 files changed, 1853 insertions(+) create mode 100644 rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error.rs.html create mode 100644 rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error_impls.rs.html create mode 100644 rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/lib.rs.html create mode 100644 rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/linux_android.rs.html create mode 100644 rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/use_file.rs.html create mode 100644 rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util.rs.html create mode 100644 rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util_libc.rs.html (limited to 'rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom') diff --git a/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error.rs.html b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error.rs.html new file mode 100644 index 0000000..4f73e10 --- /dev/null +++ b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error.rs.html @@ -0,0 +1,385 @@ +error.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+
// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+use core::{fmt, num::NonZeroU32};
+
+/// A small and `no_std` compatible error type
+///
+/// The [`Error::raw_os_error()`] will indicate if the error is from the OS, and
+/// if so, which error code the OS gave the application. If such an error is
+/// encountered, please consult with your system documentation.
+///
+/// Internally this type is a NonZeroU32, with certain values reserved for
+/// certain purposes, see [`Error::INTERNAL_START`] and [`Error::CUSTOM_START`].
+///
+/// *If this crate's `"std"` Cargo feature is enabled*, then:
+/// - [`getrandom::Error`][Error] implements
+///   [`std::error::Error`](https://doc.rust-lang.org/std/error/trait.Error.html)
+/// - [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html) implements
+///   [`From<getrandom::Error>`](https://doc.rust-lang.org/std/convert/trait.From.html).
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub struct Error(NonZeroU32);
+
+const fn internal_error(n: u16) -> Error {
+    // SAFETY: code > 0 as INTERNAL_START > 0 and adding n won't overflow a u32.
+    let code = Error::INTERNAL_START + (n as u32);
+    Error(unsafe { NonZeroU32::new_unchecked(code) })
+}
+
+impl Error {
+    /// This target/platform is not supported by `getrandom`.
+    pub const UNSUPPORTED: Error = internal_error(0);
+    /// The platform-specific `errno` returned a non-positive value.
+    pub const ERRNO_NOT_POSITIVE: Error = internal_error(1);
+    /// Call to iOS [`SecRandomCopyBytes`](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes) failed.
+    pub const IOS_SEC_RANDOM: Error = internal_error(3);
+    /// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
+    pub const WINDOWS_RTL_GEN_RANDOM: Error = internal_error(4);
+    /// RDRAND instruction failed due to a hardware issue.
+    pub const FAILED_RDRAND: Error = internal_error(5);
+    /// RDRAND instruction unsupported on this target.
+    pub const NO_RDRAND: Error = internal_error(6);
+    /// The environment does not support the Web Crypto API.
+    pub const WEB_CRYPTO: Error = internal_error(7);
+    /// Calling Web Crypto API `crypto.getRandomValues` failed.
+    pub const WEB_GET_RANDOM_VALUES: Error = internal_error(8);
+    /// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized).
+    pub const VXWORKS_RAND_SECURE: Error = internal_error(11);
+    /// Node.js does not have the `crypto` CommonJS module.
+    pub const NODE_CRYPTO: Error = internal_error(12);
+    /// Calling Node.js function `crypto.randomFillSync` failed.
+    pub const NODE_RANDOM_FILL_SYNC: Error = internal_error(13);
+    /// Called from an ES module on Node.js. This is unsupported, see:
+    /// <https://docs.rs/getrandom#nodejs-es-module-support>.
+    pub const NODE_ES_MODULE: Error = internal_error(14);
+
+    /// Codes below this point represent OS Errors (i.e. positive i32 values).
+    /// Codes at or above this point, but below [`Error::CUSTOM_START`] are
+    /// reserved for use by the `rand` and `getrandom` crates.
+    pub const INTERNAL_START: u32 = 1 << 31;
+
+    /// Codes at or above this point can be used by users to define their own
+    /// custom errors.
+    pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30);
+
+    /// Extract the raw OS error code (if this error came from the OS)
+    ///
+    /// This method is identical to [`std::io::Error::raw_os_error()`][1], except
+    /// that it works in `no_std` contexts. If this method returns `None`, the
+    /// error value can still be formatted via the `Display` implementation.
+    ///
+    /// [1]: https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error
+    #[inline]
+    pub fn raw_os_error(self) -> Option<i32> {
+        if self.0.get() < Self::INTERNAL_START {
+            match () {
+                #[cfg(target_os = "solid_asp3")]
+                // On SOLID, negate the error code again to obtain the original
+                // error code.
+                () => Some(-(self.0.get() as i32)),
+                #[cfg(not(target_os = "solid_asp3"))]
+                () => Some(self.0.get() as i32),
+            }
+        } else {
+            None
+        }
+    }
+
+    /// Extract the bare error code.
+    ///
+    /// This code can either come from the underlying OS, or be a custom error.
+    /// Use [`Error::raw_os_error()`] to disambiguate.
+    #[inline]
+    pub const fn code(self) -> NonZeroU32 {
+        self.0
+    }
+}
+
+cfg_if! {
+    if #[cfg(unix)] {
+        fn os_err(errno: i32, buf: &mut [u8]) -> Option<&str> {
+            let buf_ptr = buf.as_mut_ptr() as *mut libc::c_char;
+            if unsafe { libc::strerror_r(errno, buf_ptr, buf.len()) } != 0 {
+                return None;
+            }
+
+            // Take up to trailing null byte
+            let n = buf.len();
+            let idx = buf.iter().position(|&b| b == 0).unwrap_or(n);
+            core::str::from_utf8(&buf[..idx]).ok()
+        }
+    } else {
+        fn os_err(_errno: i32, _buf: &mut [u8]) -> Option<&str> {
+            None
+        }
+    }
+}
+
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut dbg = f.debug_struct("Error");
+        if let Some(errno) = self.raw_os_error() {
+            dbg.field("os_error", &errno);
+            let mut buf = [0u8; 128];
+            if let Some(err) = os_err(errno, &mut buf) {
+                dbg.field("description", &err);
+            }
+        } else if let Some(desc) = internal_desc(*self) {
+            dbg.field("internal_code", &self.0.get());
+            dbg.field("description", &desc);
+        } else {
+            dbg.field("unknown_code", &self.0.get());
+        }
+        dbg.finish()
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if let Some(errno) = self.raw_os_error() {
+            let mut buf = [0u8; 128];
+            match os_err(errno, &mut buf) {
+                Some(err) => err.fmt(f),
+                None => write!(f, "OS Error: {}", errno),
+            }
+        } else if let Some(desc) = internal_desc(*self) {
+            f.write_str(desc)
+        } else {
+            write!(f, "Unknown Error: {}", self.0.get())
+        }
+    }
+}
+
+impl From<NonZeroU32> for Error {
+    fn from(code: NonZeroU32) -> Self {
+        Self(code)
+    }
+}
+
+fn internal_desc(error: Error) -> Option<&'static str> {
+    match error {
+        Error::UNSUPPORTED => Some("getrandom: this target is not supported"),
+        Error::ERRNO_NOT_POSITIVE => Some("errno: did not return a positive value"),
+        Error::IOS_SEC_RANDOM => Some("SecRandomCopyBytes: iOS Security framework failure"),
+        Error::WINDOWS_RTL_GEN_RANDOM => Some("RtlGenRandom: Windows system function failure"),
+        Error::FAILED_RDRAND => Some("RDRAND: failed multiple times: CPU issue likely"),
+        Error::NO_RDRAND => Some("RDRAND: instruction not supported"),
+        Error::WEB_CRYPTO => Some("Web Crypto API is unavailable"),
+        Error::WEB_GET_RANDOM_VALUES => Some("Calling Web API crypto.getRandomValues failed"),
+        Error::VXWORKS_RAND_SECURE => Some("randSecure: VxWorks RNG module is not initialized"),
+        Error::NODE_CRYPTO => Some("Node.js crypto CommonJS module is unavailable"),
+        Error::NODE_RANDOM_FILL_SYNC => Some("Calling Node.js API crypto.randomFillSync failed"),
+        Error::NODE_ES_MODULE => Some("Node.js ES modules are not directly supported, see https://docs.rs/getrandom#nodejs-es-module-support"),
+        _ => None,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Error;
+    use core::mem::size_of;
+
+    #[test]
+    fn test_size() {
+        assert_eq!(size_of::<Error>(), 4);
+        assert_eq!(size_of::<Result<(), Error>>(), 4);
+    }
+}
+
+
\ No newline at end of file diff --git a/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error_impls.rs.html b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error_impls.rs.html new file mode 100644 index 0000000..8312fb2 --- /dev/null +++ b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/error_impls.rs.html @@ -0,0 +1,51 @@ +error_impls.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+
// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![cfg_attr(docsrs, doc(cfg(feature = "std")))]
+extern crate std;
+
+use crate::Error;
+use core::convert::From;
+use std::io;
+
+impl From<Error> for io::Error {
+    fn from(err: Error) -> Self {
+        match err.raw_os_error() {
+            Some(errno) => io::Error::from_raw_os_error(errno),
+            None => io::Error::new(io::ErrorKind::Other, err),
+        }
+    }
+}
+
+impl std::error::Error for Error {}
+
+
\ No newline at end of file diff --git a/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/lib.rs.html b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/lib.rs.html new file mode 100644 index 0000000..1ee8d19 --- /dev/null +++ b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/lib.rs.html @@ -0,0 +1,585 @@ +lib.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+
// Copyright 2019 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Interface to the operating system's random number generator.
+//!
+//! # Supported targets
+//!
+//! | Target            | Target Triple      | Implementation
+//! | ----------------- | ------------------ | --------------
+//! | Linux, Android    | `*‑linux‑*`        | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
+//! | Windows           | `*‑windows‑*`      | [`BCryptGenRandom`]
+//! | macOS             | `*‑apple‑darwin`   | [`getentropy`][3] if available, otherwise [`/dev/random`][4] (identical to `/dev/urandom`)
+//! | iOS               | `*‑apple‑ios`      | [`SecRandomCopyBytes`]
+//! | FreeBSD           | `*‑freebsd`        | [`getrandom`][5] if available, otherwise [`kern.arandom`][6]
+//! | OpenBSD           | `*‑openbsd`        | [`getentropy`][7]
+//! | NetBSD            | `*‑netbsd`         | [`kern.arandom`][8]
+//! | Dragonfly BSD     | `*‑dragonfly`      | [`getrandom`][9] if available, otherwise [`/dev/random`][10]
+//! | Solaris, illumos  | `*‑solaris`, `*‑illumos` | [`getrandom`][11] if available, otherwise [`/dev/random`][12]
+//! | Fuchsia OS        | `*‑fuchsia`        | [`cprng_draw`]
+//! | Redox             | `*‑redox`          | `/dev/urandom`
+//! | Haiku             | `*‑haiku`          | `/dev/random` (identical to `/dev/urandom`)
+//! | Hermit            | `x86_64-*-hermit`  | [`RDRAND`]
+//! | SGX               | `x86_64‑*‑sgx`     | [`RDRAND`]
+//! | VxWorks           | `*‑wrs‑vxworks‑*`  | `randABytes` after checking entropy pool initialization with `randSecure`
+//! | ESP-IDF           | `*‑espidf`         | [`esp_fill_random`]
+//! | Emscripten        | `*‑emscripten`     | `/dev/random` (identical to `/dev/urandom`)
+//! | WASI              | `wasm32‑wasi`      | [`random_get`]
+//! | Web Browser and Node.js | `wasm32‑*‑unknown` | [`Crypto.getRandomValues`] if available, then [`crypto.randomFillSync`] if on Node.js, see [WebAssembly support]
+//! | SOLID             | `*-kmc-solid_*`    | `SOLID_RNG_SampleRandomBytes`
+//! | Nintendo 3DS      | `armv6k-nintendo-3ds` | [`getrandom`][1]
+//!
+//! There is no blanket implementation on `unix` targets that reads from
+//! `/dev/urandom`. This ensures all supported targets are using the recommended
+//! interface and respect maximum buffer sizes.
+//!
+//! Pull Requests that add support for new targets to `getrandom` are always welcome.
+//!
+//! ## Unsupported targets
+//!
+//! By default, `getrandom` will not compile on unsupported targets, but certain
+//! features allow a user to select a "fallback" implementation if no supported
+//! implementation exists.
+//!
+//! All of the below mechanisms only affect unsupported
+//! targets. Supported targets will _always_ use their supported implementations.
+//! This prevents a crate from overriding a secure source of randomness
+//! (either accidentally or intentionally).
+//!
+//! ### RDRAND on x86
+//!
+//! *If the `rdrand` Cargo feature is enabled*, `getrandom` will fallback to using
+//! the [`RDRAND`] instruction to get randomness on `no_std` `x86`/`x86_64`
+//! targets. This feature has no effect on other CPU architectures.
+//!
+//! ### WebAssembly support
+//!
+//! This crate fully supports the
+//! [`wasm32-wasi`](https://github.com/CraneStation/wasi) and
+//! [`wasm32-unknown-emscripten`](https://www.hellorust.com/setup/emscripten/)
+//! targets. However, the `wasm32-unknown-unknown` target (i.e. the target used
+//! by `wasm-pack`) is not automatically
+//! supported since, from the target name alone, we cannot deduce which
+//! JavaScript interface is in use (or if JavaScript is available at all).
+//!
+//! Instead, *if the `js` Cargo feature is enabled*, this crate will assume
+//! that you are building for an environment containing JavaScript, and will
+//! call the appropriate methods. Both web browser (main window and Web Workers)
+//! and Node.js environments are supported, invoking the methods
+//! [described above](#supported-targets) using the [`wasm-bindgen`] toolchain.
+//!
+//! To enable the `js` Cargo feature, add the following to the `dependencies`
+//! section in your `Cargo.toml` file:
+//! ```toml
+//! [dependencies]
+//! getrandom = { version = "0.2", features = ["js"] }
+//! ```
+//!
+//! This can be done even if `getrandom` is not a direct dependency. Cargo
+//! allows crates to enable features for indirect dependencies.
+//!
+//! This feature should only be enabled for binary, test, or benchmark crates.
+//! Library crates should generally not enable this feature, leaving such a
+//! decision to *users* of their library. Also, libraries should not introduce
+//! their own `js` features *just* to enable `getrandom`'s `js` feature.
+//!
+//! This feature has no effect on targets other than `wasm32-unknown-unknown`.
+//!
+//! #### Node.js ES module support
+//!
+//! Node.js supports both [CommonJS modules] and [ES modules]. Due to
+//! limitations in wasm-bindgen's [`module`] support, we cannot directly
+//! support ES Modules running on Node.js. However, on Node v15 and later, the
+//! module author can add a simple shim to support the Web Cryptography API:
+//! ```js
+//! import { webcrypto } from 'node:crypto'
+//! globalThis.crypto = webcrypto
+//! ```
+//! This crate will then use the provided `webcrypto` implementation.
+//!
+//! ### Custom implementations
+//!
+//! The [`register_custom_getrandom!`] macro allows a user to mark their own
+//! function as the backing implementation for [`getrandom`]. See the macro's
+//! documentation for more information about writing and registering your own
+//! custom implementations.
+//!
+//! Note that registering a custom implementation only has an effect on targets
+//! that would otherwise not compile. Any supported targets (including those
+//! using `rdrand` and `js` Cargo features) continue using their normal
+//! implementations even if a function is registered.
+//!
+//! ## Early boot
+//!
+//! Sometimes, early in the boot process, the OS has not collected enough
+//! entropy to securely seed its RNG. This is especially common on virtual
+//! machines, where standard "random" events are hard to come by.
+//!
+//! Some operating system interfaces always block until the RNG is securely
+//! seeded. This can take anywhere from a few seconds to more than a minute.
+//! A few (Linux, NetBSD and Solaris) offer a choice between blocking and
+//! getting an error; in these cases, we always choose to block.
+//!
+//! On Linux (when the `getrandom` system call is not available), reading from
+//! `/dev/urandom` never blocks, even when the OS hasn't collected enough
+//! entropy yet. To avoid returning low-entropy bytes, we first poll
+//! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
+//!
+//! On OpenBSD, this kind of entropy accounting isn't available, and on
+//! NetBSD, blocking on it is discouraged. On these platforms, nonblocking
+//! interfaces are used, even when reliable entropy may not be available.
+//! On the platforms where it is used, the reliability of entropy accounting
+//! itself isn't free from controversy. This library provides randomness
+//! sourced according to the platform's best practices, but each platform has
+//! its own limits on the grade of randomness it can promise in environments
+//! with few sources of entropy.
+//!
+//! ## Error handling
+//!
+//! We always choose failure over returning known insecure "random" bytes. In
+//! general, on supported platforms, failure is highly unlikely, though not
+//! impossible. If an error does occur, then it is likely that it will occur
+//! on every call to `getrandom`, hence after the first successful call one
+//! can be reasonably confident that no errors will occur.
+//!
+//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
+//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
+//! [3]: https://www.unix.com/man-page/mojave/2/getentropy/
+//! [4]: https://www.unix.com/man-page/mojave/4/random/
+//! [5]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
+//! [6]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
+//! [7]: https://man.openbsd.org/getentropy.2
+//! [8]: https://man.netbsd.org/sysctl.7
+//! [9]: https://leaf.dragonflybsd.org/cgi/web-man?command=getrandom
+//! [10]: https://leaf.dragonflybsd.org/cgi/web-man?command=random&section=4
+//! [11]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
+//! [12]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
+//!
+//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+//! [`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
+//! [`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
+//! [`SecRandomCopyBytes`]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
+//! [`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
+//! [`crypto.randomFillSync`]: https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size
+//! [`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t
+//! [`random_get`]: https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno
+//! [WebAssembly support]: #webassembly-support
+//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
+//! [`module`]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/module.html
+//! [CommonJS modules]: https://nodejs.org/api/modules.html
+//! [ES modules]: https://nodejs.org/api/esm.html
+
+#![doc(
+    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
+    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
+    html_root_url = "https://docs.rs/getrandom/0.2.8"
+)]
+#![no_std]
+#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+
+#[macro_use]
+extern crate cfg_if;
+
+mod error;
+mod util;
+// To prevent a breaking change when targets are added, we always export the
+// register_custom_getrandom macro, so old Custom RNG crates continue to build.
+#[cfg(feature = "custom")]
+mod custom;
+#[cfg(feature = "std")]
+mod error_impls;
+
+pub use crate::error::Error;
+
+// System-specific implementations.
+//
+// These should all provide getrandom_inner with the same signature as getrandom.
+cfg_if! {
+    if #[cfg(any(target_os = "emscripten", target_os = "haiku",
+                 target_os = "redox"))] {
+        mod util_libc;
+        #[path = "use_file.rs"] mod imp;
+    } else if #[cfg(any(target_os = "android", target_os = "linux"))] {
+        mod util_libc;
+        mod use_file;
+        #[path = "linux_android.rs"] mod imp;
+    } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] {
+        mod util_libc;
+        mod use_file;
+        #[path = "solaris_illumos.rs"] mod imp;
+    } else if #[cfg(any(target_os = "freebsd", target_os = "netbsd"))] {
+        mod util_libc;
+        #[path = "bsd_arandom.rs"] mod imp;
+    } else if #[cfg(target_os = "dragonfly")] {
+        mod util_libc;
+        mod use_file;
+        #[path = "dragonfly.rs"] mod imp;
+    } else if #[cfg(target_os = "fuchsia")] {
+        #[path = "fuchsia.rs"] mod imp;
+    } else if #[cfg(target_os = "ios")] {
+        #[path = "ios.rs"] mod imp;
+    } else if #[cfg(target_os = "macos")] {
+        mod util_libc;
+        mod use_file;
+        #[path = "macos.rs"] mod imp;
+    } else if #[cfg(target_os = "openbsd")] {
+        mod util_libc;
+        #[path = "openbsd.rs"] mod imp;
+    } else if #[cfg(target_os = "wasi")] {
+        #[path = "wasi.rs"] mod imp;
+    } else if #[cfg(all(target_arch = "x86_64", target_os = "hermit"))] {
+        #[path = "rdrand.rs"] mod imp;
+    } else if #[cfg(target_os = "vxworks")] {
+        mod util_libc;
+        #[path = "vxworks.rs"] mod imp;
+    } else if #[cfg(target_os = "solid_asp3")] {
+        #[path = "solid.rs"] mod imp;
+    } else if #[cfg(target_os = "espidf")] {
+        #[path = "espidf.rs"] mod imp;
+    } else if #[cfg(windows)] {
+        #[path = "windows.rs"] mod imp;
+    } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
+        #[path = "rdrand.rs"] mod imp;
+    } else if #[cfg(all(feature = "rdrand",
+                        any(target_arch = "x86_64", target_arch = "x86")))] {
+        #[path = "rdrand.rs"] mod imp;
+    } else if #[cfg(all(feature = "js",
+                        target_arch = "wasm32", target_os = "unknown"))] {
+        #[path = "js.rs"] mod imp;
+    } else if #[cfg(all(target_os = "horizon", target_arch = "arm"))] {
+        // We check for target_arch = "arm" because the Nintendo Switch also
+        // uses Horizon OS (it is aarch64).
+        mod util_libc;
+        #[path = "3ds.rs"] mod imp;
+    } else if #[cfg(feature = "custom")] {
+        use custom as imp;
+    } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
+        compile_error!("the wasm32-unknown-unknown target is not supported by \
+                        default, you may need to enable the \"js\" feature. \
+                        For more information see: \
+                        https://docs.rs/getrandom/#webassembly-support");
+    } else {
+        compile_error!("target is not supported, for more information see: \
+                        https://docs.rs/getrandom/#unsupported-targets");
+    }
+}
+
+/// Fill `dest` with random bytes from the system's preferred random number
+/// source.
+///
+/// This function returns an error on any failure, including partial reads. We
+/// make no guarantees regarding the contents of `dest` on error. If `dest` is
+/// empty, `getrandom` immediately returns success, making no calls to the
+/// underlying operating system.
+///
+/// Blocking is possible, at least during early boot; see module documentation.
+///
+/// In general, `getrandom` will be fast enough for interactive usage, though
+/// significantly slower than a user-space CSPRNG; for the latter consider
+/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
+pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
+    if dest.is_empty() {
+        return Ok(());
+    }
+    imp::getrandom_inner(dest)
+}
+
+
\ No newline at end of file diff --git a/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/linux_android.rs.html b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/linux_android.rs.html new file mode 100644 index 0000000..19232f1 --- /dev/null +++ b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/linux_android.rs.html @@ -0,0 +1,97 @@ +linux_android.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Implementation for Linux / Android
+use crate::{
+    util::LazyBool,
+    util_libc::{last_os_error, sys_fill_exact},
+    {use_file, Error},
+};
+
+pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
+    // getrandom(2) was introduced in Linux 3.17
+    static HAS_GETRANDOM: LazyBool = LazyBool::new();
+    if HAS_GETRANDOM.unsync_init(is_getrandom_available) {
+        sys_fill_exact(dest, |buf| unsafe {
+            getrandom(buf.as_mut_ptr() as *mut libc::c_void, buf.len(), 0)
+        })
+    } else {
+        use_file::getrandom_inner(dest)
+    }
+}
+
+fn is_getrandom_available() -> bool {
+    let res = unsafe { getrandom(core::ptr::null_mut(), 0, libc::GRND_NONBLOCK) };
+    if res < 0 {
+        match last_os_error().raw_os_error() {
+            Some(libc::ENOSYS) => false, // No kernel support
+            Some(libc::EPERM) => false,  // Blocked by seccomp
+            _ => true,
+        }
+    } else {
+        true
+    }
+}
+
+unsafe fn getrandom(
+    buf: *mut libc::c_void,
+    buflen: libc::size_t,
+    flags: libc::c_uint,
+) -> libc::ssize_t {
+    libc::syscall(libc::SYS_getrandom, buf, buflen, flags) as libc::ssize_t
+}
+
+
\ No newline at end of file diff --git a/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/use_file.rs.html b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/use_file.rs.html new file mode 100644 index 0000000..27a1fa7 --- /dev/null +++ b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/use_file.rs.html @@ -0,0 +1,281 @@ +use_file.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+
// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Implementations that just need to read from a file
+use crate::{
+    util::LazyUsize,
+    util_libc::{open_readonly, sys_fill_exact},
+    Error,
+};
+use core::{
+    cell::UnsafeCell,
+    sync::atomic::{AtomicUsize, Ordering::Relaxed},
+};
+
+#[cfg(any(
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "haiku",
+    target_os = "macos",
+    target_os = "solaris",
+    target_os = "illumos"
+))]
+const FILE_PATH: &str = "/dev/random\0";
+#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+const FILE_PATH: &str = "/dev/urandom\0";
+
+pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
+    let fd = get_rng_fd()?;
+    let read = |buf: &mut [u8]| unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };
+
+    if cfg!(target_os = "emscripten") {
+        // `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes.
+        for chunk in dest.chunks_mut(65536) {
+            sys_fill_exact(chunk, read)?;
+        }
+    } else {
+        sys_fill_exact(dest, read)?;
+    }
+    Ok(())
+}
+
+// Returns the file descriptor for the device file used to retrieve random
+// bytes. The file will be opened exactly once. All subsequent calls will
+// return the same file descriptor. This file descriptor is never closed.
+fn get_rng_fd() -> Result<libc::c_int, Error> {
+    static FD: AtomicUsize = AtomicUsize::new(LazyUsize::UNINIT);
+    fn get_fd() -> Option<libc::c_int> {
+        match FD.load(Relaxed) {
+            LazyUsize::UNINIT => None,
+            val => Some(val as libc::c_int),
+        }
+    }
+
+    // Use double-checked locking to avoid acquiring the lock if possible.
+    if let Some(fd) = get_fd() {
+        return Ok(fd);
+    }
+
+    // SAFETY: We use the mutex only in this method, and we always unlock it
+    // before returning, making sure we don't violate the pthread_mutex_t API.
+    static MUTEX: Mutex = Mutex::new();
+    unsafe { MUTEX.lock() };
+    let _guard = DropGuard(|| unsafe { MUTEX.unlock() });
+
+    if let Some(fd) = get_fd() {
+        return Ok(fd);
+    }
+
+    // On Linux, /dev/urandom might return insecure values.
+    #[cfg(any(target_os = "android", target_os = "linux"))]
+    wait_until_rng_ready()?;
+
+    let fd = unsafe { open_readonly(FILE_PATH)? };
+    // The fd always fits in a usize without conflicting with UNINIT.
+    debug_assert!(fd >= 0 && (fd as usize) < LazyUsize::UNINIT);
+    FD.store(fd as usize, Relaxed);
+
+    Ok(fd)
+}
+
+// Succeeds once /dev/urandom is safe to read from
+#[cfg(any(target_os = "android", target_os = "linux"))]
+fn wait_until_rng_ready() -> Result<(), Error> {
+    // Poll /dev/random to make sure it is ok to read from /dev/urandom.
+    let fd = unsafe { open_readonly("/dev/random\0")? };
+    let mut pfd = libc::pollfd {
+        fd,
+        events: libc::POLLIN,
+        revents: 0,
+    };
+    let _guard = DropGuard(|| unsafe {
+        libc::close(fd);
+    });
+
+    loop {
+        // A negative timeout means an infinite timeout.
+        let res = unsafe { libc::poll(&mut pfd, 1, -1) };
+        if res >= 0 {
+            debug_assert_eq!(res, 1); // We only used one fd, and cannot timeout.
+            return Ok(());
+        }
+        let err = crate::util_libc::last_os_error();
+        match err.raw_os_error() {
+            Some(libc::EINTR) | Some(libc::EAGAIN) => continue,
+            _ => return Err(err),
+        }
+    }
+}
+
+struct Mutex(UnsafeCell<libc::pthread_mutex_t>);
+
+impl Mutex {
+    const fn new() -> Self {
+        Self(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))
+    }
+    unsafe fn lock(&self) {
+        let r = libc::pthread_mutex_lock(self.0.get());
+        debug_assert_eq!(r, 0);
+    }
+    unsafe fn unlock(&self) {
+        let r = libc::pthread_mutex_unlock(self.0.get());
+        debug_assert_eq!(r, 0);
+    }
+}
+
+unsafe impl Sync for Mutex {}
+
+struct DropGuard<F: FnMut()>(F);
+
+impl<F: FnMut()> Drop for DropGuard<F> {
+    fn drop(&mut self) {
+        self.0()
+    }
+}
+
+
\ No newline at end of file diff --git a/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util.rs.html b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util.rs.html new file mode 100644 index 0000000..73b842f --- /dev/null +++ b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util.rs.html @@ -0,0 +1,131 @@ +util.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+
// Copyright 2019 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![allow(dead_code)]
+use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+
+// This structure represents a lazily initialized static usize value. Useful
+// when it is preferable to just rerun initialization instead of locking.
+// Both unsync_init and sync_init will invoke an init() function until it
+// succeeds, then return the cached value for future calls.
+//
+// Both methods support init() "failing". If the init() method returns UNINIT,
+// that value will be returned as normal, but will not be cached.
+//
+// Users should only depend on the _value_ returned by init() functions.
+// Specifically, for the following init() function:
+//      fn init() -> usize {
+//          a();
+//          let v = b();
+//          c();
+//          v
+//      }
+// the effects of c() or writes to shared memory will not necessarily be
+// observed and additional synchronization methods with be needed.
+pub struct LazyUsize(AtomicUsize);
+
+impl LazyUsize {
+    pub const fn new() -> Self {
+        Self(AtomicUsize::new(Self::UNINIT))
+    }
+
+    // The initialization is not completed.
+    pub const UNINIT: usize = usize::max_value();
+
+    // Runs the init() function at least once, returning the value of some run
+    // of init(). Multiple callers can run their init() functions in parallel.
+    // init() should always return the same value, if it succeeds.
+    pub fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize {
+        // Relaxed ordering is fine, as we only have a single atomic variable.
+        let mut val = self.0.load(Relaxed);
+        if val == Self::UNINIT {
+            val = init();
+            self.0.store(val, Relaxed);
+        }
+        val
+    }
+}
+
+// Identical to LazyUsize except with bool instead of usize.
+pub struct LazyBool(LazyUsize);
+
+impl LazyBool {
+    pub const fn new() -> Self {
+        Self(LazyUsize::new())
+    }
+
+    pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool {
+        self.0.unsync_init(|| init() as usize) != 0
+    }
+}
+
+
\ No newline at end of file diff --git a/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util_libc.rs.html b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util_libc.rs.html new file mode 100644 index 0000000..95b9e91 --- /dev/null +++ b/rust/theBook/chapter-2-guessing-game/guessing_game/target/doc/src/getrandom/util_libc.rs.html @@ -0,0 +1,323 @@ +util_libc.rs - source
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+
// Copyright 2019 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![allow(dead_code)]
+use crate::Error;
+use core::{
+    num::NonZeroU32,
+    ptr::NonNull,
+    sync::atomic::{fence, AtomicPtr, Ordering},
+};
+use libc::c_void;
+
+cfg_if! {
+    if #[cfg(any(target_os = "netbsd", target_os = "openbsd", target_os = "android"))] {
+        use libc::__errno as errno_location;
+    } else if #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "redox"))] {
+        use libc::__errno_location as errno_location;
+    } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] {
+        use libc::___errno as errno_location;
+    } else if #[cfg(any(target_os = "macos", target_os = "freebsd"))] {
+        use libc::__error as errno_location;
+    } else if #[cfg(target_os = "haiku")] {
+        use libc::_errnop as errno_location;
+    } else if #[cfg(all(target_os = "horizon", target_arch = "arm"))] {
+        extern "C" {
+            // Not provided by libc: https://github.com/rust-lang/libc/issues/1995
+            fn __errno() -> *mut libc::c_int;
+        }
+        use __errno as errno_location;
+    }
+}
+
+cfg_if! {
+    if #[cfg(target_os = "vxworks")] {
+        use libc::errnoGet as get_errno;
+    } else if #[cfg(target_os = "dragonfly")] {
+        // Until rust-lang/rust#29594 is stable, we cannot get the errno value
+        // on DragonFlyBSD. So we just return an out-of-range errno.
+        unsafe fn get_errno() -> libc::c_int { -1 }
+    } else {
+        unsafe fn get_errno() -> libc::c_int { *errno_location() }
+    }
+}
+
+pub fn last_os_error() -> Error {
+    let errno = unsafe { get_errno() };
+    if errno > 0 {
+        Error::from(NonZeroU32::new(errno as u32).unwrap())
+    } else {
+        Error::ERRNO_NOT_POSITIVE
+    }
+}
+
+// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function:
+//   - should return -1 and set errno on failure
+//   - should return the number of bytes written on success
+pub fn sys_fill_exact(
+    mut buf: &mut [u8],
+    sys_fill: impl Fn(&mut [u8]) -> libc::ssize_t,
+) -> Result<(), Error> {
+    while !buf.is_empty() {
+        let res = sys_fill(buf);
+        if res < 0 {
+            let err = last_os_error();
+            // We should try again if the call was interrupted.
+            if err.raw_os_error() != Some(libc::EINTR) {
+                return Err(err);
+            }
+        } else {
+            // We don't check for EOF (ret = 0) as the data we are reading
+            // should be an infinite stream of random bytes.
+            buf = &mut buf[(res as usize)..];
+        }
+    }
+    Ok(())
+}
+
+// A "weak" binding to a C function that may or may not be present at runtime.
+// Used for supporting newer OS features while still building on older systems.
+// Based off of the DlsymWeak struct in libstd:
+// https://github.com/rust-lang/rust/blob/1.61.0/library/std/src/sys/unix/weak.rs#L84
+// except that the caller must manually cast self.ptr() to a function pointer.
+pub struct Weak {
+    name: &'static str,
+    addr: AtomicPtr<c_void>,
+}
+
+impl Weak {
+    // A non-null pointer value which indicates we are uninitialized. This
+    // constant should ideally not be a valid address of a function pointer.
+    // However, if by chance libc::dlsym does return UNINIT, there will not
+    // be undefined behavior. libc::dlsym will just be called each time ptr()
+    // is called. This would be inefficient, but correct.
+    // TODO: Replace with core::ptr::invalid_mut(1) when that is stable.
+    const UNINIT: *mut c_void = 1 as *mut c_void;
+
+    // Construct a binding to a C function with a given name. This function is
+    // unsafe because `name` _must_ be null terminated.
+    pub const unsafe fn new(name: &'static str) -> Self {
+        Self {
+            name,
+            addr: AtomicPtr::new(Self::UNINIT),
+        }
+    }
+
+    // Return the address of a function if present at runtime. Otherwise,
+    // return None. Multiple callers can call ptr() concurrently. It will
+    // always return _some_ value returned by libc::dlsym. However, the
+    // dlsym function may be called multiple times.
+    pub fn ptr(&self) -> Option<NonNull<c_void>> {
+        // Despite having only a single atomic variable (self.addr), we still
+        // cannot always use Ordering::Relaxed, as we need to make sure a
+        // successful call to dlsym() is "ordered before" any data read through
+        // the returned pointer (which occurs when the function is called).
+        // Our implementation mirrors that of the one in libstd, meaning that
+        // the use of non-Relaxed operations is probably unnecessary.
+        match self.addr.load(Ordering::Relaxed) {
+            Self::UNINIT => {
+                let symbol = self.name.as_ptr() as *const _;
+                let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, symbol) };
+                // Synchronizes with the Acquire fence below
+                self.addr.store(addr, Ordering::Release);
+                NonNull::new(addr)
+            }
+            addr => {
+                let func = NonNull::new(addr)?;
+                fence(Ordering::Acquire);
+                Some(func)
+            }
+        }
+    }
+}
+
+cfg_if! {
+    if #[cfg(any(target_os = "linux", target_os = "emscripten"))] {
+        use libc::open64 as open;
+    } else {
+        use libc::open;
+    }
+}
+
+// SAFETY: path must be null terminated, FD must be manually closed.
+pub unsafe fn open_readonly(path: &str) -> Result<libc::c_int, Error> {
+    debug_assert_eq!(path.as_bytes().last(), Some(&0));
+    loop {
+        let fd = open(path.as_ptr() as *const _, libc::O_RDONLY | libc::O_CLOEXEC);
+        if fd >= 0 {
+            return Ok(fd);
+        }
+        let err = last_os_error();
+        // We should try again if open() was interrupted.
+        if err.raw_os_error() != Some(libc::EINTR) {
+            return Err(err);
+        }
+    }
+}
+
+
\ No newline at end of file -- cgit v1.2.3-70-g09d2