Fossil SCM
Implement the equivalent to the `inode' SQL function on Windows.
Commit
5233364196e06d89c0f2af49d7ccaa80020c4d5b6b4f14cf29b2bbf8b8e38920
Parent
38930fbabe9b35a…
2 files changed
+9
-4
+68
+9
-4
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -2996,12 +2996,13 @@ | ||
| 2996 | 2996 | ** a regular file, then the return string is of the form: |
| 2997 | 2997 | ** |
| 2998 | 2998 | ** DEV/INODE |
| 2999 | 2999 | ** |
| 3000 | 3000 | ** Where DEV and INODE are the device number and inode number for |
| 3001 | -** the file. Or, on Windows, the return value is the canonical | |
| 3002 | -** name of the file, because Windows does not have INODEs. | |
| 3001 | +** the file. On Windows, the volume serial number (DEV) and file | |
| 3002 | +** identifier (INODE) are used to compute the value, see comments | |
| 3003 | +** on the win32_file_id() function. | |
| 3003 | 3004 | ** |
| 3004 | 3005 | ** If FILENAME does not exist, then the return is an empty string. |
| 3005 | 3006 | ** |
| 3006 | 3007 | ** The value of inode() can be used to eliminate files from a list |
| 3007 | 3008 | ** that have duplicates because they have differing names due to links. |
| @@ -3024,12 +3025,16 @@ | ||
| 3024 | 3025 | sqlite3_result_text(context, "", 0, SQLITE_STATIC); |
| 3025 | 3026 | return; |
| 3026 | 3027 | } |
| 3027 | 3028 | #if defined(_WIN32) |
| 3028 | 3029 | { |
| 3029 | - const char *zCanonical = file_canonical_name_dup(zFilename); | |
| 3030 | - sqlite3_result_text(context, zCanonical, -1, fossil_free); | |
| 3030 | + char *zFileId = win32_file_id(zFilename); | |
| 3031 | + if( zFileId ){ | |
| 3032 | + sqlite3_result_text(context, zFileId, -1, fossil_free); | |
| 3033 | + }else{ | |
| 3034 | + sqlite3_result_text(context, "", 0, SQLITE_STATIC); | |
| 3035 | + } | |
| 3031 | 3036 | } |
| 3032 | 3037 | #else |
| 3033 | 3038 | { |
| 3034 | 3039 | struct stat buf; |
| 3035 | 3040 | int rc; |
| 3036 | 3041 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -2996,12 +2996,13 @@ | |
| 2996 | ** a regular file, then the return string is of the form: |
| 2997 | ** |
| 2998 | ** DEV/INODE |
| 2999 | ** |
| 3000 | ** Where DEV and INODE are the device number and inode number for |
| 3001 | ** the file. Or, on Windows, the return value is the canonical |
| 3002 | ** name of the file, because Windows does not have INODEs. |
| 3003 | ** |
| 3004 | ** If FILENAME does not exist, then the return is an empty string. |
| 3005 | ** |
| 3006 | ** The value of inode() can be used to eliminate files from a list |
| 3007 | ** that have duplicates because they have differing names due to links. |
| @@ -3024,12 +3025,16 @@ | |
| 3024 | sqlite3_result_text(context, "", 0, SQLITE_STATIC); |
| 3025 | return; |
| 3026 | } |
| 3027 | #if defined(_WIN32) |
| 3028 | { |
| 3029 | const char *zCanonical = file_canonical_name_dup(zFilename); |
| 3030 | sqlite3_result_text(context, zCanonical, -1, fossil_free); |
| 3031 | } |
| 3032 | #else |
| 3033 | { |
| 3034 | struct stat buf; |
| 3035 | int rc; |
| 3036 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -2996,12 +2996,13 @@ | |
| 2996 | ** a regular file, then the return string is of the form: |
| 2997 | ** |
| 2998 | ** DEV/INODE |
| 2999 | ** |
| 3000 | ** Where DEV and INODE are the device number and inode number for |
| 3001 | ** the file. On Windows, the volume serial number (DEV) and file |
| 3002 | ** identifier (INODE) are used to compute the value, see comments |
| 3003 | ** on the win32_file_id() function. |
| 3004 | ** |
| 3005 | ** If FILENAME does not exist, then the return is an empty string. |
| 3006 | ** |
| 3007 | ** The value of inode() can be used to eliminate files from a list |
| 3008 | ** that have duplicates because they have differing names due to links. |
| @@ -3024,12 +3025,16 @@ | |
| 3025 | sqlite3_result_text(context, "", 0, SQLITE_STATIC); |
| 3026 | return; |
| 3027 | } |
| 3028 | #if defined(_WIN32) |
| 3029 | { |
| 3030 | char *zFileId = win32_file_id(zFilename); |
| 3031 | if( zFileId ){ |
| 3032 | sqlite3_result_text(context, zFileId, -1, fossil_free); |
| 3033 | }else{ |
| 3034 | sqlite3_result_text(context, "", 0, SQLITE_STATIC); |
| 3035 | } |
| 3036 | } |
| 3037 | #else |
| 3038 | { |
| 3039 | struct stat buf; |
| 3040 | int rc; |
| 3041 |
+68
| --- src/winfile.c | ||
| +++ src/winfile.c | ||
| @@ -451,6 +451,74 @@ | ||
| 451 | 451 | i = j; |
| 452 | 452 | } |
| 453 | 453 | fossil_free(zBuf); |
| 454 | 454 | return zRes; |
| 455 | 455 | } |
| 456 | + | |
| 457 | +/* Return the unique identifier (UID) for a file, made up of the file identifier | |
| 458 | +** (equal to "inode" for Unix-style file systems) plus the volume serial number. | |
| 459 | +** Call the GetFileInformationByHandleEx() function on Windows Vista, and resort | |
| 460 | +** to the GetFileInformationByHandle() function on Windows XP. The result string | |
| 461 | +** is allocated by mprintf(), or NULL on failure. | |
| 462 | +*/ | |
| 463 | +char *win32_file_id( | |
| 464 | + const char *zFileName | |
| 465 | +){ | |
| 466 | + static FARPROC fnGetFileInformationByHandleEx; | |
| 467 | + static int loaded_fnGetFileInformationByHandleEx; | |
| 468 | + wchar_t *wzFileName = fossil_utf8_to_path(zFileName,0); | |
| 469 | + HANDLE hFile; | |
| 470 | + char *zFileId = 0; | |
| 471 | + hFile = CreateFileW( | |
| 472 | + wzFileName, | |
| 473 | + 0, | |
| 474 | + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | |
| 475 | + NULL, | |
| 476 | + OPEN_EXISTING, | |
| 477 | + FILE_FLAG_BACKUP_SEMANTICS, | |
| 478 | + NULL); | |
| 479 | + if( hFile!=INVALID_HANDLE_VALUE ){ | |
| 480 | + BY_HANDLE_FILE_INFORMATION fi; | |
| 481 | + struct { /* FILE_ID_INFO from <winbase.h> */ | |
| 482 | + u64 VolumeSerialNumber; | |
| 483 | + unsigned char FileId[16]; | |
| 484 | + } fi2; | |
| 485 | + if( !loaded_fnGetFileInformationByHandleEx ){ | |
| 486 | + fnGetFileInformationByHandleEx = GetProcAddress( | |
| 487 | + GetModuleHandleA("kernel32"),"GetFileInformationByHandleEx"); | |
| 488 | + loaded_fnGetFileInformationByHandleEx = 1; | |
| 489 | + } | |
| 490 | + if( fnGetFileInformationByHandleEx ){ | |
| 491 | + if( fnGetFileInformationByHandleEx( | |
| 492 | + hFile,/*FileIdInfo*/0x12,&fi2,sizeof(fi2)) ){ | |
| 493 | + zFileId = mprintf( | |
| 494 | + "%016llx/" | |
| 495 | + "%02x%02x%02x%02x%02x%02x%02x%02x" | |
| 496 | + "%02x%02x%02x%02x%02x%02x%02x%02x", | |
| 497 | + fi2.VolumeSerialNumber, | |
| 498 | + fi2.FileId[15], fi2.FileId[14], | |
| 499 | + fi2.FileId[13], fi2.FileId[12], | |
| 500 | + fi2.FileId[11], fi2.FileId[10], | |
| 501 | + fi2.FileId[9], fi2.FileId[8], | |
| 502 | + fi2.FileId[7], fi2.FileId[6], | |
| 503 | + fi2.FileId[5], fi2.FileId[4], | |
| 504 | + fi2.FileId[3], fi2.FileId[2], | |
| 505 | + fi2.FileId[1], fi2.FileId[0]); | |
| 506 | + } | |
| 507 | + } | |
| 508 | + if( zFileId==0 ){ | |
| 509 | + if( GetFileInformationByHandle(hFile,&fi) ){ | |
| 510 | + ULARGE_INTEGER FileId = { | |
| 511 | + /*.LowPart = */ fi.nFileIndexLow, | |
| 512 | + /*.HighPart = */ fi.nFileIndexHigh | |
| 513 | + }; | |
| 514 | + zFileId = mprintf( | |
| 515 | + "%08x/%016llx", | |
| 516 | + fi.dwVolumeSerialNumber,(u64)FileId.QuadPart); | |
| 517 | + } | |
| 518 | + } | |
| 519 | + CloseHandle(hFile); | |
| 520 | + } | |
| 521 | + fossil_path_free(wzFileName); | |
| 522 | + return zFileId; | |
| 523 | +} | |
| 456 | 524 | #endif /* _WIN32 -- This code is for win32 only */ |
| 457 | 525 |
| --- src/winfile.c | |
| +++ src/winfile.c | |
| @@ -451,6 +451,74 @@ | |
| 451 | i = j; |
| 452 | } |
| 453 | fossil_free(zBuf); |
| 454 | return zRes; |
| 455 | } |
| 456 | #endif /* _WIN32 -- This code is for win32 only */ |
| 457 |
| --- src/winfile.c | |
| +++ src/winfile.c | |
| @@ -451,6 +451,74 @@ | |
| 451 | i = j; |
| 452 | } |
| 453 | fossil_free(zBuf); |
| 454 | return zRes; |
| 455 | } |
| 456 | |
| 457 | /* Return the unique identifier (UID) for a file, made up of the file identifier |
| 458 | ** (equal to "inode" for Unix-style file systems) plus the volume serial number. |
| 459 | ** Call the GetFileInformationByHandleEx() function on Windows Vista, and resort |
| 460 | ** to the GetFileInformationByHandle() function on Windows XP. The result string |
| 461 | ** is allocated by mprintf(), or NULL on failure. |
| 462 | */ |
| 463 | char *win32_file_id( |
| 464 | const char *zFileName |
| 465 | ){ |
| 466 | static FARPROC fnGetFileInformationByHandleEx; |
| 467 | static int loaded_fnGetFileInformationByHandleEx; |
| 468 | wchar_t *wzFileName = fossil_utf8_to_path(zFileName,0); |
| 469 | HANDLE hFile; |
| 470 | char *zFileId = 0; |
| 471 | hFile = CreateFileW( |
| 472 | wzFileName, |
| 473 | 0, |
| 474 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| 475 | NULL, |
| 476 | OPEN_EXISTING, |
| 477 | FILE_FLAG_BACKUP_SEMANTICS, |
| 478 | NULL); |
| 479 | if( hFile!=INVALID_HANDLE_VALUE ){ |
| 480 | BY_HANDLE_FILE_INFORMATION fi; |
| 481 | struct { /* FILE_ID_INFO from <winbase.h> */ |
| 482 | u64 VolumeSerialNumber; |
| 483 | unsigned char FileId[16]; |
| 484 | } fi2; |
| 485 | if( !loaded_fnGetFileInformationByHandleEx ){ |
| 486 | fnGetFileInformationByHandleEx = GetProcAddress( |
| 487 | GetModuleHandleA("kernel32"),"GetFileInformationByHandleEx"); |
| 488 | loaded_fnGetFileInformationByHandleEx = 1; |
| 489 | } |
| 490 | if( fnGetFileInformationByHandleEx ){ |
| 491 | if( fnGetFileInformationByHandleEx( |
| 492 | hFile,/*FileIdInfo*/0x12,&fi2,sizeof(fi2)) ){ |
| 493 | zFileId = mprintf( |
| 494 | "%016llx/" |
| 495 | "%02x%02x%02x%02x%02x%02x%02x%02x" |
| 496 | "%02x%02x%02x%02x%02x%02x%02x%02x", |
| 497 | fi2.VolumeSerialNumber, |
| 498 | fi2.FileId[15], fi2.FileId[14], |
| 499 | fi2.FileId[13], fi2.FileId[12], |
| 500 | fi2.FileId[11], fi2.FileId[10], |
| 501 | fi2.FileId[9], fi2.FileId[8], |
| 502 | fi2.FileId[7], fi2.FileId[6], |
| 503 | fi2.FileId[5], fi2.FileId[4], |
| 504 | fi2.FileId[3], fi2.FileId[2], |
| 505 | fi2.FileId[1], fi2.FileId[0]); |
| 506 | } |
| 507 | } |
| 508 | if( zFileId==0 ){ |
| 509 | if( GetFileInformationByHandle(hFile,&fi) ){ |
| 510 | ULARGE_INTEGER FileId = { |
| 511 | /*.LowPart = */ fi.nFileIndexLow, |
| 512 | /*.HighPart = */ fi.nFileIndexHigh |
| 513 | }; |
| 514 | zFileId = mprintf( |
| 515 | "%08x/%016llx", |
| 516 | fi.dwVolumeSerialNumber,(u64)FileId.QuadPart); |
| 517 | } |
| 518 | } |
| 519 | CloseHandle(hFile); |
| 520 | } |
| 521 | fossil_path_free(wzFileName); |
| 522 | return zFileId; |
| 523 | } |
| 524 | #endif /* _WIN32 -- This code is for win32 only */ |
| 525 |