> 백엔드 개발 > C++ > FSCTL_ENUM_USN_DATA 함수를 사용하여 NTFS 볼륨의 파일 변경 사항을 효율적으로 감지하려면 어떻게 해야 합니까?

FSCTL_ENUM_USN_DATA 함수를 사용하여 NTFS 볼륨의 파일 변경 사항을 효율적으로 감지하려면 어떻게 해야 합니까?

DDD
풀어 주다: 2024-10-29 08:14:30
원래의
617명이 탐색했습니다.

How can I efficiently detect file changes on an NTFS volume using the FSCTL_ENUM_USN_DATA function?

볼륨 변경 감지: 자세한 솔루션

NTFS 볼륨에서 파일 삭제, 수정 및 생성을 효과적으로 감지하려면 다음을 수행하세요. FSCTL_ENUM_USN_DATA 함수를 활용하세요. 이 접근 방식은 여러 가지 장점을 제공합니다.

  • 빠른 열거: 초당 6000개 이상의 레코드 성능으로 기존 파일만 검색하여 효율적으로 볼륨을 검색합니다.
  • 상세 정보: 파일 플래그 및 USN을 포함한 포괄적인 데이터를 제공하여 정확한 변경 감지 방법을 가능하게 합니다.
  • 계층적 파일 데이터: 상위 ID를 파일 ID와 일치시켜, 감지된 각 파일의 전체 파일 경로를 재구성할 수 있습니다.

구현 단계:

  1. 파일 열거: FSCTL_ENUM_USN_DATA 사용 모든 기존 파일에 대한 기록을 검색합니다.
  2. 변경 사항 확인: 파일 플래그와 USN을 분석하여 어떤 파일이 수정, 생성 또는 삭제되었는지 확인합니다.
  3. 파일 경로 재구성: 상위 ID를 파일 ID와 일치시켜 영향을 받는 파일의 전체 경로를 얻습니다.

이 접근 방식을 보여주는 예제 C 프로그램이 아래에 제공되어 "test"라는 파일을 검색합니다. .txt"를 입력하고 변경 사항 및 상위 디렉터리에 대한 정보를 표시합니다.

<code class="c++">#include <Windows.h>
#include <stdio.h>

#define BUFFER_SIZE (1024 * 1024)

int main() {
  HANDLE drive = CreateFileW(L"\\?\c:", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_NO_BUFFERING, NULL);

  MFT_ENUM_DATA mft_enum_data;
  USN maxusn;
  USN_RECORD *record;

  // Query USN journal for information
  if (DeviceIoControl(drive, FSCTL_QUERY_USN_JOURNAL, NULL, 0, &maxusn, sizeof(USN), NULL, NULL)) {
    mft_enum_data.StartFileReferenceNumber = 0;
    mft_enum_data.LowUsn = 0;
    mft_enum_data.HighUsn = maxusn;
    
    DWORDLONG nextid, filecount = 0;

    for (;;) {
      void *buffer = VirtualAlloc(NULL, BUFFER_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

      if (DeviceIoControl(drive, FSCTL_ENUM_USN_DATA, &mft_enum_data, sizeof(mft_enum_data), buffer, BUFFER_SIZE, NULL, NULL)) {
        nextid = *((DWORDLONG *)buffer);

        record = (USN_RECORD *)((USN *)buffer + 1);
        while (record < (USN_RECORD *)(((BYTE *)buffer) + BUFFER_SIZE)) {
          filecount++;
          WCHAR *filename = (WCHAR *)(((BYTE *)record) + record->FileNameOffset);
          if (wcsncmp(filename, L"test.txt", 8) == 0) {
            printf("=================================================================\n");
            printf("RecordLength: %u\n", record->RecordLength);
            printf("MajorVersion: %u\n", (DWORD)record->MajorVersion);
            printf("MinorVersion: %u\n", (DWORD)record->MinorVersion);
            printf("FileReferenceNumber: %lu\n", record->FileReferenceNumber);
            printf("ParentFRN: %lu\n", record->ParentFileReferenceNumber);
            printf("USN: %lu\n", record->Usn);
            printf("Timestamp: %lu\n", record->TimeStamp);
            printf("Reason: %u\n", record->Reason);
            printf("SourceInfo: %u\n", record->SourceInfo);
            printf("SecurityId: %u\n", record->SecurityId);
            printf("FileAttributes: %x\n", record->FileAttributes);
            printf("FileNameLength: %u\n", (DWORD)record->FileNameLength);
            printf("FileName: %.*ls\n", record->FileNameLength, filename);
            
            // Reconstruct file path by matching parent file reference numbers
            DWORD bytecount;
            if (DeviceIoControl(drive, FSCTL_ENUM_USN_DATA, &mft_enum_data, sizeof(mft_enum_data), buffer, BUFFER_SIZE, &bytecount, NULL)) {
              USN_RECORD *parent_record = (USN_RECORD *)((USN *)buffer + 1);
              if (parent_record->FileReferenceNumber == record->ParentFileReferenceNumber) {
                printf("Parent File:\n");
                printf("=================================================================\n");
                printf("FileName: %.*ls\n", parent_record->FileNameLength, (WCHAR *)(((BYTE *)parent_record) + parent_record->FileNameOffset));
              }
            }
          }
          record = (USN_RECORD *)(((BYTE *)record) + record->RecordLength);
        }
        mft_enum_data.StartFileReferenceNumber = nextid;
      } else {
        printf("FSCTL_ENUM_USN_DATA failed\n");
        break;
      }
      if (nextid == 0) break;
    }
    printf("Total Files: %lu\n", filecount);
  } else {
    printf("FSCTL_QUERY_USN_JOURNAL failed\n");
  }

  if (drive != INVALID_HANDLE_VALUE)
    CloseHandle(drive);

  return 0;
}</code>
로그인 후 복사

위 내용은 FSCTL_ENUM_USN_DATA 함수를 사용하여 NTFS 볼륨의 파일 변경 사항을 효율적으로 감지하려면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿