Fossil SCM
Handle win32 extended path prefix everywhere: Just strip it in the function file_simplify_name(), and only add it back when needed (just before feeding it to a win32 function when >260 chars). Includes additional test-cases.
Commit
95f004b1c535c545941ebe7512d7684f1250309b
Parent
3df526ca41bde75…
4 files changed
+16
-5
+16
-5
+24
-5
+5
+16
-5
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -696,10 +696,11 @@ | ||
| 696 | 696 | } |
| 697 | 697 | |
| 698 | 698 | /* |
| 699 | 699 | ** Simplify a filename by |
| 700 | 700 | ** |
| 701 | +** * Remove extended path prefix on windows and cygwin | |
| 701 | 702 | ** * Convert all \ into / on windows and cygwin |
| 702 | 703 | ** * removing any trailing and duplicate / |
| 703 | 704 | ** * removing /./ |
| 704 | 705 | ** * removing /A/../ |
| 705 | 706 | ** |
| @@ -706,17 +707,27 @@ | ||
| 706 | 707 | ** Changes are made in-place. Return the new name length. |
| 707 | 708 | ** If the slash parameter is non-zero, the trailing slash, if any, |
| 708 | 709 | ** is retained. |
| 709 | 710 | */ |
| 710 | 711 | int file_simplify_name(char *z, int n, int slash){ |
| 711 | - int i, j; | |
| 712 | + int i = 1, j; | |
| 712 | 713 | if( n<0 ) n = strlen(z); |
| 713 | 714 | |
| 714 | - /* On windows and cygwin convert all \ characters to / */ | |
| 715 | + /* On windows and cygwin convert all \ characters to / | |
| 716 | + * and remove extended path prefix if present */ | |
| 715 | 717 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 716 | - for(i=0; i<n; i++){ | |
| 717 | - if( z[i]=='\\' ) z[i] = '/'; | |
| 718 | + for(j=0; j<n; j++){ | |
| 719 | + if( z[j]=='\\' ) z[j] = '/'; | |
| 720 | + } | |
| 721 | + if( n>3 && !memcmp(z, "//?/", 4) ){ | |
| 722 | + if( fossil_strnicmp(z+4,"UNC", 3) ){ | |
| 723 | + i += 4; | |
| 724 | + z[0] = z[4]; | |
| 725 | + }else{ | |
| 726 | + i += 6; | |
| 727 | + z[0] = '/'; | |
| 728 | + } | |
| 718 | 729 | } |
| 719 | 730 | #endif |
| 720 | 731 | |
| 721 | 732 | /* Removing trailing "/" characters */ |
| 722 | 733 | if( !slash ){ |
| @@ -723,11 +734,11 @@ | ||
| 723 | 734 | while( n>1 && z[n-1]=='/' ){ n--; } |
| 724 | 735 | } |
| 725 | 736 | |
| 726 | 737 | /* Remove duplicate '/' characters. Except, two // at the beginning |
| 727 | 738 | ** of a pathname is allowed since this is important on windows. */ |
| 728 | - for(i=j=1; i<n; i++){ | |
| 739 | + for(j=1; i<n; i++){ | |
| 729 | 740 | z[j++] = z[i]; |
| 730 | 741 | while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++; |
| 731 | 742 | } |
| 732 | 743 | n = j; |
| 733 | 744 | |
| 734 | 745 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -696,10 +696,11 @@ | |
| 696 | } |
| 697 | |
| 698 | /* |
| 699 | ** Simplify a filename by |
| 700 | ** |
| 701 | ** * Convert all \ into / on windows and cygwin |
| 702 | ** * removing any trailing and duplicate / |
| 703 | ** * removing /./ |
| 704 | ** * removing /A/../ |
| 705 | ** |
| @@ -706,17 +707,27 @@ | |
| 706 | ** Changes are made in-place. Return the new name length. |
| 707 | ** If the slash parameter is non-zero, the trailing slash, if any, |
| 708 | ** is retained. |
| 709 | */ |
| 710 | int file_simplify_name(char *z, int n, int slash){ |
| 711 | int i, j; |
| 712 | if( n<0 ) n = strlen(z); |
| 713 | |
| 714 | /* On windows and cygwin convert all \ characters to / */ |
| 715 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 716 | for(i=0; i<n; i++){ |
| 717 | if( z[i]=='\\' ) z[i] = '/'; |
| 718 | } |
| 719 | #endif |
| 720 | |
| 721 | /* Removing trailing "/" characters */ |
| 722 | if( !slash ){ |
| @@ -723,11 +734,11 @@ | |
| 723 | while( n>1 && z[n-1]=='/' ){ n--; } |
| 724 | } |
| 725 | |
| 726 | /* Remove duplicate '/' characters. Except, two // at the beginning |
| 727 | ** of a pathname is allowed since this is important on windows. */ |
| 728 | for(i=j=1; i<n; i++){ |
| 729 | z[j++] = z[i]; |
| 730 | while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++; |
| 731 | } |
| 732 | n = j; |
| 733 | |
| 734 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -696,10 +696,11 @@ | |
| 696 | } |
| 697 | |
| 698 | /* |
| 699 | ** Simplify a filename by |
| 700 | ** |
| 701 | ** * Remove extended path prefix on windows and cygwin |
| 702 | ** * Convert all \ into / on windows and cygwin |
| 703 | ** * removing any trailing and duplicate / |
| 704 | ** * removing /./ |
| 705 | ** * removing /A/../ |
| 706 | ** |
| @@ -706,17 +707,27 @@ | |
| 707 | ** Changes are made in-place. Return the new name length. |
| 708 | ** If the slash parameter is non-zero, the trailing slash, if any, |
| 709 | ** is retained. |
| 710 | */ |
| 711 | int file_simplify_name(char *z, int n, int slash){ |
| 712 | int i = 1, j; |
| 713 | if( n<0 ) n = strlen(z); |
| 714 | |
| 715 | /* On windows and cygwin convert all \ characters to / |
| 716 | * and remove extended path prefix if present */ |
| 717 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 718 | for(j=0; j<n; j++){ |
| 719 | if( z[j]=='\\' ) z[j] = '/'; |
| 720 | } |
| 721 | if( n>3 && !memcmp(z, "//?/", 4) ){ |
| 722 | if( fossil_strnicmp(z+4,"UNC", 3) ){ |
| 723 | i += 4; |
| 724 | z[0] = z[4]; |
| 725 | }else{ |
| 726 | i += 6; |
| 727 | z[0] = '/'; |
| 728 | } |
| 729 | } |
| 730 | #endif |
| 731 | |
| 732 | /* Removing trailing "/" characters */ |
| 733 | if( !slash ){ |
| @@ -723,11 +734,11 @@ | |
| 734 | while( n>1 && z[n-1]=='/' ){ n--; } |
| 735 | } |
| 736 | |
| 737 | /* Remove duplicate '/' characters. Except, two // at the beginning |
| 738 | ** of a pathname is allowed since this is important on windows. */ |
| 739 | for(j=1; i<n; i++){ |
| 740 | z[j++] = z[i]; |
| 741 | while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++; |
| 742 | } |
| 743 | n = j; |
| 744 | |
| 745 |
+16
-5
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -696,10 +696,11 @@ | ||
| 696 | 696 | } |
| 697 | 697 | |
| 698 | 698 | /* |
| 699 | 699 | ** Simplify a filename by |
| 700 | 700 | ** |
| 701 | +** * Remove extended path prefix on windows and cygwin | |
| 701 | 702 | ** * Convert all \ into / on windows and cygwin |
| 702 | 703 | ** * removing any trailing and duplicate / |
| 703 | 704 | ** * removing /./ |
| 704 | 705 | ** * removing /A/../ |
| 705 | 706 | ** |
| @@ -706,17 +707,27 @@ | ||
| 706 | 707 | ** Changes are made in-place. Return the new name length. |
| 707 | 708 | ** If the slash parameter is non-zero, the trailing slash, if any, |
| 708 | 709 | ** is retained. |
| 709 | 710 | */ |
| 710 | 711 | int file_simplify_name(char *z, int n, int slash){ |
| 711 | - int i, j; | |
| 712 | + int i = 1, j; | |
| 712 | 713 | if( n<0 ) n = strlen(z); |
| 713 | 714 | |
| 714 | - /* On windows and cygwin convert all \ characters to / */ | |
| 715 | + /* On windows and cygwin convert all \ characters to / | |
| 716 | + * and remove extended path prefix if present */ | |
| 715 | 717 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 716 | - for(i=0; i<n; i++){ | |
| 717 | - if( z[i]=='\\' ) z[i] = '/'; | |
| 718 | + for(j=0; j<n; j++){ | |
| 719 | + if( z[j]=='\\' ) z[j] = '/'; | |
| 720 | + } | |
| 721 | + if( n>3 && !memcmp(z, "//?/", 4) ){ | |
| 722 | + if( fossil_strnicmp(z+4,"UNC", 3) ){ | |
| 723 | + i += 4; | |
| 724 | + z[0] = z[4]; | |
| 725 | + }else{ | |
| 726 | + i += 6; | |
| 727 | + z[0] = '/'; | |
| 728 | + } | |
| 718 | 729 | } |
| 719 | 730 | #endif |
| 720 | 731 | |
| 721 | 732 | /* Removing trailing "/" characters */ |
| 722 | 733 | if( !slash ){ |
| @@ -723,11 +734,11 @@ | ||
| 723 | 734 | while( n>1 && z[n-1]=='/' ){ n--; } |
| 724 | 735 | } |
| 725 | 736 | |
| 726 | 737 | /* Remove duplicate '/' characters. Except, two // at the beginning |
| 727 | 738 | ** of a pathname is allowed since this is important on windows. */ |
| 728 | - for(i=j=1; i<n; i++){ | |
| 739 | + for(j=1; i<n; i++){ | |
| 729 | 740 | z[j++] = z[i]; |
| 730 | 741 | while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++; |
| 731 | 742 | } |
| 732 | 743 | n = j; |
| 733 | 744 | |
| 734 | 745 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -696,10 +696,11 @@ | |
| 696 | } |
| 697 | |
| 698 | /* |
| 699 | ** Simplify a filename by |
| 700 | ** |
| 701 | ** * Convert all \ into / on windows and cygwin |
| 702 | ** * removing any trailing and duplicate / |
| 703 | ** * removing /./ |
| 704 | ** * removing /A/../ |
| 705 | ** |
| @@ -706,17 +707,27 @@ | |
| 706 | ** Changes are made in-place. Return the new name length. |
| 707 | ** If the slash parameter is non-zero, the trailing slash, if any, |
| 708 | ** is retained. |
| 709 | */ |
| 710 | int file_simplify_name(char *z, int n, int slash){ |
| 711 | int i, j; |
| 712 | if( n<0 ) n = strlen(z); |
| 713 | |
| 714 | /* On windows and cygwin convert all \ characters to / */ |
| 715 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 716 | for(i=0; i<n; i++){ |
| 717 | if( z[i]=='\\' ) z[i] = '/'; |
| 718 | } |
| 719 | #endif |
| 720 | |
| 721 | /* Removing trailing "/" characters */ |
| 722 | if( !slash ){ |
| @@ -723,11 +734,11 @@ | |
| 723 | while( n>1 && z[n-1]=='/' ){ n--; } |
| 724 | } |
| 725 | |
| 726 | /* Remove duplicate '/' characters. Except, two // at the beginning |
| 727 | ** of a pathname is allowed since this is important on windows. */ |
| 728 | for(i=j=1; i<n; i++){ |
| 729 | z[j++] = z[i]; |
| 730 | while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++; |
| 731 | } |
| 732 | n = j; |
| 733 | |
| 734 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -696,10 +696,11 @@ | |
| 696 | } |
| 697 | |
| 698 | /* |
| 699 | ** Simplify a filename by |
| 700 | ** |
| 701 | ** * Remove extended path prefix on windows and cygwin |
| 702 | ** * Convert all \ into / on windows and cygwin |
| 703 | ** * removing any trailing and duplicate / |
| 704 | ** * removing /./ |
| 705 | ** * removing /A/../ |
| 706 | ** |
| @@ -706,17 +707,27 @@ | |
| 707 | ** Changes are made in-place. Return the new name length. |
| 708 | ** If the slash parameter is non-zero, the trailing slash, if any, |
| 709 | ** is retained. |
| 710 | */ |
| 711 | int file_simplify_name(char *z, int n, int slash){ |
| 712 | int i = 1, j; |
| 713 | if( n<0 ) n = strlen(z); |
| 714 | |
| 715 | /* On windows and cygwin convert all \ characters to / |
| 716 | * and remove extended path prefix if present */ |
| 717 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 718 | for(j=0; j<n; j++){ |
| 719 | if( z[j]=='\\' ) z[j] = '/'; |
| 720 | } |
| 721 | if( n>3 && !memcmp(z, "//?/", 4) ){ |
| 722 | if( fossil_strnicmp(z+4,"UNC", 3) ){ |
| 723 | i += 4; |
| 724 | z[0] = z[4]; |
| 725 | }else{ |
| 726 | i += 6; |
| 727 | z[0] = '/'; |
| 728 | } |
| 729 | } |
| 730 | #endif |
| 731 | |
| 732 | /* Removing trailing "/" characters */ |
| 733 | if( !slash ){ |
| @@ -723,11 +734,11 @@ | |
| 734 | while( n>1 && z[n-1]=='/' ){ n--; } |
| 735 | } |
| 736 | |
| 737 | /* Remove duplicate '/' characters. Except, two // at the beginning |
| 738 | ** of a pathname is allowed since this is important on windows. */ |
| 739 | for(j=1; i<n; i++){ |
| 740 | z[j++] = z[i]; |
| 741 | while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++; |
| 742 | } |
| 743 | n = j; |
| 744 | |
| 745 |
+24
-5
| --- src/utf8.c | ||
| +++ src/utf8.c | ||
| @@ -190,11 +190,12 @@ | ||
| 190 | 190 | ** |
| 191 | 191 | */ |
| 192 | 192 | void *fossil_utf8_to_filename(const char *zUtf8){ |
| 193 | 193 | #ifdef _WIN32 |
| 194 | 194 | int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 195 | - wchar_t *zUnicode = sqlite3_malloc( nChar * 2 ); | |
| 195 | + /* Overallocate 6 chars, making some room for extended paths */ | |
| 196 | + wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) ); | |
| 196 | 197 | wchar_t *wUnicode = zUnicode; |
| 197 | 198 | if( zUnicode==0 ){ |
| 198 | 199 | return 0; |
| 199 | 200 | } |
| 200 | 201 | MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); |
| @@ -207,17 +208,35 @@ | ||
| 207 | 208 | wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\'; |
| 208 | 209 | zUtf8 += 4; |
| 209 | 210 | wUnicode += 4; |
| 210 | 211 | } |
| 211 | 212 | /* |
| 212 | - ** If (remainder of) path starts with "<drive>:/" or "<drive>:\", | |
| 213 | - ** leave the ':' intact | |
| 214 | - */ | |
| 213 | + ** If there is no "\\?\" prefix but there is a drive or UNC | |
| 214 | + ** path prefix and the path is larger than MAX_PATH chars, | |
| 215 | + ** no Win32 API function can handle that unless it is | |
| 216 | + ** prefixed with the extended path prefix. See: | |
| 217 | + ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath> | |
| 218 | + **/ | |
| 215 | 219 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 216 | - && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { | |
| 220 | + && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){ | |
| 221 | + if( wUnicode==zUnicode && nChar>MAX_PATH){ | |
| 222 | + memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t)); | |
| 223 | + memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t)); | |
| 224 | + wUnicode += 4; | |
| 225 | + } | |
| 226 | + /* | |
| 227 | + ** If (remainder of) path starts with "<drive>:/" or "<drive>:\", | |
| 228 | + ** leave the ':' intact but translate the backslash to a slash. | |
| 229 | + */ | |
| 217 | 230 | wUnicode[2] = '\\'; |
| 218 | 231 | wUnicode += 3; |
| 232 | + }else if( wUnicode==zUnicode && nChar>MAX_PATH | |
| 233 | + && (zUtf8[0]=='\\' || zUtf8[0]=='/') | |
| 234 | + && (zUtf8[1]=='\\' || zUtf8[1]=='/') && zUtf8[2]!='?'){ | |
| 235 | + memmove(wUnicode+6, wUnicode, nChar*sizeof(wchar_t)); | |
| 236 | + memcpy(wUnicode, L"\\\\?\\UNC", 7*sizeof(wchar_t)); | |
| 237 | + wUnicode += 7; | |
| 219 | 238 | } |
| 220 | 239 | /* |
| 221 | 240 | ** In the remainder of the path, translate invalid characters to |
| 222 | 241 | ** characters in the Unicode private use area. This is what makes |
| 223 | 242 | ** Win32 fossil.exe work well in a Cygwin environment even when a |
| 224 | 243 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -190,11 +190,12 @@ | |
| 190 | ** |
| 191 | */ |
| 192 | void *fossil_utf8_to_filename(const char *zUtf8){ |
| 193 | #ifdef _WIN32 |
| 194 | int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 195 | wchar_t *zUnicode = sqlite3_malloc( nChar * 2 ); |
| 196 | wchar_t *wUnicode = zUnicode; |
| 197 | if( zUnicode==0 ){ |
| 198 | return 0; |
| 199 | } |
| 200 | MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); |
| @@ -207,17 +208,35 @@ | |
| 207 | wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\'; |
| 208 | zUtf8 += 4; |
| 209 | wUnicode += 4; |
| 210 | } |
| 211 | /* |
| 212 | ** If (remainder of) path starts with "<drive>:/" or "<drive>:\", |
| 213 | ** leave the ':' intact |
| 214 | */ |
| 215 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 216 | && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 217 | wUnicode[2] = '\\'; |
| 218 | wUnicode += 3; |
| 219 | } |
| 220 | /* |
| 221 | ** In the remainder of the path, translate invalid characters to |
| 222 | ** characters in the Unicode private use area. This is what makes |
| 223 | ** Win32 fossil.exe work well in a Cygwin environment even when a |
| 224 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -190,11 +190,12 @@ | |
| 190 | ** |
| 191 | */ |
| 192 | void *fossil_utf8_to_filename(const char *zUtf8){ |
| 193 | #ifdef _WIN32 |
| 194 | int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 195 | /* Overallocate 6 chars, making some room for extended paths */ |
| 196 | wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) ); |
| 197 | wchar_t *wUnicode = zUnicode; |
| 198 | if( zUnicode==0 ){ |
| 199 | return 0; |
| 200 | } |
| 201 | MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); |
| @@ -207,17 +208,35 @@ | |
| 208 | wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\'; |
| 209 | zUtf8 += 4; |
| 210 | wUnicode += 4; |
| 211 | } |
| 212 | /* |
| 213 | ** If there is no "\\?\" prefix but there is a drive or UNC |
| 214 | ** path prefix and the path is larger than MAX_PATH chars, |
| 215 | ** no Win32 API function can handle that unless it is |
| 216 | ** prefixed with the extended path prefix. See: |
| 217 | ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath> |
| 218 | **/ |
| 219 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 220 | && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){ |
| 221 | if( wUnicode==zUnicode && nChar>MAX_PATH){ |
| 222 | memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t)); |
| 223 | memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t)); |
| 224 | wUnicode += 4; |
| 225 | } |
| 226 | /* |
| 227 | ** If (remainder of) path starts with "<drive>:/" or "<drive>:\", |
| 228 | ** leave the ':' intact but translate the backslash to a slash. |
| 229 | */ |
| 230 | wUnicode[2] = '\\'; |
| 231 | wUnicode += 3; |
| 232 | }else if( wUnicode==zUnicode && nChar>MAX_PATH |
| 233 | && (zUtf8[0]=='\\' || zUtf8[0]=='/') |
| 234 | && (zUtf8[1]=='\\' || zUtf8[1]=='/') && zUtf8[2]!='?'){ |
| 235 | memmove(wUnicode+6, wUnicode, nChar*sizeof(wchar_t)); |
| 236 | memcpy(wUnicode, L"\\\\?\\UNC", 7*sizeof(wchar_t)); |
| 237 | wUnicode += 7; |
| 238 | } |
| 239 | /* |
| 240 | ** In the remainder of the path, translate invalid characters to |
| 241 | ** characters in the Unicode private use area. This is what makes |
| 242 | ** Win32 fossil.exe work well in a Cygwin environment even when a |
| 243 |
+5
| --- test/file1.test | ||
| +++ test/file1.test | ||
| @@ -33,5 +33,10 @@ | ||
| 33 | 33 | simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b |
| 34 | 34 | simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c |
| 35 | 35 | simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y |
| 36 | 36 | simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y |
| 37 | 37 | simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y |
| 38 | + | |
| 39 | +if {$::tcl_platform(os)=="Windows NT"} { | |
| 40 | + simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {} | |
| 41 | + simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {} | |
| 42 | +} | |
| 38 | 43 |
| --- test/file1.test | |
| +++ test/file1.test | |
| @@ -33,5 +33,10 @@ | |
| 33 | simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b |
| 34 | simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c |
| 35 | simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y |
| 36 | simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y |
| 37 | simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y |
| 38 |
| --- test/file1.test | |
| +++ test/file1.test | |
| @@ -33,5 +33,10 @@ | |
| 33 | simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b |
| 34 | simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c |
| 35 | simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y |
| 36 | simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y |
| 37 | simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y |
| 38 | |
| 39 | if {$::tcl_platform(os)=="Windows NT"} { |
| 40 | simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {} |
| 41 | simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {} |
| 42 | } |
| 43 |