aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos/src/std')
-rw-r--r--libphobos/src/std/format/write.d11
-rw-r--r--libphobos/src/std/random.d66
2 files changed, 65 insertions, 12 deletions
diff --git a/libphobos/src/std/format/write.d b/libphobos/src/std/format/write.d
index d704c14..68a96d4 100644
--- a/libphobos/src/std/format/write.d
+++ b/libphobos/src/std/format/write.d
@@ -534,6 +534,8 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
// Are we already done with formats? Then just dump each parameter in turn
uint currentArg = 0;
+ bool lastWasConsumeAll;
+
while (spec.writeUpToNextSpec(w))
{
if (currentArg == Args.length && !spec.indexStart)
@@ -649,7 +651,10 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
}
default:
if (spec.indexEnd == spec.indexEnd.max)
+ {
+ lastWasConsumeAll = true;
break;
+ }
else if (spec.indexEnd == spec.indexStart)
throw new FormatException(
text("Positional specifier %", spec.indexStart, '$', spec.spec,
@@ -660,7 +665,8 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
" index exceeds ", Args.length));
}
}
- return currentArg;
+
+ return lastWasConsumeAll ? Args.length : currentArg;
}
///
@@ -1212,7 +1218,8 @@ if (isSomeString!(typeof(fmt)))
import std.array : appender;
auto w = appender!(char[])();
- formattedWrite(w, "%1:$d", 1, 2, 3);
+ uint count = formattedWrite(w, "%1:$d", 1, 2, 3);
+ assert(count == 3);
assert(w.data == "123");
}
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index dc1763c..edb8902c 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -1774,19 +1774,65 @@ else
version (linux)
{
- // `getrandom()` was introduced in Linux 3.17.
+ version (linux_legacy_emulate_getrandom)
+ {
+ /+
+ Emulates `getrandom()` for backwards compatibility
+ with outdated kernels and legacy libc versions.
+
+ `getrandom()` was added to the GNU C Library in v2.25.
+ +/
+ pragma(msg, "`getrandom()` emulation for legacy Linux targets is enabled.");
+
+ /+
+ On modern kernels (5.6+), `/dev/random` would behave more similar
+ to `getrandom()`.
+ However, this emulator was specifically written for systems older
+ than that. Hence, `/dev/urandom` is the CSPRNG of choice.
+
+ <https://web.archive.org/web/20200914181930/https://www.2uo.de/myths-about-urandom/>
+ +/
+ private static immutable _pathLinuxSystemCSPRNG = "/dev/urandom";
+
+ import core.sys.posix.sys.types : ssize_t;
+
+ /+
+ Linux `getrandom()` emulation built upon `/dev/urandom`.
+ The fourth parameter (`uint flags`) is happily ignored.
+ +/
+ private ssize_t getrandom(
+ void* buf,
+ size_t buflen,
+ uint,
+ ) @system nothrow @nogc
+ {
+ import core.stdc.stdio : fclose, fopen, fread;
- // Shim for missing bindings in druntime
- version (none)
- import core.sys.linux.sys.random : getrandom;
+ auto blockDev = fopen(_pathLinuxSystemCSPRNG.ptr, "r");
+ if (blockDev is null)
+ assert(false, "System CSPRNG unavailable: `fopen(\"" ~ _pathLinuxSystemCSPRNG ~ "\")` failed.");
+ scope (exit) fclose(blockDev);
+
+ const bytesRead = fread(buf, 1, buflen, blockDev);
+ return bytesRead;
+ }
+ }
else
{
- import core.sys.posix.sys.types : ssize_t;
- extern extern(C) ssize_t getrandom(
- void* buf,
- size_t buflen,
- uint flags,
- ) @system nothrow @nogc;
+ // `getrandom()` was introduced in Linux 3.17.
+
+ // Shim for missing bindings in druntime
+ version (none)
+ import core.sys.linux.sys.random : getrandom;
+ else
+ {
+ import core.sys.posix.sys.types : ssize_t;
+ private extern extern(C) ssize_t getrandom(
+ void* buf,
+ size_t buflen,
+ uint flags,
+ ) @system nothrow @nogc;
+ }
}
}