yohhoyの日記

技術的メモをしていきたい日記

ファイルの同一性判定

POSIX環境またはWindows環境にて、2つのパス文字列が同一ファイルを指すか否かを判定する方法。(ファイルが存在していることが前提)

POSIX

バイスIDとinode番号*1を用いて同一性判定を行う。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int is_identical_file(const char* path1, const char* path2)
{
  struct stat fs1, fs2;

  if (stat(path1, &fs1) == 0 && stat(path2, &fs2) == 0) {
    if (fs1.st_dev == fs2.st_dev && fs1.st_ino == fs2.st_ino) {
      return 1;
    }
  }
  return 0;
}

Windows

ボリュームシリアル番号とファイルID*2を用いて同一性判定を行う。

#include <windows.h>

BOOL IsIdenticalFile(LPCTSTR szPath1, LPCTSTR szPath2)
{
  static const DWORD shareMode = FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE;
  HANDLE h1 = INVALID_HANDLE_VALUE, h2 = INVALID_HANDLE_VALUE;
  BY_HANDLE_FILE_INFORMATION fi1, fi2;
  BOOL result = FALSE;

  h1 = CreateFile(szPath1, 0, shareMode, NULL, OPEN_EXISTING, 0, NULL);
  h2 = CreateFile(szPath2, 0, shareMode, NULL, OPEN_EXISTING, 0, NULL);
  if (h1 != INVALID_HANDLE_VALUE && h2 != INVALID_HANDLE_VALUE
   && GetFileInformationByHandle(h1, &fi1) && GetFileInformationByHandle(h2, &fi2)) {
    result = (fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber)
          && (fi1.nFileIndexHigh == fi2.nFileIndexHigh)
          && (fi1.nFileIndexLow == fi2.nFileIndexLow);
  }
  if (h1 != INVALID_HANDLE_VALUE) CloseHandle(h1);
  if (h2 != INVALID_HANDLE_VALUE) CloseHandle(h2);
  return result;
}

関連URL