Fossil SCM

Add support for extended UNC paths as well, and add Windows/Cygwin-specific test-cases for it.

jan.nijtmans 2014-02-26 10:42 UTC pending-review
Commit ebb42b530e4c3dc9c8e5c5e8077617ed0590b813
+8 -2
--- src/file.c
+++ src/file.c
@@ -644,10 +644,11 @@
644644
}
645645
646646
/*
647647
** Simplify a filename by
648648
**
649
+** * Remove extended path prefix on windows and cygwin
649650
** * Convert all \ into / on windows and cygwin
650651
** * removing any trailing and duplicate /
651652
** * removing /./
652653
** * removing /A/../
653654
**
@@ -664,12 +665,17 @@
664665
#if defined(_WIN32) || defined(__CYGWIN__)
665666
for(j=0; j<n; j++){
666667
if( z[j]=='\\' ) z[j] = '/';
667668
}
668669
if( n>3 && !memcmp(z, "//?/", 4) ){
669
- i += 4;
670
- z[0] = z[4];
670
+ if( fossil_strnicmp(z+4,"UNC", 3) ){
671
+ i += 4;
672
+ z[0] = z[4];
673
+ }else{
674
+ i += 6;
675
+ z[0] = '/';
676
+ }
671677
}
672678
#endif
673679
674680
/* Removing trailing "/" characters */
675681
if( !slash ){
676682
--- src/file.c
+++ src/file.c
@@ -644,10 +644,11 @@
644 }
645
646 /*
647 ** Simplify a filename by
648 **
 
649 ** * Convert all \ into / on windows and cygwin
650 ** * removing any trailing and duplicate /
651 ** * removing /./
652 ** * removing /A/../
653 **
@@ -664,12 +665,17 @@
664 #if defined(_WIN32) || defined(__CYGWIN__)
665 for(j=0; j<n; j++){
666 if( z[j]=='\\' ) z[j] = '/';
667 }
668 if( n>3 && !memcmp(z, "//?/", 4) ){
669 i += 4;
670 z[0] = z[4];
 
 
 
 
 
671 }
672 #endif
673
674 /* Removing trailing "/" characters */
675 if( !slash ){
676
--- src/file.c
+++ src/file.c
@@ -644,10 +644,11 @@
644 }
645
646 /*
647 ** Simplify a filename by
648 **
649 ** * Remove extended path prefix on windows and cygwin
650 ** * Convert all \ into / on windows and cygwin
651 ** * removing any trailing and duplicate /
652 ** * removing /./
653 ** * removing /A/../
654 **
@@ -664,12 +665,17 @@
665 #if defined(_WIN32) || defined(__CYGWIN__)
666 for(j=0; j<n; j++){
667 if( z[j]=='\\' ) z[j] = '/';
668 }
669 if( n>3 && !memcmp(z, "//?/", 4) ){
670 if( fossil_strnicmp(z+4,"UNC", 3) ){
671 i += 4;
672 z[0] = z[4];
673 }else{
674 i += 6;
675 z[0] = '/';
676 }
677 }
678 #endif
679
680 /* Removing trailing "/" characters */
681 if( !slash ){
682
+19 -13
--- src/utf8.c
+++ src/utf8.c
@@ -190,12 +190,12 @@
190190
**
191191
*/
192192
void *fossil_utf8_to_filename(const char *zUtf8){
193193
#ifdef _WIN32
194194
int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
195
- /* Overallocate 4 chars, making some room for extended paths */
196
- wchar_t *zUnicode = sqlite3_malloc( (nChar+4) * sizeof(wchar_t) );
195
+ /* Overallocate 6 chars, making some room for extended paths */
196
+ wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) );
197197
wchar_t *wUnicode = zUnicode;
198198
if( zUnicode==0 ){
199199
return 0;
200200
}
201201
MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
@@ -208,29 +208,35 @@
208208
wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
209209
zUtf8 += 4;
210210
wUnicode += 4;
211211
}
212212
/*
213
- ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
214
- ** leave the ':' intact
215
- */
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
+ **/
216219
if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
217
- && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
220
+ && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){
218221
if( wUnicode==zUnicode && nChar>MAX_PATH){
219
- /*
220
- ** If there is no "\\?\" prefix but there is a drive
221
- ** prefix and the path is larger than MAX_PATH chars,
222
- ** no Win32 API function can handle that unless it is
223
- ** prefixed with the extended path prefix. See:
224
- ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
225
- **/
226222
memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
227223
memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
228224
wUnicode += 4;
229225
}
226
+ /*
227
+ ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
228
+ ** leave the ':' intact but translate the backslash to a slash.
229
+ */
230230
wUnicode[2] = '\\';
231231
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;
232238
}
233239
/*
234240
** In the remainder of the path, translate invalid characters to
235241
** characters in the Unicode private use area. This is what makes
236242
** Win32 fossil.exe work well in a Cygwin environment even when a
237243
--- src/utf8.c
+++ src/utf8.c
@@ -190,12 +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 4 chars, making some room for extended paths */
196 wchar_t *zUnicode = sqlite3_malloc( (nChar+4) * 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);
@@ -208,29 +208,35 @@
208 wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
209 zUtf8 += 4;
210 wUnicode += 4;
211 }
212 /*
213 ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
214 ** leave the ':' intact
215 */
 
 
 
216 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
217 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
218 if( wUnicode==zUnicode && nChar>MAX_PATH){
219 /*
220 ** If there is no "\\?\" prefix but there is a drive
221 ** prefix and the path is larger than MAX_PATH chars,
222 ** no Win32 API function can handle that unless it is
223 ** prefixed with the extended path prefix. See:
224 ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
225 **/
226 memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
227 memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
228 wUnicode += 4;
229 }
 
 
 
 
230 wUnicode[2] = '\\';
231 wUnicode += 3;
 
 
 
 
 
 
232 }
233 /*
234 ** In the remainder of the path, translate invalid characters to
235 ** characters in the Unicode private use area. This is what makes
236 ** Win32 fossil.exe work well in a Cygwin environment even when a
237
--- src/utf8.c
+++ src/utf8.c
@@ -190,12 +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);
@@ -208,29 +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
--- test/file1.test
+++ test/file1.test
@@ -33,5 +33,10 @@
3333
simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
3434
simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
3535
simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
3636
simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
3737
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
+}
3843
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button