Message ID | 3e3b1c3b1ff3363b216574f09d2c9cf22d25ad30.1540291965.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Work around case-insensitivity issues with cwd on Windows | expand |
On Tuesday, October 23, 2018 3:52:49 AM MST you wrote: > From: Anton Serbulov <aserbulov@plesk.com> > > `GetLongPathName()` function may fail when it is unable to query > the parent directory of a path component to determine the long name > for that component. It happens, because of it uses `FindFirstFile()` s/of it/it/ > function for each next short part of path. The `FindFirstFile()` > requires `List Directory` and `Synchronize` desired access for a calling > process.
On Tuesday, October 23, 2018 6:16:43 AM MST Stephen Smith wrote: > On Tuesday, October 23, 2018 3:52:49 AM MST you wrote: > > From: Anton Serbulov <aserbulov@plesk.com> > > > > `GetLongPathName()` function may fail when it is unable to query > > the parent directory of a path component to determine the long name > > for that component. It happens, because of it uses `FindFirstFile()` > > s/of it/it/ > > > function for each next short part of path. The `FindFirstFile()` > > requires `List Directory` and `Synchronize` desired access for a calling > > process. BTW - It was "Stephen" that sent the email. :-)
Hi Stephen, On Tue, 23 Oct 2018, Stephen & Linda Smith wrote: > On Tuesday, October 23, 2018 3:52:49 AM MST you wrote: > > From: Anton Serbulov <aserbulov@plesk.com> > > > > `GetLongPathName()` function may fail when it is unable to query > > the parent directory of a path component to determine the long name > > for that component. It happens, because of it uses `FindFirstFile()` > s/of it/it/ Thanks, fixed in v2, Dscho > > > function for each next short part of path. The `FindFirstFile()` > > requires `List Directory` and `Synchronize` desired access for a calling > > process. > > > > > >
diff --git a/compat/mingw.c b/compat/mingw.c index 2c3e27ce9..19addfa5d 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -202,6 +202,31 @@ static int ask_yes_no_if_possible(const char *format, ...) } } +/* Normalizes NT paths as returned by some low-level APIs. */ +static wchar_t *normalize_ntpath(wchar_t *wbuf) +{ + int i; + /* fix absolute path prefixes */ + if (wbuf[0] == '\\') { + /* strip NT namespace prefixes */ + if (!wcsncmp(wbuf, L"\\??\\", 4) || + !wcsncmp(wbuf, L"\\\\?\\", 4)) + wbuf += 4; + else if (!wcsnicmp(wbuf, L"\\DosDevices\\", 12)) + wbuf += 12; + /* replace remaining '...UNC\' with '\\' */ + if (!wcsnicmp(wbuf, L"UNC\\", 4)) { + wbuf += 2; + *wbuf = '\\'; + } + } + /* convert backslashes to slashes */ + for (i = 0; wbuf[i]; i++) + if (wbuf[i] == '\\') + wbuf[i] = '/'; + return wbuf; +} + int mingw_unlink(const char *pathname) { int ret, tries = 0; @@ -925,6 +950,20 @@ char *mingw_getcwd(char *pointer, int len) return NULL; } ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer)); + if (!ret && GetLastError() == ERROR_ACCESS_DENIED) { + HANDLE hnd = CreateFileW(cwd, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hnd == INVALID_HANDLE_VALUE) + return NULL; + ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0); + CloseHandle(hnd); + if (!ret || ret >= ARRAY_SIZE(wpointer)) + return NULL; + if (xwcstoutf(pointer, normalize_ntpath(wpointer), len) < 0) + return NULL; + return pointer; + } if (!ret || ret >= ARRAY_SIZE(wpointer)) return NULL; if (xwcstoutf(pointer, wpointer, len) < 0)