Fossil SCM
If "fossil new" or "fossil open"'s argument has an extended path prefix like "\\?\C:\", don't process the '?' and ':' in it as special path characters, only do '/' -> '\' translation. This makes extended paths usable in fossil everywhere (hopefully), for now <260.
Commit
04f4e699d41b7378ce8cb5d4c09bc0756a818fb0
Parent
b7ff13a0aa6317f…
1 file changed
+18
-4
+18
-4
| --- src/utf8.c | ||
| +++ src/utf8.c | ||
| @@ -191,22 +191,36 @@ | ||
| 191 | 191 | ** |
| 192 | 192 | */ |
| 193 | 193 | void *fossil_utf8_to_filename(const char *zUtf8){ |
| 194 | 194 | #ifdef _WIN32 |
| 195 | 195 | int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 196 | - wchar_t *zUnicode = sqlite3_malloc( nChar * 2 ); | |
| 196 | + wchar_t *zUnicode = sqlite3_malloc( nChar * sizeof(wchar_t) ); | |
| 197 | 197 | wchar_t *wUnicode = zUnicode; |
| 198 | 198 | if( zUnicode==0 ){ |
| 199 | 199 | return 0; |
| 200 | 200 | } |
| 201 | - MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); | |
| 202 | - /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */ | |
| 203 | 201 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 204 | 202 | && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 205 | - zUnicode[2] = '\\'; | |
| 203 | + /* If path starts with "<drive>:[/\]", don't process the ':' */ | |
| 204 | + zUnicode[0] = zUtf8[0]; | |
| 205 | + memcpy(&zUnicode[1], L":\\", 2 * sizeof(wchar_t)); | |
| 206 | 206 | wUnicode += 3; |
| 207 | + MultiByteToWideChar(CP_UTF8, 0, zUtf8+3, -1, wUnicode, nChar-3); | |
| 208 | + goto finish; | |
| 209 | + }else if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && | |
| 210 | + (zUtf8[1]=='\\' || zUtf8[1]=='/') ) { | |
| 211 | + if( zUtf8[2]=='?' && nChar>5 ){ | |
| 212 | + /* Don't postprocess [?:] in extended path, but do '/' -> '\' */ | |
| 213 | + memcpy(zUnicode, L"\\\\", 2 * sizeof(wchar_t)); | |
| 214 | + MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, zUnicode+2, nChar-2); | |
| 215 | + if( zUtf8[3]=='/' ) zUnicode[3]='\\'; | |
| 216 | + wUnicode += 6; | |
| 217 | + goto finish; | |
| 218 | + } | |
| 207 | 219 | } |
| 220 | + MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); | |
| 221 | +finish: | |
| 208 | 222 | while( *wUnicode != '\0' ){ |
| 209 | 223 | if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){ |
| 210 | 224 | *wUnicode |= 0xF000; |
| 211 | 225 | }else if( *wUnicode == '/' ){ |
| 212 | 226 | *wUnicode = '\\'; |
| 213 | 227 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -191,22 +191,36 @@ | |
| 191 | ** |
| 192 | */ |
| 193 | void *fossil_utf8_to_filename(const char *zUtf8){ |
| 194 | #ifdef _WIN32 |
| 195 | int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 196 | wchar_t *zUnicode = sqlite3_malloc( nChar * 2 ); |
| 197 | wchar_t *wUnicode = zUnicode; |
| 198 | if( zUnicode==0 ){ |
| 199 | return 0; |
| 200 | } |
| 201 | MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); |
| 202 | /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */ |
| 203 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 204 | && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 205 | zUnicode[2] = '\\'; |
| 206 | wUnicode += 3; |
| 207 | } |
| 208 | while( *wUnicode != '\0' ){ |
| 209 | if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){ |
| 210 | *wUnicode |= 0xF000; |
| 211 | }else if( *wUnicode == '/' ){ |
| 212 | *wUnicode = '\\'; |
| 213 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -191,22 +191,36 @@ | |
| 191 | ** |
| 192 | */ |
| 193 | void *fossil_utf8_to_filename(const char *zUtf8){ |
| 194 | #ifdef _WIN32 |
| 195 | int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 196 | wchar_t *zUnicode = sqlite3_malloc( nChar * sizeof(wchar_t) ); |
| 197 | wchar_t *wUnicode = zUnicode; |
| 198 | if( zUnicode==0 ){ |
| 199 | return 0; |
| 200 | } |
| 201 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 202 | && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 203 | /* If path starts with "<drive>:[/\]", don't process the ':' */ |
| 204 | zUnicode[0] = zUtf8[0]; |
| 205 | memcpy(&zUnicode[1], L":\\", 2 * sizeof(wchar_t)); |
| 206 | wUnicode += 3; |
| 207 | MultiByteToWideChar(CP_UTF8, 0, zUtf8+3, -1, wUnicode, nChar-3); |
| 208 | goto finish; |
| 209 | }else if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && |
| 210 | (zUtf8[1]=='\\' || zUtf8[1]=='/') ) { |
| 211 | if( zUtf8[2]=='?' && nChar>5 ){ |
| 212 | /* Don't postprocess [?:] in extended path, but do '/' -> '\' */ |
| 213 | memcpy(zUnicode, L"\\\\", 2 * sizeof(wchar_t)); |
| 214 | MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, zUnicode+2, nChar-2); |
| 215 | if( zUtf8[3]=='/' ) zUnicode[3]='\\'; |
| 216 | wUnicode += 6; |
| 217 | goto finish; |
| 218 | } |
| 219 | } |
| 220 | MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); |
| 221 | finish: |
| 222 | while( *wUnicode != '\0' ){ |
| 223 | if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){ |
| 224 | *wUnicode |= 0xF000; |
| 225 | }else if( *wUnicode == '/' ){ |
| 226 | *wUnicode = '\\'; |
| 227 |