Fossil

Check-in [5233364196]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Implement the equivalent to the `inode' SQL function on Windows.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 5233364196e06d89c0f2af49d7ccaa80020c4d5b6b4f14cf29b2bbf8b8e38920
User & Date: florian 2024-11-26 05:20:00.000
Context
2024-12-04
06:32
Correct a mismatched TD HTML tag, as reported in [forum:5a7ca99ebe|forum post 5a7ca99ebe]. check-in: 11dafcf68d user: stephan tags: trunk
2024-11-28
15:07
Refactor the 3-way-merge logic to make it easier to extend and enhance. check-in: c4df699fd1 user: drh tags: merge-enhancements
2024-11-27
17:07
Wrap the list of attachments displayed on technotes/events, tickets and wiki pages in their own `section' HTML element with CSS class name 'attachlist'. Inspired by [forum:8da5a5d868 | forum thread 8da5a5d868]. Closed-Leaf check-in: b111adbe35 user: florian tags: attachlist-html-section
2024-11-26
05:20
Implement the equivalent to the `inode' SQL function on Windows. check-in: 5233364196 user: florian tags: trunk
05:17
Fix a crash if the test-file-environment command is called from outside a check-out (introduced with [106de276ee]). check-in: 38930fbabe user: florian tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/file.c.
2994
2995
2996
2997
2998
2999
3000
3001
3002

3003
3004
3005
3006
3007
3008
3009
**
** dev_inode(FILENAME) returns a string.  If FILENAME exists and is
** a regular file, then the return string is of the form:
**
**       DEV/INODE
**
** Where DEV and INODE are the device number and inode number for
** the file.  Or, on Windows, the return value is the canonical
** name of the file, because Windows does not have INODEs.

**
** If FILENAME does not exist, then the return is an empty string.
**
** The value of inode() can be used to eliminate files from a list
** that have duplicates because they have differing names due to links.
**
** Code that wants to use this SQL function needs to first register







|
|
>







2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
**
** dev_inode(FILENAME) returns a string.  If FILENAME exists and is
** a regular file, then the return string is of the form:
**
**       DEV/INODE
**
** Where DEV and INODE are the device number and inode number for
** the file.  On Windows, the volume serial number (DEV) and file
** identifier (INODE) are used to compute the value, see comments
** on the win32_file_id() function.
**
** If FILENAME does not exist, then the return is an empty string.
**
** The value of inode() can be used to eliminate files from a list
** that have duplicates because they have differing names due to links.
**
** Code that wants to use this SQL function needs to first register
3022
3023
3024
3025
3026
3027
3028
3029

3030



3031
3032
3033
3034
3035
3036
3037
  zFilename = (const char*)sqlite3_value_text(argv[0]);
  if( zFilename==0 || zFilename[0]==0 || file_access(zFilename,F_OK) ){
    sqlite3_result_text(context, "", 0, SQLITE_STATIC);
    return;
  }
#if defined(_WIN32)
  {
    const char *zCanonical = file_canonical_name_dup(zFilename);

    sqlite3_result_text(context, zCanonical, -1, fossil_free);



  }
#else
  {
    struct stat buf;
    int rc;
    memset(&buf, 0, sizeof(buf));
    rc = stat(zFilename, &buf);







|
>
|
>
>
>







3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
  zFilename = (const char*)sqlite3_value_text(argv[0]);
  if( zFilename==0 || zFilename[0]==0 || file_access(zFilename,F_OK) ){
    sqlite3_result_text(context, "", 0, SQLITE_STATIC);
    return;
  }
#if defined(_WIN32)
  {
    char *zFileId = win32_file_id(zFilename);
    if( zFileId ){
      sqlite3_result_text(context, zFileId, -1, fossil_free);
    }else{
      sqlite3_result_text(context, "", 0, SQLITE_STATIC);
    }
  }
#else
  {
    struct stat buf;
    int rc;
    memset(&buf, 0, sizeof(buf));
    rc = stat(zFilename, &buf);
Changes to src/winfile.c.
449
450
451
452
453
454
455




































































456
    }
    zBuf[j] = chSep;            /* Undo working buffer truncation. */
    i = j;
  }
  fossil_free(zBuf);
  return zRes;
}




































































#endif /* _WIN32  -- This code is for win32 only */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
    }
    zBuf[j] = chSep;            /* Undo working buffer truncation. */
    i = j;
  }
  fossil_free(zBuf);
  return zRes;
}

/* Return the unique identifier (UID) for a file, made up of the file identifier
** (equal to "inode" for Unix-style file systems) plus the volume serial number.
** Call the GetFileInformationByHandleEx() function on Windows Vista, and resort
** to the GetFileInformationByHandle() function on Windows XP. The result string
** is allocated by mprintf(), or NULL on failure.
*/
char *win32_file_id(
  const char *zFileName
){
  static FARPROC fnGetFileInformationByHandleEx;
  static int loaded_fnGetFileInformationByHandleEx;
  wchar_t *wzFileName = fossil_utf8_to_path(zFileName,0);
  HANDLE hFile;
  char *zFileId = 0;
  hFile = CreateFileW(
            wzFileName,
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_BACKUP_SEMANTICS,
            NULL);
  if( hFile!=INVALID_HANDLE_VALUE ){
    BY_HANDLE_FILE_INFORMATION fi;
    struct { /* FILE_ID_INFO from <winbase.h> */
      u64 VolumeSerialNumber;
      unsigned char FileId[16];
    } fi2;
    if( !loaded_fnGetFileInformationByHandleEx ){
      fnGetFileInformationByHandleEx = GetProcAddress(
        GetModuleHandleA("kernel32"),"GetFileInformationByHandleEx");
      loaded_fnGetFileInformationByHandleEx = 1;
    }
    if( fnGetFileInformationByHandleEx ){
      if( fnGetFileInformationByHandleEx(
            hFile,/*FileIdInfo*/0x12,&fi2,sizeof(fi2)) ){
        zFileId = mprintf(
                    "%016llx/"
                      "%02x%02x%02x%02x%02x%02x%02x%02x"
                      "%02x%02x%02x%02x%02x%02x%02x%02x",
                    fi2.VolumeSerialNumber,
                    fi2.FileId[15], fi2.FileId[14],
                    fi2.FileId[13], fi2.FileId[12],
                    fi2.FileId[11], fi2.FileId[10],
                    fi2.FileId[9],  fi2.FileId[8],
                    fi2.FileId[7],  fi2.FileId[6],
                    fi2.FileId[5],  fi2.FileId[4],
                    fi2.FileId[3],  fi2.FileId[2],
                    fi2.FileId[1],  fi2.FileId[0]);
      }
    }
    if( zFileId==0 ){
      if( GetFileInformationByHandle(hFile,&fi) ){
        ULARGE_INTEGER FileId = {
          /*.LowPart = */ fi.nFileIndexLow,
          /*.HighPart = */ fi.nFileIndexHigh
        };
        zFileId = mprintf(
                    "%08x/%016llx",
                    fi.dwVolumeSerialNumber,(u64)FileId.QuadPart);
      }
    }
    CloseHandle(hFile);
  }
  fossil_path_free(wzFileName);
  return zFileId;
}
#endif /* _WIN32  -- This code is for win32 only */