mirror of
https://github.com/microsoft/WSL.git
synced 2026-02-04 02:06:49 -06:00
Merge remote-tracking branch 'origin/master' into HEAD
This commit is contained in:
commit
ff4b5d5102
@ -166,8 +166,8 @@
|
||||
"FriendlyName": "Arch Linux",
|
||||
"Default": true,
|
||||
"Amd64Url": {
|
||||
"Url": "https://fastly.mirror.pkgbuild.com/wsl/2026.01.01.156076/archlinux-2026.01.01.156076.wsl",
|
||||
"Sha256": "e3820c60df62edc22df29c9c16d2205512d95c1b086232a9b7bc3960542036d4"
|
||||
"Url": "https://fastly.mirror.pkgbuild.com/wsl/2026.02.01.158360/archlinux-2026.02.01.158360.wsl",
|
||||
"Sha256": "e3287ab9f0458240fc6a966849dbc69188bdc7ef376dc27d441aef6f13dd45e5"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@ -292,10 +292,12 @@ a wsl.exe --install <Distro>.</value>
|
||||
<value>Starší verze distribuce nepodporuje WSL 2.</value>
|
||||
</data>
|
||||
<data name="MessageEnableVirtualization" xml:space="preserve">
|
||||
<value>WsL2 se v aktuální konfiguraci vašeho počítače nepodporuje.
|
||||
Povolte volitelnou součást „Platforma virtuálního počítače“ a ujistěte se, že je v systému BIOS povolená virtualizace.
|
||||
Povolte platformu virtuálních počítačů spuštěním příkazu: wsl.exe --install --no-distribution
|
||||
Informace najdete na https://aka.ms/enablevirtualization</value>
|
||||
<value>WSL2 nelze spustit, protože na tomto počítači není povolena virtualizace.
|
||||
Ujistěte se, že je povolena volitelná součást „Virtual Machine Platform“ a že je virtualizace zapnutá v nastavení firmwaru vašeho počítače.
|
||||
|
||||
Povolte „Virtual Machine Platform“ spuštěním: wsl.exe --install --no-distribution
|
||||
|
||||
Další informace najdete na https://aka.ms/enablevirtualization</value>
|
||||
<comment>{Locked="--install "}{Locked="--no-distribution
|
||||
"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||
</data>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -298,10 +298,12 @@ und "wsl.exe --install <Distro>".</value>
|
||||
<value>WSL 2 wird von der Legacy Distribution nicht unterstütztt.</value>
|
||||
</data>
|
||||
<data name="MessageEnableVirtualization" xml:space="preserve">
|
||||
<value>WSL2 wird von Ihrer aktuellen Computerkonfiguration nicht unterstützt.
|
||||
Aktivieren Sie die optionale Komponente "Plattform für virtuelle Computer", und stellen Sie sicher, dass die Virtualisierung im BIOS aktiviert ist.
|
||||
Aktivieren Sie "Plattform für virtuelle Computer", indem Sie ": wsl.exe --install --no-distribution
|
||||
" ausführen. Weitere Informationen finden Sie unter https://aka.ms/enablevirtualization</value>
|
||||
<value>WSL2 kann nicht gestartet werden, da die Virtualisierung auf diesem Computer nicht aktiviert ist.
|
||||
Stellen Sie sicher, dass die optionale Komponente „VM-Plattform“ aktiviert ist und die Virtualisierung in den Firmwareeinstellungen Ihres Computers eingeschaltet ist.
|
||||
|
||||
Aktivieren Sie „VM-Plattform“, indem Sie folgenden Befehl ausführen: wsl.exe --install --no-distribution
|
||||
|
||||
Weitere Informationen finden Sie unter https://aka.ms/enablevirtualization</value>
|
||||
<comment>{Locked="--install "}{Locked="--no-distribution
|
||||
"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||
</data>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -292,10 +292,12 @@ A 'wsl.exe --list --online' parancs használatával listázhatja az elérhető d
|
||||
<value>Az örökölt disztribúció nem támogatja a WSL 2-t.</value>
|
||||
</data>
|
||||
<data name="MessageEnableVirtualization" xml:space="preserve">
|
||||
<value>A jelenlegi számítógép-konfiguráció nem támogatja a WSL2-t.
|
||||
Engedélyezze a „Virtuálisgép-platform” választható összetevőt, és győződjön meg arról, hogy a virtualizálás engedélyezve van a BIOS-ban.
|
||||
<value>A WSL2 nem indítható el, mert a virtualizáció nincs engedélyezve ezen a gépen.
|
||||
Győződjön meg arról, hogy a „Virtuálisgép-platform” választható összetevő engedélyezve van, és a virtualizáció be van kapcsolva a számítógép firmware-beállításaiban.
|
||||
|
||||
A „Virtuálisgép-platform” engedélyezéséhez futtassa a következőt: wsl.exe --install --no-distribution
|
||||
További információért látogasson el a https://aka.ms/enablevirtualization oldalra</value>
|
||||
|
||||
További információért látogasson el ide: https://aka.ms/enablevirtualization</value>
|
||||
<comment>{Locked="--install "}{Locked="--no-distribution
|
||||
"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||
</data>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -292,9 +292,11 @@ e "wsl.exe --install <Distro>" para instalar.</value>
|
||||
<value>A distribuição legada não suporta o WSL 2.</value>
|
||||
</data>
|
||||
<data name="MessageEnableVirtualization" xml:space="preserve">
|
||||
<value>O WSL2 não é suportado com a configuração atual do computador.
|
||||
Ative o componente opcional "Plataforma de Máquinas Virtuais" e certifique-se de que a virtualização está ativada no BIOS.
|
||||
Ative a "Plataforma de Máquinas Virtuais" executando: wsl.exe --install --no-distribution
|
||||
<value>O WSL2 não consegue iniciar porque a virtualização não está ativada nesta máquina.
|
||||
Certifique-se de que o componente opcional "Plataforma de Máquina Virtual" está ativado e a virtualização está ligada nas definições de firmware do seu computador.
|
||||
|
||||
Ative a "Plataforma de Máquina Virtual" ao executar: wsl.exe --install --no-distribution
|
||||
|
||||
Para obter informações, visite https://aka.ms/enablevirtualization</value>
|
||||
<comment>{Locked="--install "}{Locked="--no-distribution
|
||||
"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||
|
||||
@ -169,7 +169,7 @@ Diski ayırmak için '{} {}' wsl.exe çalıştırın.</value>
|
||||
<value>Sağlanan yükleme konumu zaten kullanılıyor.</value>
|
||||
</data>
|
||||
<data name="MessageDistroNameAlreadyExists" xml:space="preserve">
|
||||
<value>Sağlanan ada sahip bir dağıtım zaten mevcut. Farklı bir isim seçmek için --name seçeneğini kullanın.</value>
|
||||
<value>Sağlanan ada sahip bir dağıtım zaten mevcut. Farklı bir ad seçmek için --name komutunu kullanın.</value>
|
||||
<comment>{Locked="--name "}Command line arguments, file names and string inserts should not be translated</comment>
|
||||
</data>
|
||||
<data name="MessageDistroNotFound" xml:space="preserve">
|
||||
@ -1123,7 +1123,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</valu
|
||||
<value>/etc/fstab with mount -a işlenemedi.</value>
|
||||
</data>
|
||||
<data name="MessageReadOnlyDistro" xml:space="preserve">
|
||||
<value>ağıtım diski bağlanırken bir hata oluştu, yedek plan olarak salt okunur şekilde bağlandı.
|
||||
<value>Dağıtım diski bağlanırken bir hata oluştu, yedek plan olarak salt okunur şekilde bağlandı.
|
||||
Kurtarma yönergelerine bakın: https://aka.ms/wsldiskmountrecovery</value>
|
||||
</data>
|
||||
<data name="MessageFailedToTranslate" xml:space="preserve">
|
||||
@ -1364,7 +1364,7 @@ Kurtarma yönergelerine bakın: https://aka.ms/wsldiskmountrecovery</value>
|
||||
<value>Yoksayılan bağlantı noktaları</value>
|
||||
</data>
|
||||
<data name="Settings_IgnoredPorts.Description" xml:space="preserve">
|
||||
<value>Yalnızca wsl2.networkingMode olarak ayarlandığında uygulanabilir. Linux uygulamalarının otomatik olarak iletilen veya Windows'ta değerlendirilen bağlantı noktalarına bağlanacak bağlantı noktalarını belirtir. Virgülle ayrılmış bir listede biçimlendirilmelidir, örneğin: 3000.9000.9090.</value>
|
||||
<value>Yalnızca wsl2.networkingMode olarak ayarlandığında uygulanabilir. Linux uygulamalarının otomatik olarak iletilen veya Windows'da değerlendirilen bağlantı noktalarına bağlanacak bağlantı noktalarını belirtir. Virgülle ayrılmış bir listede biçimlendirilmelidir, örneğin: 3000.9000.9090.</value>
|
||||
<comment>{Locked="wsl2.networkingMode"}.wslconfig property key names should not be translated</comment>
|
||||
</data>
|
||||
<data name="Settings_IgnoredPortsResetButton.Content" xml:space="preserve">
|
||||
|
||||
@ -315,21 +315,17 @@ void GnsEngine::ProcessDNSChange(Interface& interface, const wsl::shared::hns::D
|
||||
content << L"nameserver " << server << L"\n";
|
||||
}
|
||||
|
||||
if (!payload.Domain.empty())
|
||||
{
|
||||
content << L"domain " << payload.Domain << L"\n";
|
||||
}
|
||||
|
||||
// Use 'search' for DNS suffixes.
|
||||
// Per resolv.conf(5): "The domain directive is an obsolete name for the search directive
|
||||
// that handles one search list entry only."
|
||||
// See: https://man7.org/linux/man-pages/man5/resolv.conf.5.html
|
||||
if (!payload.Search.empty())
|
||||
{
|
||||
content << L"search " << wsl::shared::string::Join(wsl::shared::string::Split(payload.Search, L','), L' ') << L"\n";
|
||||
}
|
||||
|
||||
GNS_LOG_INFO(
|
||||
"Setting DNS server domain to {}: {} on interfaceName {} ",
|
||||
payload.Domain.c_str(),
|
||||
content.str().c_str(),
|
||||
interface.Name().c_str());
|
||||
"Setting DNS search to {}: {} on interfaceName {} ", payload.Search.c_str(), content.str().c_str(), interface.Name().c_str());
|
||||
|
||||
THROW_LAST_ERROR_IF(UtilMkdirPath("/etc", 0755) < 0);
|
||||
std::wofstream resolvConf;
|
||||
|
||||
@ -1729,10 +1729,6 @@ Return Value:
|
||||
if (strcmp(MountEnum.Current().FileSystemType, PLAN9_FS_TYPE) == 0)
|
||||
{
|
||||
MountSource = UtilParsePlan9MountSource(MountEnum.Current().SuperOptions);
|
||||
if (MountSource.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (strcmp(MountEnum.Current().FileSystemType, DRVFS_FS_TYPE) == 0)
|
||||
{
|
||||
@ -1741,13 +1737,18 @@ Return Value:
|
||||
}
|
||||
else if (strcmp(MountEnum.Current().FileSystemType, VIRTIO_FS_TYPE) == 0)
|
||||
{
|
||||
MountSource = UtilParseVirtiofsMountSource(MountEnum.Current().Source);
|
||||
MountSource = QueryVirtiofsMountSource(MountEnum.Current().Source);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MountSource.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto letter = ConfigGetDriveLetter(MountSource);
|
||||
if (letter.has_value())
|
||||
{
|
||||
@ -2445,17 +2446,10 @@ try
|
||||
NewMountOptions += ',';
|
||||
}
|
||||
|
||||
MountPlan9Filesystem(NewSource, MountEntry.MountPoint, NewMountOptions.c_str(), Message->Admin, Config);
|
||||
MountPlan9Share(NewSource, MountEntry.MountPoint, NewMountOptions.c_str(), Message->Admin, Config);
|
||||
}
|
||||
else if (strcmp(MountEntry.FileSystemType, VIRTIO_FS_TYPE) == 0)
|
||||
{
|
||||
std::string_view Source = MountEntry.Source;
|
||||
std::string_view OldTag = Message->Admin ? LX_INIT_DRVFS_VIRTIO_TAG : LX_INIT_DRVFS_ADMIN_VIRTIO_TAG;
|
||||
if (!wsl::shared::string::StartsWith(Source, OldTag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RemountVirtioFs(MountEntry.Source, MountEntry.MountPoint, MountEntry.MountOptions, Message->Admin);
|
||||
}
|
||||
else
|
||||
|
||||
@ -298,70 +298,12 @@ try
|
||||
{
|
||||
return MountFilesystem(DRVFS_FS_TYPE, Source, Target, Options, ExitCode);
|
||||
}
|
||||
|
||||
// Use virtiofs if the source of the mount is the root of a drive; otherwise, use 9p.
|
||||
if (WSL_USE_VIRTIO_FS(Config))
|
||||
else if (WSL_USE_VIRTIO_FS(Config))
|
||||
{
|
||||
if (wsl::shared::string::IsDriveRoot(Source))
|
||||
{
|
||||
return MountVirtioFs(Source, Target, Options, Admin, Config, ExitCode);
|
||||
}
|
||||
|
||||
LOG_WARNING("virtiofs is only supported for mounting full drives, using 9p to mount {}", Source);
|
||||
return MountVirtioFs(Source, Target, Options, Admin, Config, ExitCode);
|
||||
}
|
||||
|
||||
//
|
||||
// Check if the path is a UNC path.
|
||||
//
|
||||
|
||||
const char* Plan9Source;
|
||||
std::string UncSource;
|
||||
if ((strlen(Source) >= PLAN9_UNC_PREFIX_LENGTH) && ((Source[0] == '/') || (Source[0] == '\\')) &&
|
||||
((Source[1] == '/') || (Source[1] == '\\')))
|
||||
{
|
||||
UncSource = PLAN9_UNC_TRANSLATED_PREFIX;
|
||||
UncSource += &Source[PLAN9_UNC_PREFIX_LENGTH];
|
||||
Plan9Source = UncSource.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
Plan9Source = Source;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether to use the elevated or regular 9p server.
|
||||
//
|
||||
|
||||
bool Elevated = Admin.has_value() ? Admin.value() : IsDrvfsElevated();
|
||||
|
||||
//
|
||||
// Initialize mount options.
|
||||
//
|
||||
|
||||
auto Plan9Options = std::format("{};path={}", PLAN9_ANAME_DRVFS, Plan9Source);
|
||||
|
||||
//
|
||||
// N.B. The cache option is added to the start of this so if the user
|
||||
// specifies one explicitly, it will override the default.
|
||||
//
|
||||
|
||||
std::string MountOptions = "cache=mmap,";
|
||||
auto ParsedOptions = ConvertDrvfsMountOptionsToPlan9(Options ? Options : "", Config);
|
||||
Plan9Options += ParsedOptions.first;
|
||||
MountOptions += ParsedOptions.second;
|
||||
|
||||
//
|
||||
// Append the 9p mount options to the end of the other mount options and perform the mount operation.
|
||||
//
|
||||
|
||||
MountOptions += Plan9Options;
|
||||
|
||||
if (MountPlan9Filesystem(Source, Target, MountOptions.c_str(), Elevated, Config, ExitCode) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return MountPlan9(Source, Target, Options, Admin, Config, ExitCode);
|
||||
}
|
||||
CATCH_RETURN_ERRNO()
|
||||
|
||||
@ -407,7 +349,7 @@ Return Value:
|
||||
return ExitCode;
|
||||
}
|
||||
|
||||
int MountPlan9Filesystem(const char* Source, const char* Target, const char* Options, bool Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode)
|
||||
int MountPlan9Share(const char* Source, const char* Target, const char* Options, bool Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode)
|
||||
|
||||
/*++
|
||||
|
||||
@ -425,6 +367,8 @@ Arguments:
|
||||
|
||||
Admin - Supplies a boolean specifying if the admin share should be used.
|
||||
|
||||
Config - Supplies the distribution configuration.
|
||||
|
||||
ExitCode - Supplies an optional pointer that receives the exit code.
|
||||
|
||||
Return Value:
|
||||
@ -452,10 +396,95 @@ Return Value:
|
||||
|
||||
MountOptions =
|
||||
std::format("msize={},trans=fd,rfdno={},wfdno={},{}", LX_INIT_UTILITY_VM_PLAN9_BUFFER_SIZE, Fd.get(), Fd.get(), Options);
|
||||
|
||||
return MountFilesystem(PLAN9_FS_TYPE, Source, Target, MountOptions.c_str(), ExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
int MountPlan9(const char* Source, const char* Target, const char* Options, std::optional<bool> Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will perform a DrvFs mount using Plan9.
|
||||
|
||||
Arguments:
|
||||
|
||||
Source - Supplies the mount source.
|
||||
|
||||
Target - Supplies the mount target.
|
||||
|
||||
Options - Supplies the mount options.
|
||||
|
||||
Admin - Supplies an optional boolean to specify if the admin or non-admin share should be used.
|
||||
|
||||
Config - Supplies the distribution configuration.
|
||||
|
||||
ExitCode - Supplies an optional pointer that receives the exit code.
|
||||
|
||||
Return Value:
|
||||
|
||||
0 on success, -1 on failure.
|
||||
|
||||
--*/
|
||||
|
||||
try
|
||||
{
|
||||
//
|
||||
// Check if the path is a UNC path.
|
||||
//
|
||||
|
||||
const char* Plan9Source;
|
||||
std::string UncSource;
|
||||
if ((strlen(Source) >= PLAN9_UNC_PREFIX_LENGTH) && ((Source[0] == '/') || (Source[0] == '\\')) &&
|
||||
((Source[1] == '/') || (Source[1] == '\\')))
|
||||
{
|
||||
UncSource = PLAN9_UNC_TRANSLATED_PREFIX;
|
||||
UncSource += &Source[PLAN9_UNC_PREFIX_LENGTH];
|
||||
Plan9Source = UncSource.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
Plan9Source = Source;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether to use the elevated or regular 9p server.
|
||||
//
|
||||
|
||||
bool Elevated = Admin.has_value() ? Admin.value() : IsDrvfsElevated();
|
||||
|
||||
//
|
||||
// Initialize mount options.
|
||||
//
|
||||
|
||||
auto Plan9Options = std::format("{};path={}", PLAN9_ANAME_DRVFS, Plan9Source);
|
||||
|
||||
//
|
||||
// N.B. The cache option is added to the start of this so if the user
|
||||
// specifies one explicitly, it will override the default.
|
||||
//
|
||||
|
||||
std::string MountOptions = "cache=mmap,";
|
||||
auto ParsedOptions = ConvertDrvfsMountOptionsToPlan9(Options ? Options : "", Config);
|
||||
Plan9Options += ParsedOptions.first;
|
||||
MountOptions += ParsedOptions.second;
|
||||
|
||||
//
|
||||
// Append the 9p mount options to the end of the other mount options and perform the mount operation.
|
||||
//
|
||||
|
||||
MountOptions += Plan9Options;
|
||||
if (MountPlan9Share(Source, Target, MountOptions.c_str(), Elevated, Config, ExitCode) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
CATCH_RETURN_ERRNO()
|
||||
|
||||
int MountVirtioFs(const char* Source, const char* Target, const char* Options, std::optional<bool> Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode)
|
||||
|
||||
/*++
|
||||
@ -486,8 +515,6 @@ Return Value:
|
||||
|
||||
try
|
||||
{
|
||||
assert(wsl::shared::string::IsDriveRoot(Source));
|
||||
|
||||
//
|
||||
// Check whether to use the elevated or non-elevated virtiofs server.
|
||||
//
|
||||
@ -516,7 +543,7 @@ try
|
||||
AddShare.WriteString(AddShare->OptionsOffset, Plan9Options);
|
||||
|
||||
//
|
||||
// Connect to the wsl service to add the virtiofs share.
|
||||
// Connect to the wsl service to add the virtiofs share. If adding the share fails, fallback to mounting using Plan9.
|
||||
//
|
||||
|
||||
wsl::shared::SocketChannel Channel{UtilConnectVsock(LX_INIT_UTILITY_VM_VIRTIOFS_PORT, true), "VirtoFs"};
|
||||
@ -527,11 +554,10 @@ try
|
||||
|
||||
gsl::span<gsl::byte> ResponseSpan;
|
||||
const auto& Response = Channel.Transaction<LX_INIT_ADD_VIRTIOFS_SHARE_MESSAGE>(AddShare.Span(), &ResponseSpan);
|
||||
|
||||
if (Response.Result != 0)
|
||||
{
|
||||
LOG_ERROR("Add virtiofs share for {} failed {}", Source, Response.Result);
|
||||
return -1;
|
||||
LOG_WARNING("Add virtiofs share for {} failed {}, falling back to Plan9", Source, Response.Result);
|
||||
return MountPlan9(Source, Target, Options, Admin, Config, ExitCode);
|
||||
}
|
||||
|
||||
//
|
||||
@ -596,3 +622,52 @@ try
|
||||
return MountWithRetry(Tag, Target, VIRTIO_FS_TYPE, Options);
|
||||
}
|
||||
CATCH_RETURN_ERRNO()
|
||||
|
||||
std::string QueryVirtiofsMountSource(const char* Tag)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine takes a virtiofs tag and determines the Windows path it refers to.
|
||||
|
||||
Arguments:
|
||||
|
||||
Tag - Supplies the virtiofs tag to query.
|
||||
|
||||
Return Value:
|
||||
|
||||
The mount source, an empty string on failure.
|
||||
|
||||
--*/
|
||||
|
||||
try
|
||||
{
|
||||
wsl::shared::MessageWriter<LX_INIT_QUERY_VIRTIOFS_SHARE_MESSAGE> QueryShare(LxInitMessageQueryVirtioFsDevice);
|
||||
QueryShare.WriteString(QueryShare->TagOffset, Tag);
|
||||
|
||||
//
|
||||
// Connect to the host and send the query request.
|
||||
//
|
||||
|
||||
wsl::shared::SocketChannel Channel{UtilConnectVsock(LX_INIT_UTILITY_VM_VIRTIOFS_PORT, true), "QueryVirtioFs"};
|
||||
if (Channel.Socket() < 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
gsl::span<gsl::byte> ResponseSpan;
|
||||
const auto& Response = Channel.Transaction<LX_INIT_QUERY_VIRTIOFS_SHARE_MESSAGE>(QueryShare.Span(), &ResponseSpan);
|
||||
if (Response.Result != 0)
|
||||
{
|
||||
LOG_ERROR("Query virtiofs share for {} failed {}", Tag, Response.Result);
|
||||
return {};
|
||||
}
|
||||
|
||||
return wsl::shared::string::FromSpan(ResponseSpan, Response.TagOffset);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -23,9 +23,12 @@ int MountDrvfs(const char* Source, const char* Target, const char* Options, std:
|
||||
|
||||
int MountDrvfsEntry(int Argc, char* Argv[]);
|
||||
|
||||
int MountPlan9Filesystem(
|
||||
const char* Source, const char* Target, const char* Options, bool Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode = nullptr);
|
||||
int MountPlan9Share(const char* Source, const char* Target, const char* Options, bool Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode = nullptr);
|
||||
|
||||
int MountPlan9(const char* Source, const char* Target, const char* Options, std::optional<bool> Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode);
|
||||
|
||||
int MountVirtioFs(const char* Source, const char* Target, const char* Options, std::optional<bool> Admin, const wsl::linux::WslDistributionConfig& Config, int* ExitCode = nullptr);
|
||||
|
||||
int RemountVirtioFs(const char* Tag, const char* Target, const char* Options, bool Admin);
|
||||
|
||||
std::string QueryVirtiofsMountSource(const char* Tag);
|
||||
|
||||
@ -904,11 +904,12 @@ try
|
||||
}
|
||||
else if (strcmp(MountEnum.Current().FileSystemType, VIRTIO_FS_TYPE) == 0)
|
||||
{
|
||||
MountSource = UtilParseVirtiofsMountSource(MountEnum.Current().Source);
|
||||
MountSource = QueryVirtiofsMountSource(MountEnum.Current().Source);
|
||||
if (MountSource.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MountEnum.Current().Source = MountSource.data();
|
||||
}
|
||||
else if (strcmp(MountEnum.Current().FileSystemType, DRVFS_FS_TYPE) == 0)
|
||||
@ -2047,41 +2048,6 @@ Return Value:
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string UtilParseVirtiofsMountSource(std::string_view Source)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine parses the mount source to determine the actual source of a
|
||||
a VirtioFs mount.
|
||||
|
||||
Arguments:
|
||||
|
||||
Source - Supplies the source string.
|
||||
|
||||
Return Value:
|
||||
|
||||
The mount source, or NULL if the source is not valid.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
std::string MountSource{};
|
||||
if (wsl::shared::string::StartsWith(Source, LX_INIT_DRVFS_ADMIN_VIRTIO_TAG) && (Source.size() >= sizeof(LX_INIT_DRVFS_ADMIN_VIRTIO_TAG)))
|
||||
{
|
||||
MountSource = Source[sizeof(LX_INIT_DRVFS_ADMIN_VIRTIO_TAG) - 1];
|
||||
MountSource += ":";
|
||||
}
|
||||
else if (wsl::shared::string::StartsWith(Source, LX_INIT_DRVFS_VIRTIO_TAG) && (Source.size() >= sizeof(LX_INIT_DRVFS_VIRTIO_TAG)))
|
||||
{
|
||||
MountSource = Source[sizeof(LX_INIT_DRVFS_VIRTIO_TAG) - 1];
|
||||
MountSource += ":";
|
||||
}
|
||||
|
||||
return MountSource;
|
||||
}
|
||||
|
||||
std::vector<char> UtilParseWslEnv(char* NtEnvironment)
|
||||
|
||||
/*++
|
||||
|
||||
@ -259,8 +259,6 @@ int UtilParseCgroupsLine(char* Line, char** SubsystemName, bool* Enabled);
|
||||
|
||||
std::string UtilParsePlan9MountSource(std::string_view MountOptions);
|
||||
|
||||
std::string UtilParseVirtiofsMountSource(std::string_view MountOptions);
|
||||
|
||||
std::vector<char> UtilParseWslEnv(char* NtEnvironment);
|
||||
|
||||
int UtilProcessChildExitCode(int Status, const char* Name, int ExpectedStatus = 0, bool PrintError = true);
|
||||
|
||||
@ -319,6 +319,7 @@ typedef enum _LX_MESSAGE_TYPE
|
||||
LxInitMessageAddVirtioFsDevice,
|
||||
LxInitMessageAddVirtioFsDeviceResponse,
|
||||
LxInitMessageRemountVirtioFsDevice,
|
||||
LxInitMessageQueryVirtioFsDevice,
|
||||
LxInitMessageStartDistroInit,
|
||||
LxInitMessageCreateLoginSession,
|
||||
LxInitMessageStopPlan9Server,
|
||||
@ -1169,6 +1170,17 @@ typedef struct _LX_INIT_REMOUNT_VIRTIOFS_SHARE_MESSAGE
|
||||
PRETTY_PRINT(FIELD(Header), FIELD(Admin), STRING_FIELD(TagOffset));
|
||||
} LX_INIT_REMOUNT_VIRTIOFS_SHARE_MESSAGE, *PLX_INIT_REMOUNT_VIRTIOFS_SHARE_MESSAGE;
|
||||
|
||||
typedef struct _LX_INIT_QUERY_VIRTIOFS_SHARE_MESSAGE
|
||||
{
|
||||
static inline auto Type = LxInitMessageQueryVirtioFsDevice;
|
||||
using TResponse = LX_INIT_ADD_VIRTIOFS_SHARE_RESPONSE_MESSAGE;
|
||||
|
||||
MESSAGE_HEADER Header;
|
||||
unsigned int TagOffset;
|
||||
char Buffer[];
|
||||
|
||||
PRETTY_PRINT(FIELD(Header), STRING_FIELD(TagOffset));
|
||||
} LX_INIT_QUERY_VIRTIOFS_SHARE_MESSAGE, *PLX_INIT_QUERY_VIRTIOFS_SHARE_MESSAGE;
|
||||
//
|
||||
// The messages that can be sent to mini_init.
|
||||
//
|
||||
|
||||
@ -52,26 +52,6 @@ inline unsigned int CopyToSpan(const std::string_view String, const gsl::span<gs
|
||||
return PreviousOffset;
|
||||
}
|
||||
|
||||
inline bool IsDriveRoot(const std::string_view Path)
|
||||
{
|
||||
bool IsRoot = true;
|
||||
if (Path.length() == 3)
|
||||
{
|
||||
IsRoot &= Path[2] == '\\';
|
||||
}
|
||||
|
||||
if (Path.length() == 2 || Path.length() == 3)
|
||||
{
|
||||
IsRoot &= isalpha(Path[0]) && Path[1] == ':';
|
||||
}
|
||||
else
|
||||
{
|
||||
IsRoot = false;
|
||||
}
|
||||
|
||||
return IsRoot;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool EndsWith(const std::basic_string<T>& String, const std::basic_string_view<T> Suffix)
|
||||
{
|
||||
|
||||
@ -26,8 +26,13 @@ static wil::srwlock g_endpointsInUseLock;
|
||||
static std::vector<GUID> g_endpointsInUse;
|
||||
|
||||
NatNetworking::NatNetworking(
|
||||
HCS_SYSTEM system, wsl::windows::common::hcs::unique_hcn_network&& network, GnsChannel&& gnsChannel, Config& config, wil::unique_socket&& dnsHvsocket) :
|
||||
m_system(system), m_config(config), m_network(std::move(network)), m_gnsChannel(std::move(gnsChannel))
|
||||
HCS_SYSTEM system,
|
||||
wsl::windows::common::hcs::unique_hcn_network&& network,
|
||||
GnsChannel&& gnsChannel,
|
||||
Config& config,
|
||||
wil::unique_socket&& dnsHvsocket,
|
||||
LPCWSTR dnsOptions) :
|
||||
m_system(system), m_config(config), m_network(std::move(network)), m_dnsOptions(dnsOptions), m_gnsChannel(std::move(gnsChannel))
|
||||
{
|
||||
m_connectivityTelemetryEnabled = config.EnableTelemetry && !WslTraceLoggingShouldDisableTelemetry();
|
||||
|
||||
@ -48,7 +53,7 @@ NatNetworking::NatNetworking(
|
||||
// prioritized means:
|
||||
// - can only set 3 DNS servers (Linux limitation)
|
||||
// - when there are multiple host connected interfaces, we need to use the DNS servers from the most-likely-to-be-used interface on the host
|
||||
m_mirrorDnsInfo.emplace();
|
||||
m_useMirrorDnsSettings = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,7 +342,7 @@ void NatNetworking::Initialize()
|
||||
UpdateDns(endpointProperties.GatewayAddress.c_str());
|
||||
|
||||
// if using the shared access DNS proxy, ensure that the shared access service is allowed inbound UDP access.
|
||||
if (!m_mirrorDnsInfo && !m_dnsTunnelingResolver)
|
||||
if (!m_useMirrorDnsSettings && !m_dnsTunnelingResolver)
|
||||
{
|
||||
// N.B. This rule works around a host OS issue that prevents the DNS proxy from working on older versions of Windows.
|
||||
ConfigureSharedAccessFirewallRule();
|
||||
@ -433,35 +438,22 @@ _Requires_lock_held_(m_lock)
|
||||
void NatNetworking::UpdateDns(std::optional<PCWSTR> gatewayAddress) noexcept
|
||||
try
|
||||
{
|
||||
if (!m_dnsTunnelingResolver && !m_mirrorDnsInfo && !gatewayAddress)
|
||||
if (!m_dnsTunnelingResolver && !m_useMirrorDnsSettings && !gatewayAddress)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
networking::DnsInfo latestDnsSettings{};
|
||||
|
||||
// true if the "domain" entry of /etc/resolv.conf should be configured
|
||||
// Note: the "domain" entry allows a single DNS suffix to be configured
|
||||
bool configureLinuxDomain = false;
|
||||
|
||||
// NAT mode with DNS tunneling
|
||||
if (m_dnsTunnelingResolver)
|
||||
{
|
||||
latestDnsSettings = HostDnsInfo::GetDnsTunnelingSettings(m_dnsTunnelingIpAddress);
|
||||
}
|
||||
// NAT mode without Shared Access DNS proxy
|
||||
else if (m_mirrorDnsInfo)
|
||||
else if (m_useMirrorDnsSettings)
|
||||
{
|
||||
m_mirrorDnsInfo->UpdateNetworkInformation();
|
||||
const auto settings = m_mirrorDnsInfo->GetDnsSettings(DnsSettingsFlags::IncludeVpn);
|
||||
|
||||
latestDnsSettings.Servers = std::move(settings.Servers);
|
||||
|
||||
if (!settings.Domains.empty())
|
||||
{
|
||||
latestDnsSettings.Domains.emplace_back(std::move(settings.Domains.front()));
|
||||
configureLinuxDomain = true;
|
||||
}
|
||||
latestDnsSettings = HostDnsInfo::GetDnsSettings(DnsSettingsFlags::IncludeVpn);
|
||||
}
|
||||
// NAT mode with Shared Access DNS proxy
|
||||
else if (gatewayAddress)
|
||||
@ -472,11 +464,10 @@ try
|
||||
|
||||
if (latestDnsSettings != m_trackedDnsSettings)
|
||||
{
|
||||
auto dnsNotification = BuildDnsNotification(latestDnsSettings, configureLinuxDomain);
|
||||
auto dnsNotification = BuildDnsNotification(latestDnsSettings, m_dnsOptions);
|
||||
|
||||
WSL_LOG(
|
||||
"NatNetworking::UpdateDns",
|
||||
TraceLoggingValue(dnsNotification.Domain.c_str(), "domain"),
|
||||
TraceLoggingValue(dnsNotification.Options.c_str(), "options"),
|
||||
TraceLoggingValue(dnsNotification.Search.c_str(), "search"),
|
||||
TraceLoggingValue(dnsNotification.ServerList.c_str(), "serverList"));
|
||||
|
||||
@ -18,7 +18,13 @@ namespace wsl::core {
|
||||
class NatNetworking final : public INetworkingEngine
|
||||
{
|
||||
public:
|
||||
NatNetworking(HCS_SYSTEM system, wsl::windows::common::hcs::unique_hcn_network&& network, GnsChannel&& gnsChannel, Config& config, wil::unique_socket&& dnsHvsocket);
|
||||
NatNetworking(
|
||||
HCS_SYSTEM system,
|
||||
wsl::windows::common::hcs::unique_hcn_network&& network,
|
||||
GnsChannel&& gnsChannel,
|
||||
Config& config,
|
||||
wil::unique_socket&& dnsHvsocket,
|
||||
LPCWSTR dnsOptions = LX_INIT_RESOLVCONF_FULL_HEADER);
|
||||
~NatNetworking() override;
|
||||
|
||||
// Note: This class cannot be moved because m_networkNotifyHandle captures a 'this' pointer.
|
||||
@ -69,12 +75,18 @@ private:
|
||||
// The latest DNS settings configured in Linux
|
||||
_Guarded_by_(m_lock) networking::DnsInfo m_trackedDnsSettings {};
|
||||
|
||||
// If true, DNS settings are retrieved from host adapters (mirrored mode)
|
||||
// rather than using the shared access DNS proxy
|
||||
bool m_useMirrorDnsSettings = false;
|
||||
|
||||
// Options/header for /etc/resolv.conf
|
||||
LPCWSTR m_dnsOptions = nullptr;
|
||||
|
||||
GnsChannel m_gnsChannel;
|
||||
std::shared_ptr<networking::NetworkSettings> m_networkSettings;
|
||||
networking::EphemeralHcnEndpoint m_endpoint;
|
||||
ULONG m_networkMtu = 0;
|
||||
|
||||
std::optional<networking::HostDnsInfo> m_mirrorDnsInfo;
|
||||
networking::unique_notify_handle m_networkNotifyHandle{};
|
||||
};
|
||||
|
||||
|
||||
@ -14,11 +14,12 @@ using wsl::core::VirtioNetworking;
|
||||
static constexpr auto c_loopbackDeviceName = TEXT(LX_INIT_LOOPBACK_DEVICE_NAME);
|
||||
|
||||
VirtioNetworking::VirtioNetworking(
|
||||
GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken) :
|
||||
GnsChannel&& gnsChannel, bool enableLocalhostRelay, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken) :
|
||||
m_guestDeviceManager(std::move(guestDeviceManager)),
|
||||
m_userToken(std::move(userToken)),
|
||||
m_gnsChannel(std::move(gnsChannel)),
|
||||
m_enableLocalhostRelay(enableLocalhostRelay)
|
||||
m_enableLocalhostRelay(enableLocalhostRelay),
|
||||
m_dnsOptions(dnsOptions)
|
||||
{
|
||||
}
|
||||
|
||||
@ -66,7 +67,7 @@ void VirtioNetworking::Initialize()
|
||||
}
|
||||
|
||||
// Get initial DNS settings for device options.
|
||||
auto initialDns = m_dnsUpdateHelper.GetCurrentDnsSettings(networking::DnsSettingsFlags::IncludeVpn);
|
||||
auto initialDns = networking::HostDnsInfo::GetDnsSettings(networking::DnsSettingsFlags::IncludeVpn);
|
||||
if (!initialDns.Servers.empty())
|
||||
{
|
||||
if (device_options.tellp() > 0)
|
||||
@ -260,7 +261,7 @@ try
|
||||
UpdateMtu();
|
||||
|
||||
// Check for DNS changes and send update if needed.
|
||||
auto currentDns = m_dnsUpdateHelper.GetCurrentDnsSettings(networking::DnsSettingsFlags::IncludeVpn);
|
||||
auto currentDns = networking::HostDnsInfo::GetDnsSettings(networking::DnsSettingsFlags::IncludeVpn);
|
||||
if (currentDns != m_trackedDnsSettings)
|
||||
{
|
||||
m_trackedDnsSettings = currentDns;
|
||||
@ -274,7 +275,7 @@ void VirtioNetworking::SendDnsUpdate(const networking::DnsInfo& dnsSettings)
|
||||
hns::ModifyGuestEndpointSettingRequest<hns::DNS> notification{};
|
||||
notification.RequestType = hns::ModifyRequestType::Update;
|
||||
notification.ResourceType = hns::GuestEndpointResourceType::DNS;
|
||||
notification.Settings = networking::BuildDnsNotification(dnsSettings);
|
||||
notification.Settings = networking::BuildDnsNotification(dnsSettings, m_dnsOptions);
|
||||
m_gnsChannel.SendHnsNotification(ToJsonW(notification).c_str(), m_adapterId);
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ namespace wsl::core {
|
||||
class VirtioNetworking : public INetworkingEngine
|
||||
{
|
||||
public:
|
||||
VirtioNetworking(GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken);
|
||||
VirtioNetworking(GnsChannel&& gnsChannel, bool enableLocalhostRelay, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken);
|
||||
~VirtioNetworking();
|
||||
|
||||
// Note: This class cannot be moved because m_networkNotifyHandle captures a 'this' pointer.
|
||||
@ -49,12 +49,12 @@ private:
|
||||
std::optional<GnsPortTrackerChannel> m_gnsPortTrackerChannel;
|
||||
std::shared_ptr<networking::NetworkSettings> m_networkSettings;
|
||||
bool m_enableLocalhostRelay;
|
||||
LPCWSTR m_dnsOptions = nullptr;
|
||||
GUID m_localhostAdapterId;
|
||||
GUID m_adapterId;
|
||||
|
||||
std::optional<ULONGLONG> m_interfaceLuid;
|
||||
ULONG m_networkMtu = 0;
|
||||
networking::DnsUpdateHelper m_dnsUpdateHelper;
|
||||
networking::DnsInfo m_trackedDnsSettings;
|
||||
|
||||
// Note: this field must be destroyed first to stop the callbacks before any other field is destroyed.
|
||||
|
||||
@ -105,12 +105,6 @@ wsl::core::networking::DnsInfo wsl::core::networking::HostDnsInfo::GetDnsTunneli
|
||||
return dnsInfo;
|
||||
}
|
||||
|
||||
std::vector<wsl::core::networking::IpAdapterAddress> wsl::core::networking::HostDnsInfo::GetAdapterAddresses()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
return m_addresses;
|
||||
}
|
||||
|
||||
std::vector<std::string> wsl::core::networking::HostDnsInfo::GetDnsServerStrings(
|
||||
_In_ const PIP_ADAPTER_DNS_SERVER_ADDRESS& FirstDnsServer, _In_ USHORT IpFamilyFilter, _In_ USHORT MaxValues)
|
||||
{
|
||||
@ -233,7 +227,7 @@ std::vector<std::string> wsl::core::networking::HostDnsInfo::GetInterfaceDnsSuff
|
||||
|
||||
wsl::core::networking::DnsInfo wsl::core::networking::HostDnsInfo::GetDnsSettings(_In_ DnsSettingsFlags Flags)
|
||||
{
|
||||
std::vector<IpAdapterAddress> Addresses = GetAdapterAddresses();
|
||||
std::vector<IpAdapterAddress> Addresses = AdapterAddresses::GetCurrent();
|
||||
|
||||
auto RemoveFilter = [&](const IpAdapterAddress& Address) {
|
||||
// Ignore interfaces that are not currently "up".
|
||||
@ -326,12 +320,6 @@ wsl::core::networking::DnsInfo wsl::core::networking::HostDnsInfo::GetDnsSetting
|
||||
return DnsSettings;
|
||||
}
|
||||
|
||||
void wsl::core::networking::HostDnsInfo::UpdateNetworkInformation()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
m_addresses = AdapterAddresses::GetCurrent();
|
||||
}
|
||||
|
||||
std::string wsl::core::networking::GenerateResolvConf(_In_ const DnsInfo& Info)
|
||||
{
|
||||
std::string contents{};
|
||||
@ -345,7 +333,10 @@ std::string wsl::core::networking::GenerateResolvConf(_In_ const DnsInfo& Info)
|
||||
contents += c_asciiNewLine;
|
||||
}
|
||||
|
||||
// Add domain information if it is available.
|
||||
// Add DNS suffix information using 'search' directive.
|
||||
// Per resolv.conf(5): "The domain directive is an obsolete name for the search directive
|
||||
// that handles one search list entry only."
|
||||
// See: https://man7.org/linux/man-pages/man5/resolv.conf.5.html
|
||||
if (!Info.Domains.empty())
|
||||
{
|
||||
contents += "search ";
|
||||
@ -497,28 +488,21 @@ wsl::core::networking::DnsSuffixRegistryWatcher::DnsSuffixRegistryWatcher(Regist
|
||||
m_registryWatchers.swap(localRegistryWatchers);
|
||||
}
|
||||
|
||||
wsl::shared::hns::DNS wsl::core::networking::BuildDnsNotification(const DnsInfo& settings, bool useLinuxDomainEntry)
|
||||
wsl::shared::hns::DNS wsl::core::networking::BuildDnsNotification(const DnsInfo& settings, PCWSTR options)
|
||||
{
|
||||
wsl::shared::hns::DNS dnsNotification{};
|
||||
dnsNotification.Options = LX_INIT_RESOLVCONF_FULL_HEADER;
|
||||
if (options)
|
||||
{
|
||||
dnsNotification.Options = options;
|
||||
}
|
||||
|
||||
dnsNotification.ServerList = wsl::shared::string::MultiByteToWide(wsl::shared::string::Join(settings.Servers, ','));
|
||||
|
||||
if (useLinuxDomainEntry && !settings.Domains.empty())
|
||||
{
|
||||
// Use 'domain' entry for single DNS suffix (typically used when mirroring host DNS without tunneling)
|
||||
dnsNotification.Domain = wsl::shared::string::MultiByteToWide(settings.Domains.front());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use 'search' entry for DNS suffix list
|
||||
dnsNotification.Search = wsl::shared::string::MultiByteToWide(wsl::shared::string::Join(settings.Domains, ','));
|
||||
}
|
||||
// Use 'search' entry for DNS suffix list.
|
||||
// Per resolv.conf(5): "The domain directive is an obsolete name for the search directive
|
||||
// that handles one search list entry only."
|
||||
// See: https://man7.org/linux/man-pages/man5/resolv.conf.5.html
|
||||
dnsNotification.Search = wsl::shared::string::MultiByteToWide(wsl::shared::string::Join(settings.Domains, ','));
|
||||
|
||||
return dnsNotification;
|
||||
}
|
||||
|
||||
wsl::core::networking::DnsInfo wsl::core::networking::DnsUpdateHelper::GetCurrentDnsSettings(DnsSettingsFlags flags)
|
||||
{
|
||||
m_hostDnsInfo.UpdateNetworkInformation();
|
||||
return m_hostDnsInfo.GetDnsSettings(flags);
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -42,9 +41,9 @@ std::string GenerateResolvConf(_In_ const DnsInfo& Info);
|
||||
/// Builds an hns::DNS notification from DnsInfo settings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The DNS settings to convert</param>
|
||||
/// <param name="useLinuxDomainEntry">If true, uses 'domain' entry for single suffix; otherwise uses 'search' for all
|
||||
/// suffixes</param> <returns>The hns::DNS notification ready to send via GNS channel</returns>
|
||||
wsl::shared::hns::DNS BuildDnsNotification(const DnsInfo& settings, bool useLinuxDomainEntry = false);
|
||||
/// <param name="options">The resolv.conf header options (defaults to LX_INIT_RESOLVCONF_FULL_HEADER)</param>
|
||||
/// <returns>The hns::DNS notification ready to send via GNS channel</returns>
|
||||
wsl::shared::hns::DNS BuildDnsNotification(const DnsInfo& settings, PCWSTR options = LX_INIT_RESOLVCONF_FULL_HEADER);
|
||||
|
||||
std::vector<std::string> GetAllDnsSuffixes(const std::vector<IpAdapterAddress>& AdapterAddresses);
|
||||
|
||||
@ -53,27 +52,15 @@ DWORD GetBestInterface();
|
||||
class HostDnsInfo
|
||||
{
|
||||
public:
|
||||
DnsInfo GetDnsSettings(_In_ DnsSettingsFlags Flags);
|
||||
|
||||
void UpdateNetworkInformation();
|
||||
static DnsInfo GetDnsSettings(_In_ DnsSettingsFlags Flags);
|
||||
|
||||
static DnsInfo GetDnsTunnelingSettings(const std::wstring& dnsTunnelingNameserver);
|
||||
|
||||
const std::vector<IpAdapterAddress>& CurrentAddresses() const
|
||||
{
|
||||
return m_addresses;
|
||||
}
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Internal function to retrieve the latest copy of interface information.
|
||||
/// </summary>
|
||||
std::vector<IpAdapterAddress> GetAdapterAddresses();
|
||||
|
||||
/// <summary>
|
||||
/// Internal function to retrieve interface DNS servers.
|
||||
/// </summary>
|
||||
std::vector<std::string> GetInterfaceDnsServers(const std::vector<IpAdapterAddress>& AdapterAddresses, _In_ DnsSettingsFlags Flags);
|
||||
static std::vector<std::string> GetInterfaceDnsServers(const std::vector<IpAdapterAddress>& AdapterAddresses, _In_ DnsSettingsFlags Flags);
|
||||
|
||||
/// <summary>
|
||||
/// Internal function to retrieve all Windows DNS suffixes.
|
||||
@ -84,30 +71,6 @@ private:
|
||||
/// Internal function to convert DNS server addresses into strings.
|
||||
/// </summary>
|
||||
static std::vector<std::string> GetDnsServerStrings(_In_ const PIP_ADAPTER_DNS_SERVER_ADDRESS& DnsServer, _In_ USHORT IpFamilyFilter, _In_ USHORT MaxValues);
|
||||
|
||||
/// <summary>
|
||||
/// Stores latest copy of interface information.
|
||||
/// </summary>
|
||||
std::mutex m_lock;
|
||||
_Guarded_by_(m_lock) std::vector<IpAdapterAddress> m_addresses;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Helper class that fetches current DNS settings from the host.
|
||||
/// Callers are responsible for tracking changes if needed.
|
||||
/// </summary>
|
||||
class DnsUpdateHelper
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Fetches current DNS settings from the host.
|
||||
/// </summary>
|
||||
/// <param name="flags">Flags controlling which DNS settings to include</param>
|
||||
/// <returns>Current DNS settings</returns>
|
||||
DnsInfo GetCurrentDnsSettings(DnsSettingsFlags flags);
|
||||
|
||||
private:
|
||||
HostDnsInfo m_hostDnsInfo;
|
||||
};
|
||||
|
||||
using RegistryChangeCallback = std::function<void()>;
|
||||
|
||||
@ -784,9 +784,6 @@ try
|
||||
// Impersonate the service.
|
||||
auto runAsSelf = wil::run_as_self();
|
||||
|
||||
// Update the instance's DNS information.
|
||||
m_dnsInfo.UpdateNetworkInformation();
|
||||
|
||||
// Update the resolv.conf file if it has changed.
|
||||
_UpdateNetworkConfigurationFiles(false);
|
||||
return;
|
||||
@ -799,7 +796,7 @@ void LxssInstance::_UpdateNetworkConfigurationFiles(_In_ bool UpdateAlways)
|
||||
wsl::core::networking::DnsSettingsFlags flags = wsl::core::networking::DnsSettingsFlags::IncludeIpv6Servers;
|
||||
WI_SetFlagIf(flags, wsl::core::networking::DnsSettingsFlags::IncludeVpn, m_enableVpnDetection);
|
||||
|
||||
const auto dnsSettings = m_dnsInfo.GetDnsSettings(flags);
|
||||
const auto dnsSettings = wsl::core::networking::HostDnsInfo::GetDnsSettings(flags);
|
||||
std::string fileContents = GenerateResolvConf(dnsSettings);
|
||||
std::lock_guard<std::mutex> lock(m_resolvConfLock);
|
||||
if (!UpdateAlways && (fileContents == m_lastResolvConfContents))
|
||||
|
||||
@ -224,11 +224,6 @@ private:
|
||||
/// </summary>
|
||||
LxssIpTables m_ipTables;
|
||||
|
||||
/// <summary>
|
||||
/// Class for querying host dns information.
|
||||
/// </summary>
|
||||
wsl::core::networking::HostDnsInfo m_dnsInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Settings for updating /etc/resolv.conf.
|
||||
/// </summary>
|
||||
|
||||
@ -570,7 +570,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
|
||||
else if (m_vmConfig.NetworkingMode == NetworkingMode::VirtioProxy)
|
||||
{
|
||||
m_networkingEngine = std::make_unique<wsl::core::VirtioNetworking>(
|
||||
std::move(gnsChannel), m_vmConfig.EnableLocalhostRelay, m_guestDeviceManager, m_userToken);
|
||||
std::move(gnsChannel), m_vmConfig.EnableLocalhostRelay, LX_INIT_RESOLVCONF_FULL_HEADER, m_guestDeviceManager, m_userToken);
|
||||
}
|
||||
else if (m_vmConfig.NetworkingMode == NetworkingMode::Bridged)
|
||||
{
|
||||
@ -845,9 +845,6 @@ void WslCoreVm::AddDrvFsShare(_In_ bool Admin, _In_ HANDLE UserToken)
|
||||
{
|
||||
// Add virtiofs devices associating indices with paths from the fixed drive bitmap. These devices support
|
||||
// multiple mounts in the guest, so this only needs to be done once.
|
||||
// EX: drvfsC1 => C:\
|
||||
// drvfsD2 => D:\
|
||||
// drvfsaC3 => C:\ (elevated)
|
||||
auto fixedDrives = wsl::windows::common::filesystem::EnumerateFixedDrives(UserToken).first;
|
||||
while (fixedDrives != 0)
|
||||
{
|
||||
@ -2084,7 +2081,7 @@ void WslCoreVm::WaitForPmemDeviceInVm(_In_ ULONG PmemId)
|
||||
_Requires_lock_held_(m_guestDeviceLock)
|
||||
std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ PCWSTR Options, _In_opt_ HANDLE UserToken)
|
||||
{
|
||||
WI_ASSERT(m_vmConfig.EnableVirtioFs && wsl::shared::string::IsDriveRoot(wsl::shared::string::WideToMultiByte(Path)));
|
||||
WI_ASSERT(m_vmConfig.EnableVirtioFs);
|
||||
|
||||
if (!ARGUMENT_PRESENT(UserToken))
|
||||
{
|
||||
@ -2095,22 +2092,27 @@ std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_
|
||||
WI_ASSERT(Admin == wsl::windows::common::security::IsTokenElevated(UserToken));
|
||||
|
||||
// Ensure that the path has a trailing path separator.
|
||||
std::wstring sharePath{Path};
|
||||
if (sharePath.back() != L'\\')
|
||||
std::wstring sharePath(Path);
|
||||
if (!sharePath.ends_with(L'\\') && !sharePath.ends_with(L'/'))
|
||||
{
|
||||
sharePath += L'\\';
|
||||
sharePath.push_back(L'\\');
|
||||
}
|
||||
|
||||
sharePath = std::filesystem::weakly_canonical(sharePath).wstring();
|
||||
|
||||
// Check if a matching share already exists.
|
||||
bool created = false;
|
||||
std::wstring tag;
|
||||
VirtioFsShare key(sharePath.c_str(), Options, Admin);
|
||||
if (!m_virtioFsShares.contains(key))
|
||||
{
|
||||
// Generate a new tag for the share.
|
||||
tag = Admin ? TEXT(LX_INIT_DRVFS_ADMIN_VIRTIO_TAG) : TEXT(LX_INIT_DRVFS_VIRTIO_TAG);
|
||||
tag += sharePath[0];
|
||||
tag += std::to_wstring(m_virtioFsShares.size());
|
||||
// Generate a new unique tag for the share.
|
||||
//
|
||||
// N.B. The tag can be maximum 36 characters long so a GUID without braces fits perfectly.
|
||||
GUID tagGuid{};
|
||||
THROW_IF_FAILED(CoCreateGuid(&tagGuid));
|
||||
|
||||
tag = wsl::shared::string::GuidToString<wchar_t>(tagGuid, wsl::shared::string::None);
|
||||
WI_ASSERT(!FindVirtioFsShare(tag.c_str(), Admin));
|
||||
|
||||
(void)m_guestDeviceManager->AddGuestDevice(
|
||||
@ -2546,8 +2548,6 @@ try
|
||||
THROW_HR_IF(E_UNEXPECTED, !addShare);
|
||||
|
||||
const auto path = wsl::shared::string::FromSpan(span, addShare->PathOffset);
|
||||
THROW_HR_IF_MSG(E_INVALIDARG, !wsl::shared::string::IsDriveRoot(path), "%hs is not the root of a drive", path);
|
||||
|
||||
const auto pathWide = wsl::shared::string::MultiByteToWide(path);
|
||||
const auto options = wsl::shared::string::FromSpan(span, addShare->OptionsOffset);
|
||||
const auto optionsWide = wsl::shared::string::MultiByteToWide(options);
|
||||
@ -2567,19 +2567,6 @@ try
|
||||
THROW_HR_IF(E_UNEXPECTED, !remountShare);
|
||||
|
||||
const std::string tag = wsl::shared::string::FromSpan(span, remountShare->TagOffset);
|
||||
if (tag.find(LX_INIT_DRVFS_ADMIN_VIRTIO_TAG, 0) == 0)
|
||||
{
|
||||
THROW_HR_IF(E_UNEXPECTED, remountShare->Admin);
|
||||
}
|
||||
else if (tag.find(LX_INIT_DRVFS_VIRTIO_TAG, 0) == 0)
|
||||
{
|
||||
THROW_HR_IF(E_UNEXPECTED, !remountShare->Admin);
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_HR_MSG(E_UNEXPECTED, "Unexpected tag %hs", tag.data());
|
||||
}
|
||||
|
||||
const auto tagWide = wsl::shared::string::MultiByteToWide(tag);
|
||||
auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
|
||||
const auto foundShare = FindVirtioFsShare(tagWide.c_str(), !remountShare->Admin);
|
||||
@ -2590,6 +2577,24 @@ try
|
||||
|
||||
respondWithTag(newTag, result);
|
||||
}
|
||||
else if (message->MessageType == LxInitMessageQueryVirtioFsDevice)
|
||||
{
|
||||
std::wstring newTag;
|
||||
const auto result = wil::ResultFromException([this, span, &newTag]() {
|
||||
const auto* query = gslhelpers::try_get_struct<LX_INIT_QUERY_VIRTIOFS_SHARE_MESSAGE>(span);
|
||||
THROW_HR_IF(E_UNEXPECTED, !query);
|
||||
|
||||
const std::string tag = wsl::shared::string::FromSpan(span, query->TagOffset);
|
||||
const auto tagWide = wsl::shared::string::MultiByteToWide(tag);
|
||||
auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
|
||||
const auto foundShare = FindVirtioFsShare(tagWide.c_str());
|
||||
THROW_HR_IF_MSG(E_UNEXPECTED, !foundShare.has_value(), "Unknown tag %ls", tagWide.c_str());
|
||||
|
||||
newTag = foundShare->Path;
|
||||
});
|
||||
|
||||
respondWithTag(newTag, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_HR_MSG(E_UNEXPECTED, "Unexpected MessageType %d", message->MessageType);
|
||||
|
||||
@ -434,8 +434,7 @@ void wsl::core::networking::WslMirroredNetworkManager::ProcessDNSChange()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hostDnsInfo.UpdateNetworkInformation();
|
||||
m_dnsInfo = m_hostDnsInfo.GetDnsSettings(
|
||||
m_dnsInfo = wsl::core::networking::HostDnsInfo::GetDnsSettings(
|
||||
wsl::core::networking::DnsSettingsFlags::IncludeVpn | wsl::core::networking::DnsSettingsFlags::IncludeIpv6Servers |
|
||||
wsl::core::networking::DnsSettingsFlags::IncludeAllSuffixes);
|
||||
}
|
||||
|
||||
@ -224,9 +224,6 @@ private:
|
||||
_Guarded_by_(m_networkLock) DnsInfo m_trackedDnsInfo;
|
||||
// The current DNS info on the host
|
||||
_Guarded_by_(m_networkLock) DnsInfo m_dnsInfo;
|
||||
// m_hostDnsInfo is an optimization used to avoid allocating a large buffer every time we call
|
||||
// GetAdaptersAddresses when querying host DNS info
|
||||
_Guarded_by_(m_networkLock) HostDnsInfo m_hostDnsInfo;
|
||||
|
||||
std::wstring m_dnsTunnelingIpAddress;
|
||||
|
||||
|
||||
@ -561,11 +561,13 @@ void WSLAVirtualMachine::ConfigureNetworking()
|
||||
wsl::core::NatNetworking::CreateNetwork(config),
|
||||
std::move(gnsChannel),
|
||||
config,
|
||||
dnsChannelFd != -1 ? wil::unique_socket{(SOCKET)process->GetStdHandle(dnsChannelFd).release()} : wil::unique_socket{});
|
||||
dnsChannelFd != -1 ? wil::unique_socket{(SOCKET)process->GetStdHandle(dnsChannelFd).release()} : wil::unique_socket{},
|
||||
nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_networkEngine = std::make_unique<wsl::core::VirtioNetworking>(std::move(gnsChannel), false, m_guestDeviceManager, m_userToken);
|
||||
m_networkEngine =
|
||||
std::make_unique<wsl::core::VirtioNetworking>(std::move(gnsChannel), false, nullptr, m_guestDeviceManager, m_userToken);
|
||||
}
|
||||
|
||||
m_networkEngine->Initialize();
|
||||
|
||||
@ -294,7 +294,7 @@ Return Value:
|
||||
snprintf(
|
||||
Plan9Options,
|
||||
sizeof(Plan9Options),
|
||||
"aname=drvfs;path=%s%s;symlinkroot=/mnt/,cache=5,access=client,msize=65536,trans=fd,rfd=4,wfd=4",
|
||||
"aname=drvfs;path=%s%s;symlinkroot=/mnt/,cache=5,access=client,msize=65536,trans=fd,rfd=*,wfd=*",
|
||||
Plan9Source,
|
||||
Temp);
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ Abstract:
|
||||
#define PATH_MAX (4096)
|
||||
|
||||
void MountEscapeString(const char* Source, char* Dest, size_t Length);
|
||||
int MountCheckFsOptionsPattern(const char* Pattern, const char* Actual);
|
||||
|
||||
int MountCheckIsMount(
|
||||
const char* Path,
|
||||
@ -127,7 +128,14 @@ Return Value:
|
||||
LxtCheckStringEqual(ExpectedMountOptions, mnt_fs_get_vfs_options(FileSystem));
|
||||
if (ExpectedFsOptions != NULL)
|
||||
{
|
||||
LxtCheckStringEqual(ExpectedFsOptions, mnt_fs_get_fs_options(FileSystem));
|
||||
if (strchr(ExpectedFsOptions, '*') != NULL)
|
||||
{
|
||||
LxtCheckResult(MountCheckFsOptionsPattern(ExpectedFsOptions, mnt_fs_get_fs_options(FileSystem)));
|
||||
}
|
||||
else
|
||||
{
|
||||
LxtCheckStringEqual(ExpectedFsOptions, mnt_fs_get_fs_options(FileSystem));
|
||||
}
|
||||
}
|
||||
|
||||
LxtCheckEqual(Stat.st_dev, mnt_fs_get_devno(FileSystem), "%lu");
|
||||
@ -235,6 +243,109 @@ ErrorExit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
int MountCheckFsOptionsPattern(const char* Pattern, const char* Actual)
|
||||
|
||||
/*++
|
||||
|
||||
Description:
|
||||
|
||||
This routine checks if mount options match a pattern with wildcards.
|
||||
The '*' wildcard matches any sequence of characters.
|
||||
|
||||
Arguments:
|
||||
|
||||
Pattern - Supplies the expected pattern (e.g., "rfd=*,wfd=*").
|
||||
|
||||
Actual - Supplies the actual mount options string.
|
||||
|
||||
Return Value:
|
||||
|
||||
Returns 0 on success, -1 on failure.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
|
||||
const char* ActualPtr;
|
||||
const char* MatchPosition;
|
||||
const char* PatternPtr;
|
||||
int Result;
|
||||
const char* StarPosition;
|
||||
|
||||
PatternPtr = Pattern;
|
||||
ActualPtr = Actual;
|
||||
StarPosition = NULL;
|
||||
MatchPosition = NULL;
|
||||
Result = LXT_RESULT_FAILURE;
|
||||
|
||||
while (*ActualPtr != '\0')
|
||||
{
|
||||
if (*PatternPtr == '*')
|
||||
{
|
||||
//
|
||||
// Remember position of * and where we are in actual string.
|
||||
//
|
||||
|
||||
StarPosition = PatternPtr++;
|
||||
MatchPosition = ActualPtr;
|
||||
}
|
||||
else if (*PatternPtr == *ActualPtr)
|
||||
{
|
||||
//
|
||||
// Characters match, advance both.
|
||||
//
|
||||
|
||||
PatternPtr++;
|
||||
ActualPtr++;
|
||||
}
|
||||
else if (StarPosition != NULL)
|
||||
{
|
||||
//
|
||||
// Mismatch but we have a *, backtrack and try matching one more character.
|
||||
//
|
||||
|
||||
PatternPtr = StarPosition + 1;
|
||||
ActualPtr = ++MatchPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Mismatch and no * to backtrack to.
|
||||
//
|
||||
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Consume any trailing *'s in pattern.
|
||||
//
|
||||
|
||||
while (*PatternPtr == '*')
|
||||
{
|
||||
PatternPtr++;
|
||||
}
|
||||
|
||||
//
|
||||
// Both should be at end of string.
|
||||
//
|
||||
|
||||
if (*PatternPtr != '\0')
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
Result = LXT_RESULT_SUCCESS;
|
||||
|
||||
ErrorExit:
|
||||
if (!LXT_SUCCESS(Result))
|
||||
{
|
||||
LxtLogError("Mount options mismatch: expected '%s', got '%s'", Pattern, Actual);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void MountEscapeString(const char* Source, char* Dest, size_t Length)
|
||||
|
||||
/*++
|
||||
|
||||
@ -1706,11 +1706,7 @@ Return Value:
|
||||
|
||||
if (LxsstuVmMode())
|
||||
{
|
||||
std::wstring Command = L"/bin/cp /data/test/log/";
|
||||
Command += LogFileToken;
|
||||
Command += L" $(wslpath '";
|
||||
Command += LinuxLogPath;
|
||||
Command += L"')";
|
||||
std::wstring Command = std::format(L"/bin/cp /data/test/log/{} $(wslpath '{}')", LogFileToken, LinuxLogPath);
|
||||
VERIFY_NO_THROW(LxsstuRunTest(Command.c_str()));
|
||||
}
|
||||
|
||||
|
||||
@ -226,12 +226,6 @@ public:
|
||||
{
|
||||
SKIP_TEST_ARM64();
|
||||
|
||||
if (Mode == DrvFsMode::VirtioFs)
|
||||
{
|
||||
LogSkipped("VirtioFS currently only supports mounting full drives");
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr auto MountPoint = "C:\\lxss_fat";
|
||||
constexpr auto VhdPath = "C:\\lxss_fat.vhdx";
|
||||
auto Cleanup = wil::scope_exit([MountPoint, VhdPath] { DeleteVolume(MountPoint, VhdPath); });
|
||||
@ -352,12 +346,6 @@ public:
|
||||
SKIP_TEST_ARM64();
|
||||
WSL_TEST_VERSION_REQUIRED(wsl::windows::common::helpers::WindowsBuildNumbers::Germanium);
|
||||
|
||||
if (Mode == DrvFsMode::VirtioFs)
|
||||
{
|
||||
LogSkipped("VirtioFS currently only supports mounting full drives");
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr auto MountPoint = "C:\\lxss_refs";
|
||||
constexpr auto VhdPath = "C:\\lxss_refs.vhdx";
|
||||
auto Cleanup = wil::scope_exit([MountPoint, VhdPath] { DeleteVolume(MountPoint, VhdPath); });
|
||||
@ -367,6 +355,68 @@ public:
|
||||
LxsstuRunTest((L"bash -c '" + SkipUnstableTestEnvVar + L" /data/test/wsl_unit_tests drvfs -m 6'").c_str(), L"drvfs6"));
|
||||
}
|
||||
|
||||
void WslPath(DrvFsMode Mode)
|
||||
{
|
||||
VERIFY_NO_THROW(LxsstuRunTest(L"/data/test/wsl_unit_tests wslpath", L"wslpath"));
|
||||
|
||||
auto testWslPath = [](const std::wstring& testDir) {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { std::filesystem::remove_all(testDir); });
|
||||
|
||||
std::filesystem::create_directory(testDir);
|
||||
|
||||
auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath -aw '{}'", testDir));
|
||||
VERIFY_ARE_EQUAL((std::filesystem::canonical(std::filesystem::current_path()) / testDir).wstring() + L"\n", out);
|
||||
|
||||
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath -wa '{}'", testDir));
|
||||
VERIFY_ARE_EQUAL((std::filesystem::canonical(std::filesystem::current_path()) / testDir).wstring() + L"\n", out);
|
||||
|
||||
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath '{}'", testDir));
|
||||
VERIFY_ARE_EQUAL(std::format(L"{}\n", testDir), out);
|
||||
|
||||
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath -a '{}'", testDir));
|
||||
VERIFY_IS_TRUE(out.find(L"/mnt/") == 0);
|
||||
};
|
||||
|
||||
testWslPath(L"wslpath-test-dir");
|
||||
testWslPath(L"wslpath-测试目录-テスト");
|
||||
}
|
||||
|
||||
void DrvFsMountUnicodePath(DrvFsMode Mode)
|
||||
{
|
||||
WSL2_TEST_ONLY();
|
||||
|
||||
// Create a Windows directory with unicode characters
|
||||
constexpr auto unicodeDir = L"C:\\drvfs-测试-テスト";
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { std::filesystem::remove_all(unicodeDir); });
|
||||
|
||||
std::filesystem::create_directory(unicodeDir);
|
||||
|
||||
// Create a test file inside the directory
|
||||
const auto testFilePath = std::filesystem::path(unicodeDir) / L"test-file.txt";
|
||||
{
|
||||
std::ofstream testFile(testFilePath);
|
||||
testFile << "hello from unicode path";
|
||||
}
|
||||
|
||||
// Mount the unicode directory using mount -t drvfs
|
||||
constexpr auto mountPoint = L"/tmp/unicode-mount-test";
|
||||
auto unmountCleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
|
||||
LxsstuLaunchWsl(std::format(L"-u root umount '{}'", mountPoint).c_str());
|
||||
LxsstuLaunchWsl(std::format(L"-u root rmdir '{}'", mountPoint).c_str());
|
||||
});
|
||||
|
||||
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"-u root mkdir -p '{}'", mountPoint).c_str()), 0);
|
||||
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"-u root mount -t drvfs '{}' '{}'", unicodeDir, mountPoint).c_str()), 0);
|
||||
|
||||
// Verify we can read the test file through the mount
|
||||
auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"cat '{}/test-file.txt'", mountPoint));
|
||||
VERIFY_ARE_EQUAL(L"hello from unicode path", out);
|
||||
|
||||
// Verify we can list the directory
|
||||
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"ls '{}'", mountPoint));
|
||||
VERIFY_IS_TRUE(out.find(L"test-file.txt") != std::wstring::npos);
|
||||
}
|
||||
|
||||
// DrvFsTests Private Methods
|
||||
private:
|
||||
static VOID CreateDrvFsTestFiles(bool Metadata)
|
||||
@ -935,7 +985,11 @@ private:
|
||||
const auto lines = LxssSplitString(output.Stdout, L"\n");
|
||||
|
||||
VERIFY_ARE_EQUAL(lines.size(), 1);
|
||||
VERIFY_IS_TRUE(output.Stdout.find(expectedType) == 0);
|
||||
|
||||
if (!expectedType.empty())
|
||||
{
|
||||
VERIFY_IS_TRUE(output.Stdout.find(expectedType) == 0);
|
||||
}
|
||||
};
|
||||
|
||||
std::wstring elevatedType;
|
||||
@ -951,8 +1005,7 @@ private:
|
||||
nonElevatedType = L"drvfs";
|
||||
break;
|
||||
case DrvFsMode::VirtioFs:
|
||||
elevatedType = L"drvfsaC";
|
||||
nonElevatedType = L"drvfsC";
|
||||
// VirtioFs uses GUIDs as the tag so the value is not predictable.
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1149,6 +1202,12 @@ class WSL1 : public DrvFsTests
|
||||
WSL1_TEST_ONLY();
|
||||
DrvFsTests::XattrDrvFs(DrvFsMode::WSL1);
|
||||
}
|
||||
|
||||
TEST_METHOD(WslPath)
|
||||
{
|
||||
WSL1_TEST_ONLY();
|
||||
DrvFsTests::WslPath(DrvFsMode::WSL1);
|
||||
}
|
||||
};
|
||||
|
||||
#define WSL2_DRVFS_TEST_CLASS(_mode) \
|
||||
@ -1266,6 +1325,18 @@ class WSL1 : public DrvFsTests
|
||||
WSL2_TEST_ONLY(); \
|
||||
DrvFsTests::DrvFsReFs(DrvFsMode::##_mode##); \
|
||||
} \
|
||||
\
|
||||
TEST_METHOD(WslPath) \
|
||||
{ \
|
||||
WSL2_TEST_ONLY(); \
|
||||
DrvFsTests::WslPath(DrvFsMode::##_mode##); \
|
||||
} \
|
||||
\
|
||||
TEST_METHOD(DrvFsMountUnicodePath) \
|
||||
{ \
|
||||
WSL2_TEST_ONLY(); \
|
||||
DrvFsTests::DrvFsMountUnicodePath(DrvFsMode::##_mode##); \
|
||||
} \
|
||||
}
|
||||
|
||||
WSL2_DRVFS_TEST_CLASS(Plan9);
|
||||
|
||||
@ -1037,7 +1037,6 @@ class NetworkTests
|
||||
|
||||
wsl::shared::hns::DNS dns;
|
||||
dns.ServerList = L"1.1.1.1,1.1.1.2";
|
||||
dns.Domain = L"microsoft.com";
|
||||
dns.Search = L"foo.microsoft.com,bar.microsoft.com";
|
||||
dns.Options = LX_INIT_RESOLVCONF_FULL_HEADER;
|
||||
RunGns(dns, ModifyRequestType::Update, GuestEndpointResourceType::DNS);
|
||||
@ -1047,7 +1046,6 @@ class NetworkTests
|
||||
const std::wstring expected = std::wstring(LX_INIT_RESOLVCONF_FULL_HEADER) +
|
||||
L"nameserver 1.1.1.1\n"
|
||||
L"nameserver 1.1.1.2\n"
|
||||
L"domain microsoft.com\n"
|
||||
L"search foo.microsoft.com bar.microsoft.com\n";
|
||||
VERIFY_ARE_EQUAL(expected, out.c_str());
|
||||
}
|
||||
@ -4612,6 +4610,9 @@ class VirtioProxyTests
|
||||
const std::wregex pattern(L"(.|\\n)*nameserver [0-9. ]+(.|\\n)*");
|
||||
|
||||
VERIFY_IS_TRUE(std::regex_match(out, pattern));
|
||||
|
||||
// Verify that /etc/resolv.conf contains a 'search' line with DNS suffixes
|
||||
VERIFY_IS_TRUE(out.find(L"search ") != std::wstring::npos);
|
||||
}
|
||||
|
||||
TEST_METHOD(GuestPortIsReleased)
|
||||
|
||||
@ -878,11 +878,6 @@ class UnitTests
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(WslPath)
|
||||
{
|
||||
VERIFY_NO_THROW(LxsstuRunTest(L"/data/test/wsl_unit_tests wslpath", L"wslpath"));
|
||||
}
|
||||
|
||||
TEST_METHOD(FsTab)
|
||||
{
|
||||
//
|
||||
@ -5958,25 +5953,6 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
|
||||
VERIFY_IS_TRUE(a);
|
||||
VERIFY_ARE_EQUAL(pos, L"-");
|
||||
}
|
||||
|
||||
{
|
||||
constexpr auto testDir = "wslpath-test-dir";
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { std::filesystem::remove_all(testDir); });
|
||||
|
||||
std::filesystem::create_directory(testDir);
|
||||
|
||||
auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath -aw {}", testDir));
|
||||
VERIFY_ARE_EQUAL((std::filesystem::canonical(std::filesystem::current_path()) / testDir).wstring() + L"\n", out);
|
||||
|
||||
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath -wa {}", testDir));
|
||||
VERIFY_ARE_EQUAL((std::filesystem::canonical(std::filesystem::current_path()) / testDir).wstring() + L"\n", out);
|
||||
|
||||
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath {}", testDir));
|
||||
VERIFY_ARE_EQUAL(std::format(L"{}\n", testDir), out);
|
||||
|
||||
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"wslpath -a {}", testDir));
|
||||
VERIFY_IS_TRUE(out.find(L"/mnt/") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseSensitivity)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user