Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -644,10 +644,11 @@ } /* ** Simplify a filename by ** +** * Remove extended path prefix on windows and cygwin ** * Convert all \ into / on windows and cygwin ** * removing any trailing and duplicate / ** * removing /./ ** * removing /A/../ ** @@ -654,17 +655,27 @@ ** Changes are made in-place. Return the new name length. ** If the slash parameter is non-zero, the trailing slash, if any, ** is retained. */ int file_simplify_name(char *z, int n, int slash){ - int i, j; + int i = 1, j; if( n<0 ) n = strlen(z); - /* On windows and cygwin convert all \ characters to / */ + /* On windows and cygwin convert all \ characters to / + * and remove extended path prefix if present */ #if defined(_WIN32) || defined(__CYGWIN__) - for(i=0; i3 && !memcmp(z, "//?/", 4) ){ + if( fossil_strnicmp(z+4,"UNC", 3) ){ + i += 4; + z[0] = z[4]; + }else{ + i += 6; + z[0] = '/'; + } } #endif /* Removing trailing "/" characters */ if( !slash ){ @@ -671,11 +682,11 @@ while( n>1 && z[n-1]=='/' ){ n--; } } /* Remove duplicate '/' characters. Except, two // at the beginning ** of a pathname is allowed since this is important on windows. */ - for(i=j=1; i:/" or ":\", - ** leave the ':' intact - */ + ** If there is no "\\?\" prefix but there is a drive or UNC + ** path prefix and the path is larger than MAX_PATH chars, + ** no Win32 API function can handle that unless it is + ** prefixed with the extended path prefix. See: + ** + **/ if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' - && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { + && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){ + if( wUnicode==zUnicode && nChar>MAX_PATH){ + memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t)); + memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t)); + wUnicode += 4; + } + /* + ** If (remainder of) path starts with ":/" or ":\", + ** leave the ':' intact but translate the backslash to a slash. + */ wUnicode[2] = '\\'; wUnicode += 3; + }else if( wUnicode==zUnicode && nChar>MAX_PATH + && (zUtf8[0]=='\\' || zUtf8[0]=='/') + && (zUtf8[1]=='\\' || zUtf8[1]=='/') && zUtf8[2]!='?'){ + memmove(wUnicode+6, wUnicode, nChar*sizeof(wchar_t)); + memcpy(wUnicode, L"\\\\?\\UNC", 7*sizeof(wchar_t)); + wUnicode += 7; } /* ** In the remainder of the path, translate invalid characters to ** characters in the Unicode private use area. This is what makes ** Win32 fossil.exe work well in a Cygwin environment even when a Index: test/file1.test ================================================================== --- test/file1.test +++ test/file1.test @@ -33,5 +33,10 @@ simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y + +if {$::tcl_platform(os)=="Windows NT"} { + simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {} + simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {} +}