Fossil SCM

Implement the equivalent to the `inode' SQL function on Windows.

florian 2024-11-26 05:20 trunk
Commit 5233364196e06d89c0f2af49d7ccaa80020c4d5b6b4f14cf29b2bbf8b8e38920
2 files changed +9 -4 +68
+9 -4
--- src/file.c
+++ src/file.c
@@ -2996,12 +2996,13 @@
29962996
** a regular file, then the return string is of the form:
29972997
**
29982998
** DEV/INODE
29992999
**
30003000
** 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.
30033004
**
30043005
** If FILENAME does not exist, then the return is an empty string.
30053006
**
30063007
** The value of inode() can be used to eliminate files from a list
30073008
** that have duplicates because they have differing names due to links.
@@ -3024,12 +3025,16 @@
30243025
sqlite3_result_text(context, "", 0, SQLITE_STATIC);
30253026
return;
30263027
}
30273028
#if defined(_WIN32)
30283029
{
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
+ }
30313036
}
30323037
#else
30333038
{
30343039
struct stat buf;
30353040
int rc;
30363041
--- 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
--- src/winfile.c
+++ src/winfile.c
@@ -451,6 +451,74 @@
451451
i = j;
452452
}
453453
fossil_free(zBuf);
454454
return zRes;
455455
}
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
+}
456524
#endif /* _WIN32 -- This code is for win32 only */
457525
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button