Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Another update for[9919dfbbaa]: Make sure reallocated buffers always grow, guard all buffer writes by overflow checks (next time use blobs), make sure the `case-sensitive' setting and command-line option are followed, and use brute force to achieve binary (vs.linguistic) file name comparison (only on older versions of Windows). |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
fe6ef89f5f9d23e09c899e854d6dc796 |
| User & Date: | florian 2024-10-19 14:03:00.000 |
References
|
2024-10-20
| ||
| 04:24 | Fix an oversight in [fe6ef89f5f]. check-in: 95c1490cd6 user: florian tags: trunk | |
Context
|
2024-10-19
| ||
| 14:10 | Resolve accidental fork. check-in: 6041e258ba user: florian tags: trunk | |
| 14:03 | Another update for[9919dfbbaa]: Make sure reallocated buffers always grow, guard all buffer writes by overflow checks (next time use blobs), make sure the `case-sensitive' setting and command-line option are followed, and use brute force to achieve binary (vs.linguistic) file name comparison (only on older versions of Windows). check-in: fe6ef89f5f user: florian tags: trunk | |
|
2024-10-17
| ||
| 16:54 | Merge brickviking's documentation typo fixes to trunk. check-in: efd79f87f5 user: drh tags: trunk | |
Changes
Changes to src/file.c.
| ︙ | ︙ | |||
1406 1407 1408 1409 1410 1411 1412 |
fossil_path_free(zUtf8);
}
closedir(d);
}
fossil_path_free(zNative);
if( zResult==0 ) zResult = fossil_strdup(zPath);
return zResult;
| | | | 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 |
fossil_path_free(zUtf8);
}
closedir(d);
}
fossil_path_free(zNative);
if( zResult==0 ) zResult = fossil_strdup(zPath);
return zResult;
#else /* !_WIN32 */
return win32_file_case_preferred_name(zDir,zPath);
#endif /* !_WIN32 */
}
/*
** COMMAND: test-case-filename
**
** Usage: fossil test-case-filename DIRECTORY PATH PATH PATH ....
**
|
| ︙ | ︙ |
Changes to src/winfile.c.
| ︙ | ︙ | |||
291 292 293 294 295 296 297 | for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/'; strncpy(zBuf, zUtf8, nBuf); fossil_path_free(zUtf8); } /* Perform case-insensitive comparison of two UTF-16 file names. Try to load the ** CompareStringOrdinal() function on Windows Vista and newer, and resort to the | | > > > > > | > > | > | | | > > > > > > > > > > > > > | > | > > > | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/';
strncpy(zBuf, zUtf8, nBuf);
fossil_path_free(zUtf8);
}
/* Perform case-insensitive comparison of two UTF-16 file names. Try to load the
** CompareStringOrdinal() function on Windows Vista and newer, and resort to the
** RtlEqualUnicodeString() function on Windows XP.
** The dance to invoke RtlEqualUnicodeString() is necessary because lstrcmpiW()
** performs linguistic comparison, while the former performs binary comparison.
** As an example, matching "ß" (U+00DF Latin Small Letter Sharp S) with "ss" is
** undesirable in file name comparison, so lstrcmpiW() is only invoked in cases
** that are technically impossible and contradicting all known laws of physics.
*/
int win32_filenames_equal_nocase(
const wchar_t *fn1,
const wchar_t *fn2
){
static FARPROC fnCompareStringOrdinal;
static FARPROC fnRtlInitUnicodeString;
static FARPROC fnRtlEqualUnicodeString;
static int loaded_CompareStringOrdinal;
static int loaded_RtlUnicodeStringAPIs;
if( !loaded_CompareStringOrdinal ){
fnCompareStringOrdinal =
GetProcAddress(GetModuleHandleA("kernel32"),"CompareStringOrdinal");
loaded_CompareStringOrdinal = 1;
}
if( fnCompareStringOrdinal ){
return fnCompareStringOrdinal(fn1,-1,fn2,-1,1)-2==0;
}
if( !loaded_RtlUnicodeStringAPIs ){
fnRtlInitUnicodeString =
GetProcAddress(GetModuleHandleA("ntdll"),"RtlInitUnicodeString");
fnRtlEqualUnicodeString =
GetProcAddress(GetModuleHandleA("ntdll"),"RtlEqualUnicodeString");
loaded_RtlUnicodeStringAPIs = 1;
}
if( fnRtlInitUnicodeString && fnRtlEqualUnicodeString ){
struct { /* UNICODE_STRING from <ntdef.h> */
unsigned short Length;
unsigned short MaximumLength;
wchar_t *Buffer;
} u1, u2;
fnRtlInitUnicodeString(&u1,fn1);
fnRtlInitUnicodeString(&u2,fn2);
return (unsigned char)fnRtlEqualUnicodeString(&u1,&u2,1);
}
/* In what kind of strange parallel universe are we? */
return lstrcmpiW(fn1,fn2)==0;
}
/* Helper macros to deal with directory separators. */
#define IS_DIRSEP(s,i) ( s[i]=='/' || s[i]=='\\' )
#define NEXT_DIRSEP(s,i) while( s[i] && s[i]!='/' && s[i]!='\\' ){i++;}
/* The Win32 version of file_case_preferred_name() from file.c, which is able to
|
| ︙ | ︙ | |||
345 346 347 348 349 350 351 |
** information class FILE_CASE_SENSITIVE_INFORMATION. So this function may be
** changed to act like fossil_strdup() for files located in such directories.
*/
char *win32_file_case_preferred_name(
const char *zBase,
const char *zPath
){
| > > > > > > > > > > > | | | | | | | < > > > > | | | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
** information class FILE_CASE_SENSITIVE_INFORMATION. So this function may be
** changed to act like fossil_strdup() for files located in such directories.
*/
char *win32_file_case_preferred_name(
const char *zBase,
const char *zPath
){
int cchBase;
int cchPath;
int cchBuf;
int cchRes;
char *zBuf;
char *zRes;
int ncUsed;
int i, j;
if( filenames_are_case_sensitive() ){
return fossil_strdup(zPath);
}
cchBase = strlen(zBase);
cchPath = strlen(zPath);
cchBuf = cchBase + cchPath + 2; /* + NULL + optional directory slash */
cchRes = cchPath + 1; /* + NULL */
zBuf = fossil_malloc(cchBuf);
zRes = fossil_malloc(cchRes);
ncUsed = 0;
memcpy(zBuf,zBase,cchBase);
if( !IS_DIRSEP(zBuf,cchBase-1) ){
zBuf[cchBase++]=L'/';
}
memcpy(zBuf+cchBase,zPath,cchPath+1);
i = j = cchBase;
while( 1 ){
WIN32_FIND_DATAW fd;
HANDLE hFind;
wchar_t *wzBuf;
char *zCompBuf = 0;
char *zComp = &zBuf[i];
int cchComp;
char chSep;
int fDone;
if( IS_DIRSEP(zBuf,i) ){
zRes[ncUsed++] = zBuf[i];
if( ncUsed+2>cchRes ){ /* Directory slash + NULL*/
cchRes += 32; /* Overprovisioning. */
zRes = fossil_realloc(zRes,cchRes);
}
i = j = i+1;
continue;
}
NEXT_DIRSEP(zBuf,j);
fDone = zBuf[j]==0;
chSep = zBuf[j];
zBuf[j] = 0; /* Truncate working buffer. */
wzBuf = fossil_utf8_to_path(zBuf,0);
hFind = FindFirstFileW(wzBuf,&fd);
if( hFind!=INVALID_HANDLE_VALUE ){
wchar_t *wzComp = fossil_utf8_to_path(zComp,0);
FindClose(hFind);
/* Test fd.cFileName, not fd.cAlternateFileName (classic 8.3 format). */
if( win32_filenames_equal_nocase(wzComp,fd.cFileName) ){
zCompBuf = fossil_path_to_utf8(fd.cFileName);
zComp = zCompBuf;
}
fossil_path_free(wzComp);
}
fossil_path_free(wzBuf);
cchComp = strlen(zComp);
if( ncUsed+cchComp+1>cchRes ){ /* Current component + NULL */
cchRes += cchComp + 32; /* Overprovisioning. */
zRes = fossil_realloc(zRes,cchRes);
}
memcpy(zRes+ncUsed,zComp,cchComp);
ncUsed += cchComp;
if( zCompBuf ){
fossil_path_free(zCompBuf);
}
|
| ︙ | ︙ |