lima
lima copied to clipboard
Use short path for LIMA_HOME on windows
Other commands such as qemu-system-x86_64.exe don't work with
C:\Users\AndersBjörklund, they need to use C:\Users\ANDERS~1
In theory they could have supported using UNC paths such as
\\?\C:\Users\AndersBjörklund, but in practice they do not...
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getshortpathnamew
A long file name is considered to be any file name that exceeds the short MS-DOS (also called 8.3) style naming convention.
GOOS=linux (host)
=== RUN TestShortNameShort
shortname_test.go:20: /tmp/foo => /tmp/foo
--- PASS: TestShortNameShort (0.00s)
=== RUN TestShortNameLong
shortname_test.go:31: /tmp/baaaaaaaaaar => /tmp/baaaaaaaaaar
--- PASS: TestShortNameLong (0.00s)
PASS
GOOS=windows (wine)
=== RUN TestShortNameShort
shortname_test.go:20: C:\users\anders\Temp\foo => C:\users\anders\Temp\foo
--- PASS: TestShortNameShort (0.00s)
=== RUN TestShortNameLong
shortname_test.go:31: C:\users\anders\Temp\baaaaaaaaaar => C:\users\anders\Temp\BAAA~MWI
--- PASS: TestShortNameLong (0.00s)
PASS
C:\Users\AndersBjörklund, they need to use C:\Users\ANDERS~1
What if your home directory is like C:\Users\Björklund or C:\Users\漢字 ?
What if your home directory is like
C:\Users\BjörklundorC:\Users\漢字?
GetShortPathName will automatically translate them to 8.3 format (if the file exists; there is no way to generate a short name before creating the file, as the short name depends on what other files already exist in the directory). dir /x shows both the short and long names:
C:\Users\Jan\Names>dir /x
Volume in drive C has no label.
Volume Serial Number is 5C37-CD74
Directory of C:\Users\Jan\Names
07/12/2022 10:10 PM <DIR> .
07/12/2022 10:10 PM <DIR> ..
07/12/2022 10:08 PM <DIR> BJRKLU~1 Björklund
07/12/2022 10:08 PM <DIR> ED60~1 漢字
0 File(s) 0 bytes
4 Dir(s) 41,248,669,696 bytes free
C:\Users\Jan\Names>perl -MWin32 -E "say Win32::GetShortPathName('Björklund')"
BJRKLU~1
Note that the creation of 8.3 short names can be disabled by NTFS on a per-volume basis (search for HKLM\System\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation and fsutil 8dot3name). In that case GetShortPathName will still return the long name and not set an error.
Other commands such as
qemu-system-x86_64.exedon't work withC:\Users\AndersBjörklund, they need to useC:\Users\ANDERS~1
BTW, are you sure the problem is the long pathname and not some code page problem? It doesn't really matter though, as the short name algorithm always returns ASCII compatible strings, so you don't have to worry about encodings (unless people enable HKLM\System\CurrentControlSet\Control\FileSystem\NtfsAllowExtendedCharacterIn8dot3Name in which case they can only blame themselves).
Actually I think the problem is related to how Go handles paths in the exec.Command, when running from a prompt it seems to work. Unfortunately each program is required to handle parsing in Windows, and it seems to fail with the long names.
It could definitely be the unicode as well as the length, but the "fix" (workaround) would be the same either way. I'm not really a Windows person, I just saw this issue happening when it was run on a computer connected to the Active Directory.
There is some confusion between $HOME and os.UserHomeDir, but the plan is to go with the windows default (%HOMEDRIVE%HOMEPATH%)
i.e. for MSYS2 it will use something like C:\msys64\home\AndersBjörklund for the $HOME variable (in bash)
But for MinGW64 it will use C:\Users\AndersBjörklund and Command Prompt doesn't even have a %HOME%.
For corner cases, the user can override with $LIMA_HOME - maybe need something similar for the ssh variables (SSH_HOME?)
EDIT: Updated to use the proper dos variables
There is some confusion between $HOME and os.UserHomeDir, but the plan is to go with the windows default %HOMEPATH%
Note that %HOMEPATH% does not include the drive; you would need %HOMEDRIVE%%HOMEPATH%. However, I think you want to use %USERPROFILE% here, which is where application settings are stored. Homedrive/path often point to the same location, but don't have to.
On second thoughts, %LOCALAPPDATA%\Lima is where LIMA_HOME should live by default. Do not use %APPDATA%, which is the location of the roaming profile; it will be copied back and forth to the domain controller on login/logout, which will take forever to copy the full VM; it is only meant for small config files, like editor settings.
I was suspecting that "appdata" and friends had the same concern on Windows as on macOS, so didn't use them.
Didn't expect home to fail too, but here we are.
Actually I think the problem is related to how Go handles paths in the
exec.Command, when running from a prompt it seems to work.
This seems to confirm that the issue is an encoding problem, and not the long filenames.
I found this possible workaround (codepage 65001 is utf-8), but haven't tested it:
cmd := exec.Command("powershell.exe", "-c", "chcp", "65001", ">", "$null", ";", command)
Maybe even more gross than using short names. 😄
For myself, I only care about MSYS2 and MinGW64...
It is nice if the old school Command Prompt works too (if it isn't too much hassle, like a simple .bat file or something)
But I will not bother with Powershell, if the user is interested in Linux containers then I assume they have a decent shell.
Something like this: https://dilbert.com/strip/1995-06-24
However, I think you want to use
%USERPROFILE%here, which is where application settings are stored.
Actually, that is what is being done: https://pkg.go.dev/os#UserHomeDir
On Unix, including macOS, it returns the
$HOMEenvironment variable. On Windows, it returns%USERPROFILE%. On Plan 9, it returns the$homeenvironment variable.
The rest was just my own guesses, based on variables (which I botched)
But I will not bother with Powershell
This is not about the user using Powershell; it is just a way to switch the codepage before running the command. You can probably do the same thing with cmd.exe. Anyways, I don't really care; was just trying to provide some additional background info. I'm out of here now. 😄
However, I think you want to use
%USERPROFILE%here, which is where application settings are stored.Actually, that is what is being done: https://pkg.go.dev/os#UserHomeDir
I still think for this particular case %LOCALAPPDATA%\Lima is the right choice (which will typically be just %USERPROFILE%\AppData\Local\Lima. You don't want %USERPROFILE%\.lima because dot files are not a thing on Windows (they are not hidden by default). OTOH, if you only care about MSYS and MinGW64, then maybe dot files are the way to go... 🤷
We can have a poll later, but it is something nice about using the same path on all platforms ?
Also, we are not using the proper XDG directories on linux either - but polluting the home dir...
It was the same problem with ~/.docker/machine.
And also with other traditional tools, like ~/.ccache.
So I will stick with ~/.lima. Splitting up config and data can get very tricky, for these things.
Note that we are using the system cache directory (which is in AppData). os.UserCacheDir
So at least the downloads will end up there.
https://pkg.go.dev/os#UserCacheDir