Страницы

Поиск по вопросам

среда, 22 января 2020 г.

C++ Определение физического расположения файла на диске

#cpp #winapi #файловая_система


Для начала, мне не даётся использование DeviceIoControl.
Говорит, что hFile неверный, хотя он не NULL. С какими атрибутами открывать?

ANDLE hFile = CreateFile(path,
    GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    0,
    NULL);

RETRIEVAL_POINTERS_BUFFER rpb;
STARTING_VCN_INPUT_BUFFER startingVcn;
DWORD dwBytesReturned;
OVERLAPPED overlapped;

DWORD dwFragments = 0, dwTotalClusters = 0;

    // ...

    DeviceIoControl(hFile, 
        FSCTL_GET_REPARSE_POINT,
        &startingVcn, sizeof startingVcn,
        &rpb, sizeof rpb,
        &dwBytesReturned, &overlapped);

     // ... while(dwError == ERROR_MORE_DATA);


Далее алгоритм будет следующий:
Вызвать GetLastError и по коду ошибки определить дальнейшие действия.


Если это первая итерация и ERROR_HANDLE_EOF, значит файл резидентный, если не первая,
то выход из цикла.
Если NO_ERROR, файл занимает 1 фрагмент кластеров (т.е. все по-порядку, а не в разброс
по диску).
Если ERROR_MORE_DATA, есть ещё на диске фрагменты этого файла.


Таким образом, будем иметь список всех фрагментов файла на диске ввиде списка пар
StartLCN-ClustersLength.

Так же, понятия не имею, что делать, если файл резидентный. Как вытащить его положение
на диске?

Работать всё это должно под FAT, FAT32 и NTFS (с поддержкой SPARSE, COMPRESSED и
ENCRYPTED файлов).

Нужно это положение для программы безопасного удаления данных, т.е. потом я полученные
кластеры затру.
    


Ответы

Ответ 1



HANDLE hFile = CreateFile(lpFilePath, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (hFile == INVALID_HANDLE_VALUE) { wcout << "Open file error: " << GetLastError() << endl; system("pause"); return -1; } PSTARTING_VCN_INPUT_BUFFER startingVcn = new STARTING_VCN_INPUT_BUFFER(); PRETRIEVAL_POINTERS_BUFFER prpb = new RETRIEVAL_POINTERS_BUFFER(); DWORD dwBytesReturned = 0; DWORD dwExtentNumber = 0, dwTotalClusters = 0; DWORD dwError; do { DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, startingVcn, sizeof *startingVcn, prpb, sizeof *prpb, &dwBytesReturned, NULL); dwError = GetLastError(); switch (dwError) { case ERROR_HANDLE_EOF: if (dwExtentNumber == 0) cout << "MFT Table..." << endl; else wcout << endl << "Total clusters: " << dwTotalClusters << endl << "Fragments: " << dwExtentNumber << endl; break; case NO_ERROR: wcout << "Fragment 0:" << endl << "\tStart LCN: " << prpb->Extents->Lcn.QuadPart << endl << "\tClusters: " << prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart << endl << endl; wcout << "Total clusters: " << prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart << endl << "Fragments: " << dwExtentNumber; break; case ERROR_MORE_DATA: wcout << "Fragment " << dwExtentNumber << ":" << endl << "\tStart LCN: " << prpb->Extents->Lcn.QuadPart << endl << "\tClusters: " << prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart << endl << endl; dwTotalClusters += prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart; startingVcn->StartingVcn.QuadPart = prpb->Extents->NextVcn.QuadPart; break; default: wcout << "DeviceIoControl error: " << dwError << endl; system("pause"); return -1; } dwExtentNumber++; } while (dwError == ERROR_MORE_DATA); CloseHandle(hFile); system("pause"); return 0;

Комментариев нет:

Отправить комментарий