Patch to avoid short name usage where possible. Get the actual case spelling of a file name on 'Windows' without converting to short name and back again. Avoids bad behavior reported in http://bugs.winehq.org/show_bug.cgi?id=22286 when using cmake under a wine/msys/mingw installation on a Linux box. Thanks to Clinton Stimpson for preparing the patch.

This commit is contained in:
David Cole 2010-04-09 12:15:06 -04:00
parent f468b50e9a
commit 018c13ff73
1 changed files with 20 additions and 61 deletions

View File

@ -3065,38 +3065,35 @@ kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remot
return relativePath; return relativePath;
} }
// OK, some fun stuff to get the actual case of a given path.
// Basically, you just need to call ShortPath, then GetLongPathName,
// However, GetLongPathName is not implemented on windows NT and 95,
// so we have to simulate it on those versions
#ifdef _WIN32 #ifdef _WIN32
int OldWindowsGetLongPath(kwsys_stl::string const& shortPath, static int GetCasePathName(const kwsys_stl::string & pathIn,
kwsys_stl::string& longPath ) kwsys_stl::string & casePath)
{ {
kwsys_stl::string::size_type iFound = shortPath.rfind('/'); kwsys_stl::string::size_type iFound = pathIn.rfind('/');
if (iFound > 1 && iFound != shortPath.npos) if (iFound > 1 && iFound != pathIn.npos)
{ {
// recurse to peel off components // recurse to peel off components
// //
if (OldWindowsGetLongPath(shortPath.substr(0, iFound), longPath) > 0) if (GetCasePathName(pathIn.substr(0, iFound), casePath) > 0)
{ {
longPath += '/'; casePath += '/';
if (shortPath[1] != '/') if (pathIn[1] != '/')
{ {
WIN32_FIND_DATA findData; WIN32_FIND_DATA findData;
// append the long component name to the path // append the long component name to the path
// //
if (INVALID_HANDLE_VALUE != ::FindFirstFile HANDLE hFind = ::FindFirstFile(pathIn.c_str(), &findData);
(shortPath.c_str(), &findData)) if (INVALID_HANDLE_VALUE != hFind)
{ {
longPath += findData.cFileName; casePath += findData.cFileName;
::FindClose(hFind);
} }
else else
{ {
// if FindFirstFile fails, return the error code // if FindFirstFile fails, return the error code
// //
longPath = ""; casePath = "";
return 0; return 0;
} }
} }
@ -3104,37 +3101,9 @@ int OldWindowsGetLongPath(kwsys_stl::string const& shortPath,
} }
else else
{ {
longPath = shortPath; casePath = pathIn;
} }
return (int)longPath.size(); return (int)casePath.size();
}
int PortableGetLongPathName(const char* pathIn,
kwsys_stl::string & longPath)
{
HMODULE lh = LoadLibrary("Kernel32.dll");
if(lh)
{
FARPROC proc = GetProcAddress(lh, "GetLongPathNameA");
if(proc)
{
typedef DWORD (WINAPI * GetLongFunctionPtr) (LPCSTR,LPSTR,DWORD);
GetLongFunctionPtr func = (GetLongFunctionPtr)proc;
char buffer[MAX_PATH+1];
int len = (*func)(pathIn, buffer, MAX_PATH+1);
if(len == 0 || len > MAX_PATH+1)
{
FreeLibrary(lh);
return 0;
}
longPath = buffer;
FreeLibrary(lh);
return len;
}
FreeLibrary(lh);
}
return OldWindowsGetLongPath(pathIn, longPath);
} }
#endif #endif
@ -3153,29 +3122,19 @@ kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p)
{ {
return i->second; return i->second;
} }
kwsys_stl::string shortPath; kwsys_stl::string casePath;
if(!SystemTools::GetShortPath(p, shortPath)) int len = GetCasePathName(p, casePath);
{
return p;
}
kwsys_stl::string longPath;
int len = PortableGetLongPathName(shortPath.c_str(), longPath);
if(len == 0 || len > MAX_PATH+1) if(len == 0 || len > MAX_PATH+1)
{ {
return p; return p;
} }
// Use original path if conversion back to a long path failed.
if(longPath == shortPath)
{
longPath = p;
}
// make sure drive letter is always upper case // make sure drive letter is always upper case
if(longPath.size() > 1 && longPath[1] == ':') if(casePath.size() > 1 && casePath[1] == ':')
{ {
longPath[0] = toupper(longPath[0]); casePath[0] = toupper(casePath[0]);
} }
(*SystemTools::LongPathMap)[p] = longPath; (*SystemTools::LongPathMap)[p] = casePath;
return longPath; return casePath;
#endif #endif
} }