Windowsでもinode的なところを調べたかったのですが調べてみると、
stackoverflow.com
Open both files with CreateFile, call GetFileInformationByHandle for both, and compare dwVolumeSerialNumber, nFileIndexLow, nFileIndexHigh. If all three are equal they both point to the same file:
とのことで、GetFileInformationByHandle
関数で取得できる、BY_HANDLE_FILE_INFORMATION
のStructureを調べれば良いようです。
GetFileInformationByHandle function | Microsoft Docs
_BY_HANDLE_FILE_INFORMATION | Microsoft Docs
ここで取得した dwVolumeSerialNumber
, nFileIndexLow
, nFileIndexHigh
を比較するということのようです。
処理の定義
すみません。PowerShellと題名に書いておきながらコードはC#です。
yomon.hatenablog.com
以下をPowerShellに貼り付けてEnterで定義ができます。
Add-Type -TypeDefinition @'
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace WindowsFileInfo
{
public static class Kernel32Api
{
[StructLayout(LayoutKind.Sequential)]
public struct BY_HANDLE_FILE_INFORMATION
{
public uint FileAttributes;
public FILETIME CreationTime;
public FILETIME LastAccessTime;
public FILETIME LastWriteTime;
public uint VolumeSerialNumber;
public uint FileSizeHigh;
public uint FileSizeLow;
public uint NumberOfLinks;
public uint FileIndexHigh;
public uint FileIndexLow;
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern SafeFileHandle CreateFile(
string lpFileName,
[MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
[MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
IntPtr lpSecurityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetFileInformationByHandle(SafeFileHandle handle, out BY_HANDLE_FILE_INFORMATION lpFileInformation);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(SafeHandle hObject);
public static BY_HANDLE_FILE_INFORMATION GetFileInfo(string filepath)
{
SafeFileHandle handle = CreateFile(filepath, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Archive, IntPtr.Zero);
BY_HANDLE_FILE_INFORMATION fileInfo = new BY_HANDLE_FILE_INFORMATION();
GetFileInformationByHandle(handle, out fileInfo);
CloseHandle(handle);
return fileInfo;
}
}
}
'@
確認
VolumeSerialNumber
と FileIndexHigh
と FileIndexLow
を比較して同一のファイルであることを判断します。
PS > echo "a" > a.txt
PS > $filepath = [System.IO.Directory]::GetCurrentDirectory() + "\a.txt"
PS > [WindowsFileInfo.Kernel32Api]::GetFileInfo($filepath)
FileAttributes : 32
CreationTime : System.Runtime.InteropServices.ComTypes.FILETIME
LastAccessTime : System.Runtime.InteropServices.ComTypes.FILETIME
LastWriteTime : System.Runtime.InteropServices.ComTypes.FILETIME
VolumeSerialNumber : 2421491731
FileSizeHigh : 0
FileSizeLow : 8
NumberOfLinks : 1
FileIndexHigh : 327680
FileIndexLow : 901684
PS > mv a.txt b.txt
PS > [WindowsFileInfo.Kernel32Api]::GetFileInfo($filepath)
FileAttributes : 32
CreationTime : System.Runtime.InteropServices.ComTypes.FILETIME
LastAccessTime : System.Runtime.InteropServices.ComTypes.FILETIME
LastWriteTime : System.Runtime.InteropServices.ComTypes.FILETIME
VolumeSerialNumber : 2421491731
FileSizeHigh : 0
FileSizeLow : 8
NumberOfLinks : 1
FileIndexHigh : 327680
FileIndexLow : 901684
fsutilでも似た情報を取得可能
同僚に教えてもらいましたが、似たような情報はfsutilでも取得可能です。
PS> fsutil usn readdata .\b.txt
メジャー バージョン : 0x3
マイナー バージョン : 0x0
ファイルの参照番号 : 0x0000000000000000008a00000006ff4f
親ファイルの参照番号 : 0x000000000000000000c3000000021499
USN : 0x000000026e1def60
タイム スタンプ : 0x0000000000000000 0:00:00 1601/01/01
理由 : 0x0
ソース情報 : 0x0
セキュリティ ID : 0x0
ファイル属性 : 0x20
ファイル名の長さ : 0xa
ファイル名オフセット : 0x4c
ファイル名 : b.txt