Skip to main content

Module discovery

Module discovery 

Source
Expand description

Reading wsl.exe --list --verbose, and deciding that a name an operator typed is exactly one distribution that is really installed.

§wsl.exe answers in UTF-16, and sometimes does not

Microsoft documents wsl --list --verbose as the way to enumerate installed distributions and versions (https://learn.microsoft.com/en-us/windows/wsl/basic-commands). What it does not document is the encoding, and it has changed: for most of WSL’s life the output has been UTF-16 little-endian — which through a redirected pipe reads as ASCII interleaved with NUL bytes — and newer builds have started emitting plain UTF-8 for some subcommands. A parser that assumes either one is a parser that reports “no distributions are installed” on the other, which is the worst possible failure here: it looks exactly like a machine with no WSL, and the remedy it suggests is to install one.

So decode_console_output decides per call, from the bytes:

SignalRead as
FF FE byte-order markUTF-16LE
EF BB BF byte-order markUTF-8
even length, and most odd-indexed bytes are NULUTF-16LE
anything elseUTF-8

The byte-order mark is authoritative and is checked first. The NUL heuristic exists for the BOM-less UTF-16 that a redirected wsl.exe produces, and it is deliberately a majority test rather than an “any NUL” test, so that a distribution name in Cyrillic or Japanese — whose UTF-16 high bytes are not NUL — is still recognised as UTF-16 on the strength of the ASCII around it.

Anything that does not decode cleanly is kept, with the replacement character, and DecodedOutput::is_lossy says so. Nothing here silently repairs a name: a row whose name did not survive decoding is moved to DistributionTable::unreadable rather than offered as something an operator may install into.

§A name may contain spaces, so the table is parsed from the right

  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  Debian GNU/Linux 12    Stopped         1

split_whitespace would turn the third row’s name into four fields. The last two columns, however, are a single word each, so the row is cut from the end: the last token is the version, the one before it is the state, and everything left — trimmed — is the name, spaces, punctuation and all. The header row falls out of the same rule for free, because VERSION does not parse as a number.

Structs§

DecodedOutput
Console output, decoded, and how it had to be read.
DistributionTable
Everything wsl --list --verbose reported, and everything it reported that could not be read.
InstalledDistribution
One row of wsl --list --verbose.

Enums§

ConsoleEncoding
How decode_console_output read the bytes.

Constants§

MAX_DISTRIBUTION_NAME
The longest distribution name this adapter will handle.

Functions§

decode_console_output
Decodes what a Windows console program wrote to a pipe.
validate_distribution_name
Checks a name’s syntax, before it is ever put in an argument vector.