Rumah > pembangunan bahagian belakang > C++ > Bagaimanakah saya boleh mengesan perubahan fail dengan cekap pada volum NTFS menggunakan fungsi FSCTL_ENUM_USN_DATA?

Bagaimanakah saya boleh mengesan perubahan fail dengan cekap pada volum NTFS menggunakan fungsi FSCTL_ENUM_USN_DATA?

DDD
Lepaskan: 2024-10-29 08:14:30
asal
728 orang telah melayarinya

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

Mengesan Perubahan pada Kelantangan: Penyelesaian Terperinci

Untuk mengesan pemadaman, pengubahsuaian dan penciptaan fail secara berkesan pada volum NTFS, anda boleh gunakan fungsi FSCTL_ENUM_USN_DATA. Pendekatan ini menawarkan beberapa kelebihan:

  • Penghitungan Pantas: Ia mengimbas volum dengan cekap, mengambil hanya fail sedia ada dengan prestasi lebih 6000 rekod sesaat.
  • Maklumat Terperinci: Ia menyediakan data yang komprehensif, termasuk bendera fail dan USN, membolehkan kaedah pengesanan perubahan yang tepat.
  • Data Fail Hierarki: Dengan memadankan ID induk dengan ID fail, anda boleh membina semula laluan fail lengkap untuk setiap fail yang dikesan.

Langkah Pelaksanaan:

  1. Enumerate Files: Gunakan FSCTL_ENUM_USN_DATA untuk mendapatkan semula rekod bagi semua fail sedia ada.
  2. Kenalpasti Perubahan: Analisis bendera fail dan USN untuk menentukan fail mana yang telah diubah suai, dibuat atau dipadamkan.
  3. Bina semula Laluan Fail: Padankan ID induk dengan ID fail untuk mendapatkan laluan penuh fail yang terjejas.

Contoh program C yang menunjukkan pendekatan ini disediakan di bawah, mencari fail bernama "test .txt" dan memaparkan maklumat tentang perubahan dan direktori induk mereka:

<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>
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimanakah saya boleh mengesan perubahan fail dengan cekap pada volum NTFS menggunakan fungsi FSCTL_ENUM_USN_DATA?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan