Fossil SCM
Added code to detect if the working directory file system is one that supports symlinks so that we won't try to do symlink processing when the platform does not support it.
Commit
5d251b673983cd93bd4eef26c87bd7608fed8752
Parent
db2128fa24cac46…
2 files changed
+1
-1
+33
-4
+1
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -1116,11 +1116,11 @@ | ||
| 1116 | 1116 | mPerm = file_wd_perm(blob_str(&filename)); |
| 1117 | 1117 | #if !defined(_WIN32) |
| 1118 | 1118 | isExe = ( mPerm==PERM_EXE ); |
| 1119 | 1119 | #endif |
| 1120 | 1120 | #if defined(_WIN32) |
| 1121 | - if (win32_symlinks_supported()) | |
| 1121 | + if (win32_symlinks_supported(blob_str(&filename))) | |
| 1122 | 1122 | #endif |
| 1123 | 1123 | isLink = ( mPerm==PERM_LNK ); |
| 1124 | 1124 | } |
| 1125 | 1125 | |
| 1126 | 1126 | if( isExe ){ |
| 1127 | 1127 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1116,11 +1116,11 @@ | |
| 1116 | mPerm = file_wd_perm(blob_str(&filename)); |
| 1117 | #if !defined(_WIN32) |
| 1118 | isExe = ( mPerm==PERM_EXE ); |
| 1119 | #endif |
| 1120 | #if defined(_WIN32) |
| 1121 | if (win32_symlinks_supported()) |
| 1122 | #endif |
| 1123 | isLink = ( mPerm==PERM_LNK ); |
| 1124 | } |
| 1125 | |
| 1126 | if( isExe ){ |
| 1127 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1116,11 +1116,11 @@ | |
| 1116 | mPerm = file_wd_perm(blob_str(&filename)); |
| 1117 | #if !defined(_WIN32) |
| 1118 | isExe = ( mPerm==PERM_EXE ); |
| 1119 | #endif |
| 1120 | #if defined(_WIN32) |
| 1121 | if (win32_symlinks_supported(blob_str(&filename))) |
| 1122 | #endif |
| 1123 | isLink = ( mPerm==PERM_LNK ); |
| 1124 | } |
| 1125 | |
| 1126 | if( isExe ){ |
| 1127 |
+33
-4
| --- src/winfile.c | ||
| +++ src/winfile.c | ||
| @@ -276,22 +276,28 @@ | ||
| 276 | 276 | |
| 277 | 277 | return !created; |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | 280 | /* |
| 281 | -** Check if symlinks are potentially supported on the current OS. | |
| 281 | +** Check if symlinks are potentially supported on the current OS for the given file. | |
| 282 | 282 | ** Theoretically this code should work on any NT based version of windows |
| 283 | 283 | ** but I have no way of testing that. The initial check for |
| 284 | 284 | ** IsWindowsVistaOrGreater() should in theory eliminate any system prior to |
| 285 | 285 | ** Windows Vista, but I have no way to test that at this time. |
| 286 | 286 | ** Return 1 if supported, 0 if not. |
| 287 | 287 | */ |
| 288 | -int win32_symlinks_supported(){ | |
| 288 | +int win32_symlinks_supported(const char* zFilename){ | |
| 289 | 289 | TOKEN_PRIVILEGES tp; |
| 290 | 290 | LUID luid; |
| 291 | 291 | HANDLE process, token; |
| 292 | 292 | DWORD status; |
| 293 | + int success; | |
| 294 | + wchar_t *pFilename; | |
| 295 | + wchar_t fullName[MAX_PATH+1]; | |
| 296 | + DWORD fullLength; | |
| 297 | + wchar_t volName[MAX_PATH+1]; | |
| 298 | + DWORD fsFlags; | |
| 293 | 299 | |
| 294 | 300 | /* symlinks only supported on vista or greater */ |
| 295 | 301 | if (!IsWindowsVistaOrGreater()) |
| 296 | 302 | return 0; |
| 297 | 303 | |
| @@ -319,13 +325,36 @@ | ||
| 319 | 325 | CloseHandle(token); |
| 320 | 326 | |
| 321 | 327 | /* any error means we failed to enable the privilege, symlinks not supported */ |
| 322 | 328 | if (status != ERROR_SUCCESS) |
| 323 | 329 | return 0; |
| 330 | + | |
| 331 | + /* assume no support for symlinks */ | |
| 332 | + success = 0; | |
| 333 | + | |
| 334 | + pFilename = fossil_utf8_to_filename(zFilename); | |
| 335 | + | |
| 336 | + /* given the filename we're interested in, symlinks are supported if */ | |
| 337 | + /* 1. we can get the full name of the path from the given path */ | |
| 338 | + fullLength = GetFullPathNameW(pFilename, sizeof(fullName), fullName, NULL); | |
| 339 | + if ((fullLength > 0) && (fullLength < sizeof(fullName))){ | |
| 340 | + /* 2. we can get the volume path name from the full name */ | |
| 341 | + if (GetVolumePathNameW(fullName, volName, sizeof(volName))){ | |
| 342 | + /* 3. we can get volume information from the volume path name */ | |
| 343 | + if (GetVolumeInformationW(volName, NULL, 0, NULL, NULL, &fsFlags, NULL, 0)){ | |
| 344 | + /* 4. the given volume support reparse points */ | |
| 345 | + if (fsFlags & FILE_SUPPORTS_REPARSE_POINTS){ | |
| 346 | + /* all four conditions were true, so we support symlinks; success! */ | |
| 347 | + success = 1; | |
| 348 | + } | |
| 349 | + } | |
| 350 | + } | |
| 351 | + } | |
| 324 | 352 | |
| 325 | - /* we made it this far, symlinks must be supported */ | |
| 326 | - return 1; | |
| 353 | + fossil_filename_free(pFilename); | |
| 354 | + | |
| 355 | + return success; | |
| 327 | 356 | } |
| 328 | 357 | |
| 329 | 358 | /* |
| 330 | 359 | ** Wrapper around the access() system call. This code was copied from Tcl |
| 331 | 360 | ** 8.6 and then modified. |
| 332 | 361 |
| --- src/winfile.c | |
| +++ src/winfile.c | |
| @@ -276,22 +276,28 @@ | |
| 276 | |
| 277 | return !created; |
| 278 | } |
| 279 | |
| 280 | /* |
| 281 | ** Check if symlinks are potentially supported on the current OS. |
| 282 | ** Theoretically this code should work on any NT based version of windows |
| 283 | ** but I have no way of testing that. The initial check for |
| 284 | ** IsWindowsVistaOrGreater() should in theory eliminate any system prior to |
| 285 | ** Windows Vista, but I have no way to test that at this time. |
| 286 | ** Return 1 if supported, 0 if not. |
| 287 | */ |
| 288 | int win32_symlinks_supported(){ |
| 289 | TOKEN_PRIVILEGES tp; |
| 290 | LUID luid; |
| 291 | HANDLE process, token; |
| 292 | DWORD status; |
| 293 | |
| 294 | /* symlinks only supported on vista or greater */ |
| 295 | if (!IsWindowsVistaOrGreater()) |
| 296 | return 0; |
| 297 | |
| @@ -319,13 +325,36 @@ | |
| 319 | CloseHandle(token); |
| 320 | |
| 321 | /* any error means we failed to enable the privilege, symlinks not supported */ |
| 322 | if (status != ERROR_SUCCESS) |
| 323 | return 0; |
| 324 | |
| 325 | /* we made it this far, symlinks must be supported */ |
| 326 | return 1; |
| 327 | } |
| 328 | |
| 329 | /* |
| 330 | ** Wrapper around the access() system call. This code was copied from Tcl |
| 331 | ** 8.6 and then modified. |
| 332 |
| --- src/winfile.c | |
| +++ src/winfile.c | |
| @@ -276,22 +276,28 @@ | |
| 276 | |
| 277 | return !created; |
| 278 | } |
| 279 | |
| 280 | /* |
| 281 | ** Check if symlinks are potentially supported on the current OS for the given file. |
| 282 | ** Theoretically this code should work on any NT based version of windows |
| 283 | ** but I have no way of testing that. The initial check for |
| 284 | ** IsWindowsVistaOrGreater() should in theory eliminate any system prior to |
| 285 | ** Windows Vista, but I have no way to test that at this time. |
| 286 | ** Return 1 if supported, 0 if not. |
| 287 | */ |
| 288 | int win32_symlinks_supported(const char* zFilename){ |
| 289 | TOKEN_PRIVILEGES tp; |
| 290 | LUID luid; |
| 291 | HANDLE process, token; |
| 292 | DWORD status; |
| 293 | int success; |
| 294 | wchar_t *pFilename; |
| 295 | wchar_t fullName[MAX_PATH+1]; |
| 296 | DWORD fullLength; |
| 297 | wchar_t volName[MAX_PATH+1]; |
| 298 | DWORD fsFlags; |
| 299 | |
| 300 | /* symlinks only supported on vista or greater */ |
| 301 | if (!IsWindowsVistaOrGreater()) |
| 302 | return 0; |
| 303 | |
| @@ -319,13 +325,36 @@ | |
| 325 | CloseHandle(token); |
| 326 | |
| 327 | /* any error means we failed to enable the privilege, symlinks not supported */ |
| 328 | if (status != ERROR_SUCCESS) |
| 329 | return 0; |
| 330 | |
| 331 | /* assume no support for symlinks */ |
| 332 | success = 0; |
| 333 | |
| 334 | pFilename = fossil_utf8_to_filename(zFilename); |
| 335 | |
| 336 | /* given the filename we're interested in, symlinks are supported if */ |
| 337 | /* 1. we can get the full name of the path from the given path */ |
| 338 | fullLength = GetFullPathNameW(pFilename, sizeof(fullName), fullName, NULL); |
| 339 | if ((fullLength > 0) && (fullLength < sizeof(fullName))){ |
| 340 | /* 2. we can get the volume path name from the full name */ |
| 341 | if (GetVolumePathNameW(fullName, volName, sizeof(volName))){ |
| 342 | /* 3. we can get volume information from the volume path name */ |
| 343 | if (GetVolumeInformationW(volName, NULL, 0, NULL, NULL, &fsFlags, NULL, 0)){ |
| 344 | /* 4. the given volume support reparse points */ |
| 345 | if (fsFlags & FILE_SUPPORTS_REPARSE_POINTS){ |
| 346 | /* all four conditions were true, so we support symlinks; success! */ |
| 347 | success = 1; |
| 348 | } |
| 349 | } |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | fossil_filename_free(pFilename); |
| 354 | |
| 355 | return success; |
| 356 | } |
| 357 | |
| 358 | /* |
| 359 | ** Wrapper around the access() system call. This code was copied from Tcl |
| 360 | ** 8.6 and then modified. |
| 361 |