Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch ticket-d17d6e5b17 Excluding Merge-Ins
This is equivalent to a diff from a98467b661 to fdd51b617c
2013-02-18
| ||
13:46 | Fixed ticket [5df2715635b99bd46a] (check-in count mismatch). check-in: b27c0d6d3f user: stephan tags: trunk | |
10:03 | New function fossil_utf8_to_filename, such that fossil_unicode_to_utf8/fossil_utf8_to_unicode/fossil_unicode_free are not used on UNIX/MAC any more: On UNIX those 3 functions were only no-ops, but this allows to re-implement then for real unicode <-> utf-8 conversions. There is an "#ifdef _WIN32" around those 3 functions and 2 more (fossil_mbcs_to... Leaf check-in: cc3976fd30 user: jan.nijtmans tags: fossil_utf8_to_filename | |
08:30 | merge trunk Leaf check-in: fdd51b617c user: jan.nijtmans tags: ticket-d17d6e5b17 | |
2013-02-17
| ||
21:37 | merge trunk Leaf check-in: fdf9050c4b user: jan.nijtmans tags: improve_commit_warning | |
14:47 | More simplification in UTF-16 bom detection Leaf check-in: 1e70f211f9 user: jan.nijtmans tags: utf16Bom | |
14:43 | Remove two unused variables check-in: a98467b661 user: jan.nijtmans tags: trunk | |
2013-02-16
| ||
14:12 | Limit the complexity of the diff display on check-in information pages. check-in: 4f95ea8c56 user: drh tags: trunk | |
2013-01-28
| ||
13:09 | win32: files with invalid chars were not deleted sometimes with "fossil update" check-in: d9aa512e20 user: jan.nijtmans tags: ticket-d17d6e5b17 | |
Changes to src/file.c.
62 62 63 63 /* 64 64 ** Fill stat buf with information received from stat() or lstat(). 65 65 ** lstat() is called on Unix if isWd is TRUE and allow-symlinks setting is on. 66 66 ** 67 67 */ 68 68 static int fossil_stat(const char *zFilename, struct stat *buf, int isWd){ 69 + int rc; 69 70 #if !defined(_WIN32) 71 + char *zMbcs = fossil_utf8_to_filename(zFilename); 70 72 if( isWd && g.allowSymlinks ){ 71 - return lstat(zFilename, buf); 73 + rc = lstat(zMbcs, buf); 72 74 }else{ 73 - return stat(zFilename, buf); 75 + rc = stat(zMbcs, buf); 74 76 } 75 77 #else 76 - int rc = 0; 77 - wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename); 78 + wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); 78 79 rc = _wstati64(zMbcs, buf); 79 - fossil_unicode_free(zMbcs); 80 +#endif 81 + fossil_filename_free(zMbcs); 80 82 return rc; 81 -#endif 82 83 } 83 84 84 85 /* 85 86 ** Fill in the fileStat variable for the file named zFilename. 86 87 ** If zFilename==0, then use the previous value of fileStat if 87 88 ** there is a previous value. 88 89 ** ................................................................................ 301 302 302 303 303 304 /* 304 305 ** Wrapper around the access() system call. 305 306 */ 306 307 int file_access(const char *zFilename, int flags){ 307 308 #ifdef _WIN32 308 - wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename); 309 + wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); 309 310 int rc = _waccess(zMbcs, flags); 310 - fossil_unicode_free(zMbcs); 311 311 #else 312 - int rc = access(zFilename, flags); 312 + char *zMbcs = fossil_utf8_to_filename(zFilename); 313 + int rc = access(zMbcs, flags); 313 314 #endif 315 + fossil_filename_free(zMbcs); 314 316 return rc; 315 317 } 316 318 317 319 /* 318 320 ** Find an unused filename similar to zBase with zSuffix appended. 319 321 ** 320 322 ** Make the name relative to the working directory if relFlag is true. ................................................................................ 400 402 */ 401 403 void file_set_mtime(const char *zFilename, i64 newMTime){ 402 404 #if !defined(_WIN32) 403 405 struct timeval tv[2]; 404 406 memset(tv, 0, sizeof(tv[0])*2); 405 407 tv[0].tv_sec = newMTime; 406 408 tv[1].tv_sec = newMTime; 407 - utimes(zFilename, tv); 409 + char *zMbcs = fossil_utf8_to_filename(zFilename); 410 + utimes(zMbcs, tv); 408 411 #else 409 412 struct _utimbuf tb; 410 - wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename); 413 + wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); 411 414 tb.actime = newMTime; 412 415 tb.modtime = newMTime; 413 416 _wutime(zMbcs, &tb); 414 - fossil_unicode_free(zMbcs); 415 417 #endif 418 + fossil_filename_free(zMbcs); 416 419 } 417 420 418 421 /* 419 422 ** COMMAND: test-set-mtime 420 423 ** 421 424 ** Usage: %fossil test-set-mtime FILENAME DATE/TIME 422 425 ** ................................................................................ 439 442 } 440 443 441 444 /* 442 445 ** Delete a file. 443 446 */ 444 447 void file_delete(const char *zFilename){ 445 448 #ifdef _WIN32 446 - wchar_t *z = fossil_utf8_to_unicode(zFilename); 449 + wchar_t *z = fossil_utf8_to_filename(zFilename); 447 450 _wunlink(z); 448 - fossil_unicode_free(z); 449 451 #else 452 + char *z = fossil_utf8_to_filename(zFilename); 450 453 unlink(zFilename); 451 454 #endif 455 + fossil_filename_free(z); 452 456 } 453 457 454 458 /* 455 459 ** Create the directory named in the argument, if it does not already 456 460 ** exist. If forceFlag is 1, delete any prior non-directory object 457 461 ** with the same name. 458 462 ** ................................................................................ 462 466 int rc = file_wd_isdir(zName); 463 467 if( rc==2 ){ 464 468 if( !forceFlag ) return 1; 465 469 file_delete(zName); 466 470 } 467 471 if( rc!=1 ){ 468 472 #if defined(_WIN32) 469 - int rc; 470 - wchar_t *zMbcs = fossil_utf8_to_unicode(zName); 473 + wchar_t *zMbcs = fossil_utf8_to_filename(zName); 471 474 rc = _wmkdir(zMbcs); 472 - fossil_unicode_free(zMbcs); 473 - return rc; 474 475 #else 475 - return mkdir(zName, 0755); 476 + char *zMbcs = fossil_utf8_to_filename(zName); 477 + rc = mkdir(zName, 0755); 476 478 #endif 479 + fossil_filename_free(zMbcs); 480 + return rc; 477 481 } 478 482 return 0; 479 483 } 480 484 481 485 /* 482 486 ** Return true if the filename given is a valid filename for 483 487 ** a file in a repository. Valid filenames follow all of the 484 488 ** following rules: 485 489 ** 486 490 ** * Does not begin with "/" 487 491 ** * Does not contain any path element named "." or ".." 488 -** * Does not contain any of these characters in the path: "\" 489 492 ** * Does not end with "/". 490 493 ** * Does not contain two or more "/" characters in a row. 491 494 ** * Contains at least one character 492 495 ** 493 496 ** Invalid UTF8 characters result in a false return if bStrictUtf8 is 494 497 ** true. If bStrictUtf8 is false, invalid UTF8 characters are silently 495 498 ** ignored. See http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ................................................................................ 545 548 return 0; 546 549 } 547 550 if( (z[++i]&0xc0)!=0x80 ){ 548 551 /* Invalid second continuation byte */ 549 552 return 0; 550 553 } 551 554 } 552 - }else if( bStrictUtf8 && (c=='\\') ){ 553 - return 0; 554 555 } 555 556 if( c=='/' ){ 556 557 if( z[i+1]=='/' ) return 0; 557 558 if( z[i+1]=='.' ){ 558 559 if( z[i+2]=='/' || z[i+2]==0 ) return 0; 559 560 if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0; 560 561 } ................................................................................ 578 579 *pJ = i-1; 579 580 return 1; 580 581 } 581 582 582 583 /* 583 584 ** Simplify a filename by 584 585 ** 585 -** * Convert all \ into / on windows 586 +** * Convert all \ into / on windows and cygwin 586 587 ** * removing any trailing and duplicate / 587 588 ** * removing /./ 588 589 ** * removing /A/../ 589 590 ** 590 591 ** Changes are made in-place. Return the new name length. 591 592 ** If the slash parameter is non-zero, the trailing slash, if any, 592 593 ** is retained. 593 594 */ 594 595 int file_simplify_name(char *z, int n, int slash){ 595 596 int i, j; 596 597 if( n<0 ) n = strlen(z); 597 598 598 - /* On windows convert all \ characters to / */ 599 -#if defined(_WIN32) 599 + /* On windows/cygwin convert all \ characters to / */ 600 +#if defined(_WIN32) || defined(__CYGWIN__) 600 601 for(i=0; i<n; i++){ 601 602 if( z[i]=='\\' ) z[i] = '/'; 602 603 } 603 604 #endif 604 605 605 606 /* Removing trailing "/" characters */ 606 607 if( !slash ){ ................................................................................ 703 704 704 705 /* 705 706 ** Return true if zPath is an absolute pathname. Return false 706 707 ** if it is relative. 707 708 */ 708 709 int file_is_absolute_path(const char *zPath){ 709 710 if( zPath[0]=='/' 710 -#if defined(_WIN32) 711 +#if defined(__CYGWIN__) 712 + || zPath[0]=='\\' 713 +#elif defined(_WIN32) 711 714 || zPath[0]=='\\' 712 715 || (strlen(zPath)>3 && zPath[1]==':' 713 716 && (zPath[2]=='\\' || zPath[2]=='/')) 714 717 #endif 715 718 ){ 716 719 return 1; 717 720 }else{ ................................................................................ 1135 1138 1136 1139 /* 1137 1140 ** Like fopen() but always takes a UTF8 argument. 1138 1141 */ 1139 1142 FILE *fossil_fopen(const char *zName, const char *zMode){ 1140 1143 #ifdef _WIN32 1141 1144 wchar_t *uMode = fossil_utf8_to_unicode(zMode); 1142 - wchar_t *uName = fossil_utf8_to_unicode(zName); 1145 + wchar_t *uName = fossil_utf8_to_filename(zName); 1143 1146 FILE *f = _wfopen(uName, uMode); 1144 - fossil_unicode_free(uName); 1147 + fossil_filename_free(uName); 1145 1148 fossil_unicode_free(uMode); 1146 1149 #else 1147 1150 FILE *f = fopen(zName, zMode); 1148 1151 #endif 1149 1152 return f; 1150 1153 }
Changes to src/rebuild.c.
839 839 DIR *d; 840 840 struct dirent *pEntry; 841 841 Blob aContent; /* content of the just read artifact */ 842 842 static int nFileRead = 0; 843 843 void *zUnicodePath; 844 844 char *zUtf8Name; 845 845 846 - zUnicodePath = fossil_utf8_to_unicode(zPath); 846 + zUnicodePath = fossil_utf8_to_filename(zPath); 847 847 d = opendir(zUnicodePath); 848 848 if( d ){ 849 849 while( (pEntry=readdir(d))!=0 ){ 850 850 Blob path; 851 851 char *zSubpath; 852 852 853 853 if( pEntry->d_name[0]=='.' ){ ................................................................................ 873 873 fflush(stdout); 874 874 } 875 875 closedir(d); 876 876 }else { 877 877 fossil_panic("encountered error %d while trying to open \"%s\".", 878 878 errno, g.argv[3]); 879 879 } 880 - fossil_unicode_free(zUnicodePath); 880 + fossil_filename_free(zUnicodePath); 881 881 } 882 882 883 883 /* 884 884 ** COMMAND: reconstruct* 885 885 ** 886 886 ** Usage: %fossil reconstruct FILENAME DIRECTORY 887 887 **
Changes to src/utf8.c.
109 109 110 110 /* 111 111 ** Translate text from the filename character set into 112 112 ** to precomposed UTF8. Return a pointer to the translated text. 113 113 ** Call fossil_filename_free() to deallocate any memory used to store the 114 114 ** returned pointer when done. 115 115 */ 116 -char *fossil_filename_to_utf8(const void *zFilename){ 116 +char *fossil_filename_to_utf8(void *zFilename){ 117 117 #if defined(_WIN32) 118 - int nByte = WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, 0, 0, 0, 0); 119 - char *zUtf = sqlite3_malloc( nByte ); 118 + int nByte; 119 + char *zUtf; 120 + WCHAR *wUnicode = zFilename; 121 + while( *wUnicode != 0 ){ 122 + if ( (*wUnicode & 0xFF80) == 0xF000 ){ 123 + WCHAR converted = (*wUnicode & 0x7F); 124 + /* Only really convert it when the resulting char is in the given range*/ 125 + if ( (converted < 32) || wcschr(L"\"*<>?|:", converted) ){ 126 + *wUnicode = converted; 127 + } 128 + } 129 + ++wUnicode; 130 + } 131 + nByte = WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, 0, 0, 0, 0); 132 + zUtf = sqlite3_malloc( nByte ); 120 133 if( zUtf==0 ){ 121 134 return 0; 122 135 } 123 136 WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0); 124 137 return zUtf; 138 +#elif defined(__CYGWIN__) 139 + char *zOut; 140 + zOut = fossil_strdup(zFilename); 141 + return zOut; 125 142 #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) 126 143 char *zIn = (char*)zFilename; 127 144 char *zOut; 128 145 iconv_t cd; 129 146 size_t n, x; 130 147 for(n=0; zIn[n]>0 && zIn[n]<=0x7f; n++){} 131 148 if( zIn[n]!=0 && (cd = iconv_open("UTF-8", "UTF-8-MAC"))!=(iconv_t)-1 ){ ................................................................................ 147 164 zOut = fossil_strdup(zFilename); 148 165 } 149 166 return zOut; 150 167 #else 151 168 return (char *)zFilename; /* No-op on non-mac unix */ 152 169 #endif 153 170 } 171 + 172 +/* 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. 184 +** 185 +** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html> 186 +** 187 +*/ 188 +void *fossil_utf8_to_filename(const char *zUtf8){ 189 +#ifdef _WIN32 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 +} 154 223 155 224 /* 156 225 ** Deallocate any memory that was previously allocated by 157 -** fossil_filename_to_utf8(). 226 +** fossil_filename_to_utf8() or fossil_utf8_to_filename(). 158 227 */ 159 -void fossil_filename_free(char *pOld){ 228 +void fossil_filename_free(void *pOld){ 160 229 #if defined(_WIN32) 161 230 sqlite3_free(pOld); 162 -#elif defined(__APPLE__) && !defined(WITHOUT_ICONV) 231 +#elif (defined(__APPLE__) && !defined(WITHOUT_ICONV)) || defined(__CYGWIN__) 163 232 fossil_free(pOld); 164 233 #else 165 234 /* No-op on all other unix */ 166 235 #endif 167 236 } 168 237 169 238 /*
Changes to src/vfile.c.
457 457 "INSERT OR IGNORE INTO sfile(x) SELECT :file" 458 458 " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=:file)" 459 459 ); 460 460 } 461 461 depth++; 462 462 463 463 zDir = blob_str(pPath); 464 - zNative = fossil_utf8_to_unicode(zDir); 464 + zNative = fossil_utf8_to_filename(zDir); 465 465 d = opendir(zNative); 466 466 if( d ){ 467 467 while( (pEntry=readdir(d))!=0 ){ 468 468 char *zPath; 469 469 char *zUtf8; 470 470 if( pEntry->d_name[0]=='.' ){ 471 471 if( (scanFlags & SCAN_ALL)==0 ) continue; ................................................................................ 489 489 } 490 490 } 491 491 fossil_filename_free(zUtf8); 492 492 blob_resize(pPath, origSize); 493 493 } 494 494 closedir(d); 495 495 } 496 - fossil_unicode_free(zNative); 496 + fossil_filename_free(zNative); 497 497 498 498 depth--; 499 499 if( depth==0 ){ 500 500 db_finalize(&ins); 501 501 } 502 502 } 503 503