Fossil SCM
Fix fossil_stat() and fossil_chdir() such that they accept paths>MAX_PATH. For file_access(), implement a workaround that the '\\?\' prefix can be handled.
Commit
29f023fe536c49b2bfc222e785b3e5ec6ea1aac5
Parent
da8d516fe1a4c04…
1 file changed
+29
-13
+29
-13
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -47,11 +47,16 @@ | ||
| 47 | 47 | ** Use _stati64 rather than stat on windows, in order to handle files |
| 48 | 48 | ** larger than 2GB. |
| 49 | 49 | */ |
| 50 | 50 | #if defined(_WIN32) && (defined(__MSVCRT__) || defined(_MSC_VER)) |
| 51 | 51 | # undef stat |
| 52 | -# define stat _stati64 | |
| 52 | +# define stat _fossil_stati64 | |
| 53 | +struct stat { | |
| 54 | + i64 st_size; | |
| 55 | + i64 st_mtime; | |
| 56 | + int st_mode; | |
| 57 | +}; | |
| 53 | 58 | #endif |
| 54 | 59 | /* |
| 55 | 60 | ** On Windows S_ISLNK always returns FALSE. |
| 56 | 61 | */ |
| 57 | 62 | #if !defined(S_ISLNK) |
| @@ -73,21 +78,21 @@ | ||
| 73 | 78 | rc = lstat(zMbcs, buf); |
| 74 | 79 | }else{ |
| 75 | 80 | rc = stat(zMbcs, buf); |
| 76 | 81 | } |
| 77 | 82 | #else |
| 83 | + WIN32_FILE_ATTRIBUTE_DATA attr; | |
| 78 | 84 | wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); |
| 79 | - if( memcmp(zMbcs, L"\\\\?\\", 8)==0 ){ | |
| 80 | - /* Unfortunately, _wstati64 cannot handle extended prefixes. */ | |
| 81 | - if( memcmp(zMbcs+4, "UNC\\", 8)==0 ){ | |
| 82 | - zMbcs[6] = '\\'; | |
| 83 | - rc = _wstati64(zMbcs+6, buf); | |
| 84 | - }else{ | |
| 85 | - rc = _wstati64(zMbcs+4, buf); | |
| 86 | - } | |
| 87 | - }else{ | |
| 88 | - rc = _wstati64(zMbcs, buf); | |
| 85 | + rc = !GetFileAttributesExW(zMbcs, GetFileExInfoStandard, &attr); | |
| 86 | + if( !rc ){ | |
| 87 | + ULARGE_INTEGER ull; | |
| 88 | + ull.LowPart = attr.ftLastWriteTime.dwLowDateTime; | |
| 89 | + ull.HighPart = attr.ftLastWriteTime.dwHighDateTime; | |
| 90 | + buf->st_mode = (attr.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)? | |
| 91 | + S_IFDIR:S_IFREG; | |
| 92 | + buf->st_size = (((i64)attr.nFileSizeHigh)<<32) | buf->attr.nFileSizeLow; | |
| 93 | + buf->st_mtime = ull.QuadPart / 10000000ULL - 11644473600ULL; | |
| 89 | 94 | } |
| 90 | 95 | #endif |
| 91 | 96 | fossil_filename_free(zMbcs); |
| 92 | 97 | return rc; |
| 93 | 98 | } |
| @@ -314,11 +319,22 @@ | ||
| 314 | 319 | ** Wrapper around the access() system call. |
| 315 | 320 | */ |
| 316 | 321 | int file_access(const char *zFilename, int flags){ |
| 317 | 322 | #ifdef _WIN32 |
| 318 | 323 | wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); |
| 319 | - int rc = _waccess(zMbcs, flags); | |
| 324 | + int rc; | |
| 325 | + if( memcmp(zMbcs, L"\\\\?\\", 8)==0 ){ | |
| 326 | + /* Unfortunately, _waccess cannot handle extended prefixes. */ | |
| 327 | + if( memcmp(zMbcs+4, "UNC\\", 8)==0 ){ | |
| 328 | + zMbcs[6] = '\\'; | |
| 329 | + rc = _waccess(zMbcs+6, flags); | |
| 330 | + }else{ | |
| 331 | + rc = _waccess(zMbcs+4, flags); | |
| 332 | + } | |
| 333 | + }else{ | |
| 334 | + rc = _waccess(zMbcs, flags); | |
| 335 | + } | |
| 320 | 336 | #else |
| 321 | 337 | char *zMbcs = fossil_utf8_to_filename(zFilename); |
| 322 | 338 | int rc = access(zMbcs, flags); |
| 323 | 339 | #endif |
| 324 | 340 | fossil_filename_free(zMbcs); |
| @@ -331,11 +347,11 @@ | ||
| 331 | 347 | ** (UNIX only) |
| 332 | 348 | */ |
| 333 | 349 | int file_chdir(const char *zChDir, int bChroot){ |
| 334 | 350 | #ifdef _WIN32 |
| 335 | 351 | wchar_t *zPath = fossil_utf8_to_filename(zChDir); |
| 336 | - int rc = _wchdir(zPath); | |
| 352 | + int rc = SetCurrentDirectoryW(zPath)==0; | |
| 337 | 353 | #else |
| 338 | 354 | char *zPath = fossil_utf8_to_filename(zChDir); |
| 339 | 355 | int rc = chdir(zPath); |
| 340 | 356 | if( !rc && bChroot ){ |
| 341 | 357 | rc = chroot(zPath); |
| 342 | 358 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -47,11 +47,16 @@ | |
| 47 | ** Use _stati64 rather than stat on windows, in order to handle files |
| 48 | ** larger than 2GB. |
| 49 | */ |
| 50 | #if defined(_WIN32) && (defined(__MSVCRT__) || defined(_MSC_VER)) |
| 51 | # undef stat |
| 52 | # define stat _stati64 |
| 53 | #endif |
| 54 | /* |
| 55 | ** On Windows S_ISLNK always returns FALSE. |
| 56 | */ |
| 57 | #if !defined(S_ISLNK) |
| @@ -73,21 +78,21 @@ | |
| 73 | rc = lstat(zMbcs, buf); |
| 74 | }else{ |
| 75 | rc = stat(zMbcs, buf); |
| 76 | } |
| 77 | #else |
| 78 | wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); |
| 79 | if( memcmp(zMbcs, L"\\\\?\\", 8)==0 ){ |
| 80 | /* Unfortunately, _wstati64 cannot handle extended prefixes. */ |
| 81 | if( memcmp(zMbcs+4, "UNC\\", 8)==0 ){ |
| 82 | zMbcs[6] = '\\'; |
| 83 | rc = _wstati64(zMbcs+6, buf); |
| 84 | }else{ |
| 85 | rc = _wstati64(zMbcs+4, buf); |
| 86 | } |
| 87 | }else{ |
| 88 | rc = _wstati64(zMbcs, buf); |
| 89 | } |
| 90 | #endif |
| 91 | fossil_filename_free(zMbcs); |
| 92 | return rc; |
| 93 | } |
| @@ -314,11 +319,22 @@ | |
| 314 | ** Wrapper around the access() system call. |
| 315 | */ |
| 316 | int file_access(const char *zFilename, int flags){ |
| 317 | #ifdef _WIN32 |
| 318 | wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); |
| 319 | int rc = _waccess(zMbcs, flags); |
| 320 | #else |
| 321 | char *zMbcs = fossil_utf8_to_filename(zFilename); |
| 322 | int rc = access(zMbcs, flags); |
| 323 | #endif |
| 324 | fossil_filename_free(zMbcs); |
| @@ -331,11 +347,11 @@ | |
| 331 | ** (UNIX only) |
| 332 | */ |
| 333 | int file_chdir(const char *zChDir, int bChroot){ |
| 334 | #ifdef _WIN32 |
| 335 | wchar_t *zPath = fossil_utf8_to_filename(zChDir); |
| 336 | int rc = _wchdir(zPath); |
| 337 | #else |
| 338 | char *zPath = fossil_utf8_to_filename(zChDir); |
| 339 | int rc = chdir(zPath); |
| 340 | if( !rc && bChroot ){ |
| 341 | rc = chroot(zPath); |
| 342 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -47,11 +47,16 @@ | |
| 47 | ** Use _stati64 rather than stat on windows, in order to handle files |
| 48 | ** larger than 2GB. |
| 49 | */ |
| 50 | #if defined(_WIN32) && (defined(__MSVCRT__) || defined(_MSC_VER)) |
| 51 | # undef stat |
| 52 | # define stat _fossil_stati64 |
| 53 | struct stat { |
| 54 | i64 st_size; |
| 55 | i64 st_mtime; |
| 56 | int st_mode; |
| 57 | }; |
| 58 | #endif |
| 59 | /* |
| 60 | ** On Windows S_ISLNK always returns FALSE. |
| 61 | */ |
| 62 | #if !defined(S_ISLNK) |
| @@ -73,21 +78,21 @@ | |
| 78 | rc = lstat(zMbcs, buf); |
| 79 | }else{ |
| 80 | rc = stat(zMbcs, buf); |
| 81 | } |
| 82 | #else |
| 83 | WIN32_FILE_ATTRIBUTE_DATA attr; |
| 84 | wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); |
| 85 | rc = !GetFileAttributesExW(zMbcs, GetFileExInfoStandard, &attr); |
| 86 | if( !rc ){ |
| 87 | ULARGE_INTEGER ull; |
| 88 | ull.LowPart = attr.ftLastWriteTime.dwLowDateTime; |
| 89 | ull.HighPart = attr.ftLastWriteTime.dwHighDateTime; |
| 90 | buf->st_mode = (attr.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)? |
| 91 | S_IFDIR:S_IFREG; |
| 92 | buf->st_size = (((i64)attr.nFileSizeHigh)<<32) | buf->attr.nFileSizeLow; |
| 93 | buf->st_mtime = ull.QuadPart / 10000000ULL - 11644473600ULL; |
| 94 | } |
| 95 | #endif |
| 96 | fossil_filename_free(zMbcs); |
| 97 | return rc; |
| 98 | } |
| @@ -314,11 +319,22 @@ | |
| 319 | ** Wrapper around the access() system call. |
| 320 | */ |
| 321 | int file_access(const char *zFilename, int flags){ |
| 322 | #ifdef _WIN32 |
| 323 | wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); |
| 324 | int rc; |
| 325 | if( memcmp(zMbcs, L"\\\\?\\", 8)==0 ){ |
| 326 | /* Unfortunately, _waccess cannot handle extended prefixes. */ |
| 327 | if( memcmp(zMbcs+4, "UNC\\", 8)==0 ){ |
| 328 | zMbcs[6] = '\\'; |
| 329 | rc = _waccess(zMbcs+6, flags); |
| 330 | }else{ |
| 331 | rc = _waccess(zMbcs+4, flags); |
| 332 | } |
| 333 | }else{ |
| 334 | rc = _waccess(zMbcs, flags); |
| 335 | } |
| 336 | #else |
| 337 | char *zMbcs = fossil_utf8_to_filename(zFilename); |
| 338 | int rc = access(zMbcs, flags); |
| 339 | #endif |
| 340 | fossil_filename_free(zMbcs); |
| @@ -331,11 +347,11 @@ | |
| 347 | ** (UNIX only) |
| 348 | */ |
| 349 | int file_chdir(const char *zChDir, int bChroot){ |
| 350 | #ifdef _WIN32 |
| 351 | wchar_t *zPath = fossil_utf8_to_filename(zChDir); |
| 352 | int rc = SetCurrentDirectoryW(zPath)==0; |
| 353 | #else |
| 354 | char *zPath = fossil_utf8_to_filename(zChDir); |
| 355 | int rc = chdir(zPath); |
| 356 | if( !rc && bChroot ){ |
| 357 | rc = chroot(zPath); |
| 358 |