Windows vs Cygwin File Paths
In the last post, I described how to build the Info-ZIP sources. When using the resulting zip binaries in Cygwin, some important path handling issues come up. The paths passed to the zip binary when building the OpenJDK in Cygwin use forward slashes. The Cygwin User’s Guide has a section on File Access that outlines the support for POSIX and Win32-style file paths.
The Windows file system APIs support forward slashes in file paths. The zip source code uses the fopen
CRT function, which eventually ends up calling CreateFileW
. The CreateFileW
docs state that you may use either forward slashes (/) or backslashes (\) in the lpFileName
parameter. The translation of paths from Win32 to NT happens in a function called RtlDosPathNameToRelativeNtPathName_U
as discussed in the Definitive Guide on Win32 to NT Path Conversion. Since this is a built-in Windows function, it does not support the /cygdrive/ style prefixes. Running the simple test program argtofile in Cygwin easily demonstrates this.
The /cygdrive/ prefixes will therefore not work for programs compiled for Windows (such as the zip binary directly compiled using Visual C++). Therefore, the cygpath
command is necessary to translate these paths to Win32-style file paths. To peek into how cygpath works, we can take advantage of the fact that the source code for the cygpath utility is available online. I found it easier to browse the sources after cloning the repo:
git clone https://cygwin.com/git/newlib-cygwin.git
The scenario of interest is what happens when cygpath -u ~
is invoked. In this case, we want to see how the “/cygdrive/” string is prefixed to the computed path.
- Execution flows from main > action > do_pathconv
- do_pathconv calls cygwin_conv_path which
- calls the conv_to_posix_path method of the mount_table which then
- normalizes the path by calling normalize_win32_path
- before finally iterating through the mount items to find the path’s prefix in the mount table.
Also searching for the cygpath \s*(
regex leads to the vcygpath
function in winsup/utils/path.cc. That appears to be more directly related to the cygpath command (how?). Searching for the \"cygdrive\"
regex also reveals that this is a magic string used in many places in the codebase.
All this shows that there is indeed some complexity behind maintaining the POSIX/Win32-style file path mapping in Cygwin but it should be possible to add some basic logic to the Windows Info-ZIP build to handle /cygdrive/ prefixes in its file arguments. The question I have at this point is how does compiling the zip binaries for the Cygwin environment (the shipping configuration) result in proper handling of POSIX-style filenames?
Leave a Reply