lima icon indicating copy to clipboard operation
lima copied to clipboard

Use short path for LIMA_HOME on windows

Open afbjorklund opened this issue 3 years ago • 13 comments

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

afbjorklund avatar Jul 12 '22 20:07 afbjorklund

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\漢字 ?

AkihiroSuda avatar Jul 13 '22 02:07 AkihiroSuda

What if your home directory is like C:\Users\Björklund or C:\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.

jandubois avatar Jul 13 '22 05:07 jandubois

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

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).

jandubois avatar Jul 13 '22 05:07 jandubois

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.

afbjorklund avatar Jul 13 '22 05:07 afbjorklund

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

afbjorklund avatar Jul 13 '22 06:07 afbjorklund

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.

jandubois avatar Jul 13 '22 06:07 jandubois

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.

afbjorklund avatar Jul 13 '22 06:07 afbjorklund

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. 😄

jandubois avatar Jul 13 '22 06:07 jandubois

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

afbjorklund avatar Jul 13 '22 06:07 afbjorklund

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 $HOME environment variable. On Windows, it returns %USERPROFILE%. On Plan 9, it returns the $home environment variable.

The rest was just my own guesses, based on variables (which I botched)

afbjorklund avatar Jul 13 '22 06:07 afbjorklund

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. 😄

jandubois avatar Jul 13 '22 06:07 jandubois

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... 🤷

jandubois avatar Jul 13 '22 06:07 jandubois

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

afbjorklund avatar Jul 13 '22 06:07 afbjorklund