MiniLang exposes the same application-facing system interfaces on
windows-x64 and linux-x64. The modules select native Win32 or POSIX/glibc
operations at compile time. Existing Windows projects remain source-compatible:
windows-x64 is still the default target and no new library is linked unless a
source module imports it.
std.platformreports the target OS and architecture plus path separators, line endings and executable/shared-library extensions.std.pathprovides target-aware absolute-path detection, joining, file and directory names, extensions and extension replacement. These functions are lexical and do not touch the filesystem.std.processprovides the process ID, environment lookup, current directory lookup and current-directory changes.std.consoledetects interactive input, disables Windows QuickEdit when requested, and reads echo-free secrets or confirmed passwords. Linux secret input usesgetpass; the native temporary buffer is explicitly wiped before returning. Callwipeon caller-owned secret byte arrays after use.
std.io.file complements the convenience-oriented std.fs module. Its
FileHandle supports positional readAt, readExactAt and writeAt, append,
size, truncate, explicit flush and close. Durable open/create variants request
write-through semantics. Windows uses CreateFileW, FlushFileBuffers,
LockFileEx and MoveFileExW; Linux uses open, pread, pwrite, fsync,
flock and rename.
readAt and writeAt pass validated ranges of caller-owned byte buffers
directly to the native file APIs, including nonzero buffer offsets and
short-write retries. The requested count may be smaller than the buffer;
readAt leaves bytes outside the bytes actually read unchanged. Reuse buffers
for hot positional I/O loops. The native call is synchronous; callers must not
mutate a buffer concurrently while a read or write is in progress.
lock(file, mode, wait) takes a whole-file advisory shared or exclusive lock.
A non-blocking conflict returns error code 264. Every participant must obey
the advisory-lock protocol. On Windows, cursor-based operations on one handle
are serialized by the caller; servers should use separate handles per worker.
atomicMove atomically replaces a path within the guarantees of the host
filesystem. For durable metadata updates, flush the file, perform the move and
then call syncDirectory on the containing directory. readAllBytes and
readAllText require an explicit maximum size to prevent accidental unbounded
allocations.
The convenience std.fs.copyFile uses Win32 CopyFileW on Windows. On
Linux it uses copy_file_range when the filesystem supports a fast kernel
copy, with a 1-MiB reusable buffer fallback (selected directly for WSL
DrvFS). It rejects a source and destination that resolve to the same inode
before truncating, including hard links and symlinks.
std.net now exposes reusable-address, keepalive, TCP no-delay and send/receive
timeout options. tcpListenAddress(host, port, backlog) binds an explicit IPv4
address; tcpListen keeps its established all-interface behavior. Public TCP
and UDP helpers accept ports from 0 through 65535 and reject values outside
that range. TCP listeners and ordinary bound UDP sockets request exclusive port
ownership on Windows to avoid cross-process traffic routing; Linux TCP
listeners retain SO_REUSEADDR restart semantics. An explicit
setReuseAddress(socket, true) call opts a Windows UDP socket out of the
exclusive default before it is bound, so intentional shared-port designs keep
working. Process-wide socket initialization and cleanup are serialized; as
before, applications must not call cleanup() while sockets are still in use.
Native socket timeouts are portable for integer millisecond values in
0..2147483647; negative, oversized and non-integer values return a managed
network error rather than being truncated by the platform ABI.
tcpSendAll sends directly from the source byte buffer even after a partial
send. For allocation-free receives into an existing buffer, use
tcpRecvInto(socket, destination, offset, count), which returns the received
byte count (zero on orderly TCP shutdown), or
udpRecvFromInto(socket, destination, offset, count), which returns
[receivedCount, peerIp, peerPort]. Both validate the destination range and
leave bytes outside the received range unchanged. The older tcpRecv and
udpRecvFrom APIs remain available and return newly allocated payloads.
std.tls includes a native provider selected at compile time: Windows uses
Schannel and the system certificate stores; Linux uses OpenSSL 3
(libssl.so.3 and libcrypto.so.3). nativeProviderName() reports the active
backend. The callback-based provider(...), connectClient(...) and
acceptServer(...) contract remains available for application-specific
transports, while normal applications use connect(socket, options) and
accept(socket, options).
Client options default to TLS 1.3, system trust and mandatory DNS-name
verification. The minimum may be changed to TLS 1.2. A 32-byte SHA-256 leaf
certificate pin is an additional fail-closed check; pinning cannot disable peer
verification. Linux optionally accepts a PEM CA bundle through caFile.
Schannel intentionally rejects caFile; install that CA in a Windows store or
use a leaf pin. Neither backend silently falls back below the configured
minimum.
Linux server options are PEM certificate-chain and private-key paths. Windows
accepts store:<SHA1-thumbprint> (searched in CurrentUser and LocalMachine
MY) or pfx:<path>. A PFX password is read from
MINILANG_TLS_PFX_PASSWORD; alternatively set privateKeyReference to
env:VARIABLE_NAME. Secret buffers and imported PFX payloads are wiped during
release. requireClientCertificate requests native client-certificate
validation.
TLS streams own their native security context, but never own the TCP socket.
Call shutdown(stream) to send close_notify, then close(stream), and
finally std.net.close(socket). sendAll handles partial provider writes,
passes the original byte buffer to the provider on the first attempt, and
copies only the unsent tail after a partial write. Providers must treat the
input buffer as read-only. receive returns empty bytes after a clean peer
shutdown. The native Schannel provider grows incomplete-record buffers
geometrically and encrypts each outgoing record in one contiguous buffer;
the Linux OpenSSL provider avoids copying exact-size receive results.
std.uuid creates RFC 4122 version-4 UUIDs with std.crypto.secureRandom and
provides byte/string format, parse and validation helpers. std.crypto adds
PBKDF2-HMAC-SHA-256 and PBKDF2-HMAC-SHA-384 backed by Windows CNG or OpenSSL 3.
std.compress.fast(bytes) tries a standard LZ4 block, retaining raw bytes
when that is smaller. std.compress.compact(bytes) additionally tries
std.compress.rle, a simple byte-run format suited to long equal-byte runs.
Both return the same MLC1 container on Windows and Linux: four magic bytes,
one algorithm byte, three reserved zero bytes, a little-endian 32-bit decoded
length, a little-endian CRC-32C, then the chosen payload. Algorithm 0 is raw,
1 is an LZ4 block, and 2 is MiniLang RLE. The container is not an LZ4 frame,
ZIP archive, or gzip stream.
Call std.compress.decompress(container, maxOutputBytes) with an explicit
application limit. The decoder checks the header, limit, payload bounds,
exact decoded length, and checksum. CRC-32C detects accidental corruption
but provides no authenticity; authenticate data separately when it may be
modified by an attacker. The APIs are one-shot and hold input and output in
memory; split very large files into application-level chunks. Raw
std.compress.lz4.encode/decode blocks interoperate with liblz4 when the
caller supplies the exact uncompressed size.
An unguarded Windows .dll import is a compile error for --target linux-x64.
Use conditional compilation around platform-specific providers. The shared
tests/platform_services.ml acceptance fixture exercises both native targets,
including PBKDF2 vectors, UUIDs, socket options, durable file operations,
advisory lock conflicts and the TLS provider lifecycle. Run
tests/run_tls_native.ps1 -Compiler <compiler> with WSL/OpenSSL installed for
real positive and wrong-hostname Schannel/OpenSSL client/server handshakes.