Fossil SCM
Handle translation between '/' and '\\' on Windows and Cygwin
Commit
ba87fb1fecfa54a28922ead0c8e10a8cbc4dc2ed
Parent
ba3e82f1894c454…
2 files changed
+4
-4
+19
-3
+4
-4
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -547,12 +547,10 @@ | ||
| 547 | 547 | if( (z[++i]&0xc0)!=0x80 ){ |
| 548 | 548 | /* Invalid second continuation byte */ |
| 549 | 549 | return 0; |
| 550 | 550 | } |
| 551 | 551 | } |
| 552 | - }else if( c=='\\' ){ | |
| 553 | - return 0; | |
| 554 | 552 | } |
| 555 | 553 | if( c=='/' ){ |
| 556 | 554 | if( z[i+1]=='/' ) return 0; |
| 557 | 555 | if( z[i+1]=='.' ){ |
| 558 | 556 | if( z[i+2]=='/' || z[i+2]==0 ) return 0; |
| @@ -792,12 +790,12 @@ | ||
| 792 | 790 | } |
| 793 | 791 | |
| 794 | 792 | /* |
| 795 | 793 | ** Return TRUE if the given filename is canonical. |
| 796 | 794 | ** |
| 797 | -** Canonical names are full pathnames using "/" not "\" and which | |
| 798 | -** contain no "/./" or "/../" terms. | |
| 795 | +** Canonical names are full pathnames which contain no "/./" or "/../" | |
| 796 | +** terms and (On Windows/Cygwin) using "/" not "\". | |
| 799 | 797 | */ |
| 800 | 798 | int file_is_canonical(const char *z){ |
| 801 | 799 | int i; |
| 802 | 800 | if( z[0]!='/' |
| 803 | 801 | #if defined(_WIN32) |
| @@ -804,11 +802,13 @@ | ||
| 804 | 802 | && (z[0]==0 || z[1]!=':' || z[2]!='/') |
| 805 | 803 | #endif |
| 806 | 804 | ) return 0; |
| 807 | 805 | |
| 808 | 806 | for(i=0; z[i]; i++){ |
| 807 | +#if defined(_WIN32) || defined(__CYGWIN__) | |
| 809 | 808 | if( z[i]=='\\' ) return 0; |
| 809 | +#endif | |
| 810 | 810 | if( z[i]=='/' ){ |
| 811 | 811 | if( z[i+1]=='.' ){ |
| 812 | 812 | if( z[i+2]=='/' || z[i+2]==0 ) return 0; |
| 813 | 813 | if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0; |
| 814 | 814 | } |
| 815 | 815 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -547,12 +547,10 @@ | |
| 547 | if( (z[++i]&0xc0)!=0x80 ){ |
| 548 | /* Invalid second continuation byte */ |
| 549 | return 0; |
| 550 | } |
| 551 | } |
| 552 | }else if( c=='\\' ){ |
| 553 | return 0; |
| 554 | } |
| 555 | if( c=='/' ){ |
| 556 | if( z[i+1]=='/' ) return 0; |
| 557 | if( z[i+1]=='.' ){ |
| 558 | if( z[i+2]=='/' || z[i+2]==0 ) return 0; |
| @@ -792,12 +790,12 @@ | |
| 792 | } |
| 793 | |
| 794 | /* |
| 795 | ** Return TRUE if the given filename is canonical. |
| 796 | ** |
| 797 | ** Canonical names are full pathnames using "/" not "\" and which |
| 798 | ** contain no "/./" or "/../" terms. |
| 799 | */ |
| 800 | int file_is_canonical(const char *z){ |
| 801 | int i; |
| 802 | if( z[0]!='/' |
| 803 | #if defined(_WIN32) |
| @@ -804,11 +802,13 @@ | |
| 804 | && (z[0]==0 || z[1]!=':' || z[2]!='/') |
| 805 | #endif |
| 806 | ) return 0; |
| 807 | |
| 808 | for(i=0; z[i]; i++){ |
| 809 | if( z[i]=='\\' ) return 0; |
| 810 | if( z[i]=='/' ){ |
| 811 | if( z[i+1]=='.' ){ |
| 812 | if( z[i+2]=='/' || z[i+2]==0 ) return 0; |
| 813 | if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0; |
| 814 | } |
| 815 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -547,12 +547,10 @@ | |
| 547 | if( (z[++i]&0xc0)!=0x80 ){ |
| 548 | /* Invalid second continuation byte */ |
| 549 | return 0; |
| 550 | } |
| 551 | } |
| 552 | } |
| 553 | if( c=='/' ){ |
| 554 | if( z[i+1]=='/' ) return 0; |
| 555 | if( z[i+1]=='.' ){ |
| 556 | if( z[i+2]=='/' || z[i+2]==0 ) return 0; |
| @@ -792,12 +790,12 @@ | |
| 790 | } |
| 791 | |
| 792 | /* |
| 793 | ** Return TRUE if the given filename is canonical. |
| 794 | ** |
| 795 | ** Canonical names are full pathnames which contain no "/./" or "/../" |
| 796 | ** terms and (On Windows/Cygwin) using "/" not "\". |
| 797 | */ |
| 798 | int file_is_canonical(const char *z){ |
| 799 | int i; |
| 800 | if( z[0]!='/' |
| 801 | #if defined(_WIN32) |
| @@ -804,11 +802,13 @@ | |
| 802 | && (z[0]==0 || z[1]!=':' || z[2]!='/') |
| 803 | #endif |
| 804 | ) return 0; |
| 805 | |
| 806 | for(i=0; z[i]; i++){ |
| 807 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 808 | if( z[i]=='\\' ) return 0; |
| 809 | #endif |
| 810 | if( z[i]=='/' ){ |
| 811 | if( z[i+1]=='.' ){ |
| 812 | if( z[i+2]=='/' || z[i+2]==0 ) return 0; |
| 813 | if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0; |
| 814 | } |
| 815 |
+19
-3
| --- src/utf8.c | ||
| +++ src/utf8.c | ||
| @@ -133,10 +133,14 @@ | ||
| 133 | 133 | if( zUtf==0 ){ |
| 134 | 134 | return 0; |
| 135 | 135 | } |
| 136 | 136 | WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0); |
| 137 | 137 | return zUtf; |
| 138 | +#elif defined(__CYGWIN__) | |
| 139 | + char *zOut; | |
| 140 | + zOut = fossil_strdup(zFilename); | |
| 141 | + return zOut; | |
| 138 | 142 | #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 139 | 143 | char *zIn = (char*)zFilename; |
| 140 | 144 | char *zOut; |
| 141 | 145 | iconv_t cd; |
| 142 | 146 | size_t n, x; |
| @@ -169,11 +173,11 @@ | ||
| 169 | 173 | ** Translate UTF8 to unicode for use in filename translations. |
| 170 | 174 | ** Return a pointer to the translated text.. Call fossil_filename_free() |
| 171 | 175 | ** to deallocate any memory used to store the returned pointer when done. |
| 172 | 176 | ** |
| 173 | 177 | ** On Windows, characters in the range U+0001 to U+0031 and the |
| 174 | -** characters '"', '*', ':', '<', '>', '?', '|' and '\\' are invalid | |
| 178 | +** characters '"', '*', ':', '<', '>', '?' and '|' are invalid | |
| 175 | 179 | ** to be used. Therefore, translated those to characters in the |
| 176 | 180 | ** (private use area), in the range U+F001 - U+F07F, so those |
| 177 | 181 | ** characters never arrive in any Windows API. The filenames might |
| 178 | 182 | ** look strange in Windows explorer, but in the cygwin shell |
| 179 | 183 | ** everything looks as expected. |
| @@ -186,21 +190,33 @@ | ||
| 186 | 190 | WCHAR *zUnicode = fossil_utf8_to_unicode(zUtf8); |
| 187 | 191 | WCHAR *wUnicode = zUnicode; |
| 188 | 192 | /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */ |
| 189 | 193 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 190 | 194 | && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 195 | + zUnicode[2] = '\\'; | |
| 191 | 196 | wUnicode += 3; |
| 192 | 197 | } |
| 193 | 198 | while( *wUnicode != '\0' ){ |
| 194 | 199 | if ( (*wUnicode < 32) || wcschr(L"\"*<>?|:", *wUnicode) ){ |
| 195 | 200 | *wUnicode |= 0xF000; |
| 201 | + }else if( *wUnicode == '/' ){ | |
| 202 | + *wUnicode = '\\'; | |
| 196 | 203 | } |
| 197 | 204 | ++wUnicode; |
| 198 | 205 | } |
| 199 | 206 | |
| 200 | 207 | return zUnicode; |
| 201 | -#elif defined(__APPLE__) | |
| 208 | +#elif defined(__CYGWIN__) | |
| 209 | + char *zPath = fossil_strdup(zUtf8); | |
| 210 | + char *p = zPath; | |
| 211 | + while( (*p = *zUtf8++) != 0){ | |
| 212 | + if (*p++ == '\\' ) { | |
| 213 | + p[-1] = '/'; | |
| 214 | + } | |
| 215 | + } | |
| 216 | + return zPath; | |
| 217 | +#elif defined(__APPLE__) && !defined(WITHOUT_ICONV) | |
| 202 | 218 | return fossil_strdup(zUtf8); |
| 203 | 219 | #else |
| 204 | 220 | return (void *)zUtf8; /* No-op on unix */ |
| 205 | 221 | #endif |
| 206 | 222 | } |
| @@ -210,11 +226,11 @@ | ||
| 210 | 226 | ** fossil_filename_to_utf8() or fossil_utf8_to_filename(). |
| 211 | 227 | */ |
| 212 | 228 | void fossil_filename_free(void *pOld){ |
| 213 | 229 | #if defined(_WIN32) |
| 214 | 230 | sqlite3_free(pOld); |
| 215 | -#elif defined(__APPLE__) && !defined(WITHOUT_ICONV) | |
| 231 | +#elif (defined(__APPLE__) && !defined(WITHOUT_ICONV)) || defined(__CYGWIN__) | |
| 216 | 232 | fossil_free(pOld); |
| 217 | 233 | #else |
| 218 | 234 | /* No-op on all other unix */ |
| 219 | 235 | #endif |
| 220 | 236 | } |
| 221 | 237 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -133,10 +133,14 @@ | |
| 133 | if( zUtf==0 ){ |
| 134 | return 0; |
| 135 | } |
| 136 | WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0); |
| 137 | return zUtf; |
| 138 | #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 139 | char *zIn = (char*)zFilename; |
| 140 | char *zOut; |
| 141 | iconv_t cd; |
| 142 | size_t n, x; |
| @@ -169,11 +173,11 @@ | |
| 169 | ** Translate UTF8 to unicode for use in filename translations. |
| 170 | ** Return a pointer to the translated text.. Call fossil_filename_free() |
| 171 | ** to deallocate any memory used to store the returned pointer when done. |
| 172 | ** |
| 173 | ** On Windows, characters in the range U+0001 to U+0031 and the |
| 174 | ** characters '"', '*', ':', '<', '>', '?', '|' and '\\' are invalid |
| 175 | ** to be used. Therefore, translated those to characters in the |
| 176 | ** (private use area), in the range U+F001 - U+F07F, so those |
| 177 | ** characters never arrive in any Windows API. The filenames might |
| 178 | ** look strange in Windows explorer, but in the cygwin shell |
| 179 | ** everything looks as expected. |
| @@ -186,21 +190,33 @@ | |
| 186 | WCHAR *zUnicode = fossil_utf8_to_unicode(zUtf8); |
| 187 | WCHAR *wUnicode = zUnicode; |
| 188 | /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */ |
| 189 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 190 | && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 191 | wUnicode += 3; |
| 192 | } |
| 193 | while( *wUnicode != '\0' ){ |
| 194 | if ( (*wUnicode < 32) || wcschr(L"\"*<>?|:", *wUnicode) ){ |
| 195 | *wUnicode |= 0xF000; |
| 196 | } |
| 197 | ++wUnicode; |
| 198 | } |
| 199 | |
| 200 | return zUnicode; |
| 201 | #elif defined(__APPLE__) |
| 202 | return fossil_strdup(zUtf8); |
| 203 | #else |
| 204 | return (void *)zUtf8; /* No-op on unix */ |
| 205 | #endif |
| 206 | } |
| @@ -210,11 +226,11 @@ | |
| 210 | ** fossil_filename_to_utf8() or fossil_utf8_to_filename(). |
| 211 | */ |
| 212 | void fossil_filename_free(void *pOld){ |
| 213 | #if defined(_WIN32) |
| 214 | sqlite3_free(pOld); |
| 215 | #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 216 | fossil_free(pOld); |
| 217 | #else |
| 218 | /* No-op on all other unix */ |
| 219 | #endif |
| 220 | } |
| 221 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -133,10 +133,14 @@ | |
| 133 | if( zUtf==0 ){ |
| 134 | return 0; |
| 135 | } |
| 136 | WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0); |
| 137 | return zUtf; |
| 138 | #elif defined(__CYGWIN__) |
| 139 | char *zOut; |
| 140 | zOut = fossil_strdup(zFilename); |
| 141 | return zOut; |
| 142 | #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 143 | char *zIn = (char*)zFilename; |
| 144 | char *zOut; |
| 145 | iconv_t cd; |
| 146 | size_t n, x; |
| @@ -169,11 +173,11 @@ | |
| 173 | ** Translate UTF8 to unicode for use in filename translations. |
| 174 | ** Return a pointer to the translated text.. Call fossil_filename_free() |
| 175 | ** to deallocate any memory used to store the returned pointer when done. |
| 176 | ** |
| 177 | ** On Windows, characters in the range U+0001 to U+0031 and the |
| 178 | ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid |
| 179 | ** to be used. Therefore, translated those to characters in the |
| 180 | ** (private use area), in the range U+F001 - U+F07F, so those |
| 181 | ** characters never arrive in any Windows API. The filenames might |
| 182 | ** look strange in Windows explorer, but in the cygwin shell |
| 183 | ** everything looks as expected. |
| @@ -186,21 +190,33 @@ | |
| 190 | WCHAR *zUnicode = fossil_utf8_to_unicode(zUtf8); |
| 191 | WCHAR *wUnicode = zUnicode; |
| 192 | /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */ |
| 193 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 194 | && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 195 | zUnicode[2] = '\\'; |
| 196 | wUnicode += 3; |
| 197 | } |
| 198 | while( *wUnicode != '\0' ){ |
| 199 | if ( (*wUnicode < 32) || wcschr(L"\"*<>?|:", *wUnicode) ){ |
| 200 | *wUnicode |= 0xF000; |
| 201 | }else if( *wUnicode == '/' ){ |
| 202 | *wUnicode = '\\'; |
| 203 | } |
| 204 | ++wUnicode; |
| 205 | } |
| 206 | |
| 207 | return zUnicode; |
| 208 | #elif defined(__CYGWIN__) |
| 209 | char *zPath = fossil_strdup(zUtf8); |
| 210 | char *p = zPath; |
| 211 | while( (*p = *zUtf8++) != 0){ |
| 212 | if (*p++ == '\\' ) { |
| 213 | p[-1] = '/'; |
| 214 | } |
| 215 | } |
| 216 | return zPath; |
| 217 | #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 218 | return fossil_strdup(zUtf8); |
| 219 | #else |
| 220 | return (void *)zUtf8; /* No-op on unix */ |
| 221 | #endif |
| 222 | } |
| @@ -210,11 +226,11 @@ | |
| 226 | ** fossil_filename_to_utf8() or fossil_utf8_to_filename(). |
| 227 | */ |
| 228 | void fossil_filename_free(void *pOld){ |
| 229 | #if defined(_WIN32) |
| 230 | sqlite3_free(pOld); |
| 231 | #elif (defined(__APPLE__) && !defined(WITHOUT_ICONV)) || defined(__CYGWIN__) |
| 232 | fossil_free(pOld); |
| 233 | #else |
| 234 | /* No-op on all other unix */ |
| 235 | #endif |
| 236 | } |
| 237 |