Получаю цепочку кластеров файлика с NTFS раздела. Копирую на винт все замечательно.
Пытаюсь проделать тоже самое с файликом на fat32, часть файла является мусором

Опытным путем выяснил, что смещение верхушки в результирующем файле составляет 4096 байта.
В чем может быть проблема при работе с FAT32?
размер таблицы фат? и как это пофиксить. Ниже представлен код копирующий файл.
используем таги ccode & asm для выделения кусков кода. пример см ниже — модератор
//функция для получения цепочки кластеров по имени файла.
ULONGLONG *GetFileClusters(
PCHAR lpFileName,
ULONG ClusterSize,
ULONG *ClCount,
ULONG *FileSize
)
{
HANDLE hFile;
ULONG OutSize;
ULONG Bytes, Cls, CnCount, r;
ULONGLONG *Clusters = NULL;
BOOLEAN Result = FALSE;
LARGE_INTEGER PrevVCN, Lcn;
STARTING_VCN_INPUT_BUFFER InBuf;
PRETRIEVAL_POINTERS_BUFFER OutBuf;
hFile = CreateFile(lpFileName, FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
*FileSize = GetFileSize(hFile, NULL);
OutSize = sizeof(RETRIEVAL_POINTERS_BUFFER) + (*FileSize / ClusterSize) * sizeof(OutBuf->Extents);
OutBuf = (PRETRIEVAL_POINTERS_BUFFER)malloc( OutSize );
InBuf.StartingVcn.QuadPart = 0;
if (DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, &InBuf,
sizeof(InBuf), OutBuf, OutSize, &Bytes, NULL))
{
*ClCount = (*FileSize + ClusterSize - 1) / ClusterSize;
Clusters = (ULONGLONG*)malloc(*ClCount * sizeof(ULONGLONG));
PrevVCN = OutBuf->StartingVcn;
for (r = 0, Cls = 0; r < OutBuf->ExtentCount; r++)
{
Lcn = OutBuf->Extents[r].Lcn;
for (CnCount = (ULONG)(OutBuf->Extents[r].NextVcn.QuadPart - PrevVCN.QuadPart);
CnCount; CnCount--, Cls++, Lcn.QuadPart++) Clusters[Cls] = Lcn.QuadPart;
PrevVCN = OutBuf->Extents[r].NextVcn;
}
}
free(OutBuf);
CloseHandle(hFile);
}
return Clusters;
}
//непосредственно копиривание файла
hDrive = CreateFile(Name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDrive != INVALID_HANDLE_VALUE)
{
hFile = CreateFile(lpDstName, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
Buff_Read = malloc(ClusterSize);
for (r = 0; r < ClCount; r++, FileSize -= BlockSize)
{
Offset.QuadPart = (ClusterSize * Clusters[r]);
printf( "%d\n", Offset.QuadPart );
SetFilePointer(hDrive, Offset.LowPart, &Offset.HighPart, FILE_BEGIN);
ReadFile(hDrive, Buff_Read, ClusterSize, &Bytes, NULL);
BlockSize = FileSize < ClusterSize ? FileSize : ClusterSize;
WriteFile(hFile, Buff_Read, BlockSize, &Bytes, NULL);
}//end_ for_ r
free(Buff_Read);
//free(Buff);
CloseHandle(hFile);
}
CloseHandle(hDrive);
}
первоисточник:
http://www.wasm.ru/article.php?article=lockfileswork
Здравствуйте, realand, Вы писали:
R>Получаю цепочку кластеров файлика с NTFS раздела. Копирую на винт все замечательно.
R>Пытаюсь проделать тоже самое с файликом на fat32, часть файла является мусором
R>Опытным путем выяснил, что смещение верхушки в результирующем файле составляет 4096 байта.
R>В чем может быть проблема при работе с FAT32?
R>размер таблицы фат? и как это пофиксить. Ниже представлен код копирующий файл.
А можно вопрос, зачем это нада? Ну точнее как будит использоваться? Просто на вид вещь то полезная, но как оказывается не всегда. Разве что скопировать залоченные файлы реестра.
Здравствуйте, Denwer, Вы писали:
D>Здравствуйте, realand, Вы писали:
R>>Получаю цепочку кластеров файлика с NTFS раздела. Копирую на винт все замечательно.
R>>Пытаюсь проделать тоже самое с файликом на fat32, часть файла является мусором
R>>Опытным путем выяснил, что смещение верхушки в результирующем файле составляет 4096 байта.
R>>В чем может быть проблема при работе с FAT32?
R>>размер таблицы фат? и как это пофиксить. Ниже представлен код копирующий файл.
D>А можно вопрос, зачем это нада? Ну точнее как будит использоваться? Просто на вид вещь то полезная, но как оказывается не всегда. Разве что скопировать залоченные файлы реестра.
Ну с помощью этой бодяги можно читать любой залоченый файл.
На диске C Винда и фат32 время от времени бекаплю под досом системные файлы реестра. Все.
Оч помогает если система трапнулась или надо откатится. Спасало не раз. А ответ по существу?

слабо?
R>Получаю цепочку кластеров файлика с NTFS раздела. Копирую на винт все замечательно.
R>Пытаюсь проделать тоже самое с файликом на fat32, часть файла является мусором
R>Опытным путем выяснил, что смещение верхушки в результирующем файле составляет 4096 байта.
R>В чем может быть проблема при работе с FAT32?
R>размер таблицы фат? и как это пофиксить. Ниже представлен код копирующий файл.
R> Offset.QuadPart = (ClusterSize * Clusters[r]);
R> printf( "%d\n", Offset.QuadPart );
R> SetFilePointer(hDrive, Offset.LowPart, &Offset.HighPart, FILE_BEGIN);
R> ReadFile(hDrive, Buff_Read, ClusterSize, &Bytes, NULL);
Нумерация кластеров на FAT начинается не от начала тома.
Область данных начинается после области boot + области фат(ов) + (область корневой директории на FAT12/16)
4096 байт для такой области маловато (разве только для дискеты)
Чтобы это пофиксить необходимо к Offset добавить эту область.
Как вычислить эту область? Прочитайте спецификацию на FAT.
http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc
Здравствуйте, MShura, Вы писали:
Правила форума нарушены.
— оверквотинг
Правила можно найти в разделе FAQ данного форума и\или ресурса.
Нарушение правил может повлечь за собой санкции, описанные там же — модератор
MS>Нумерация кластеров на FAT начинается не от начала тома.
MS>Область данных начинается после области boot + области фат(ов) + (область корневой директории на FAT12/16)
MS>4096 байт для такой области маловато (разве только для дискеты)
MS>Чтобы это пофиксить необходимо к Offset добавить эту область.
MS>Как вычислить эту область? Прочитайте спецификацию на FAT.
MS>http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc
Спасибо. То что надо.
Сейчас занимаюсь реализацией.
Если у кого есть готовый работающий пример буду премного благодарен
MS>>Нумерация кластеров на FAT начинается не от начала тома.
MS>>Область данных начинается после области boot + области фат(ов) + (область корневой директории на FAT12/16)
R>Спасибо. То что надо.
R>Сейчас занимаюсь реализацией.
R>Если у кого есть готовый работающий пример буду премного благодарен
Примерно так:
typedef struct BIOS_PARAMETER_BLOCK {
USHORT BytesPerSector;
UCHAR SectorsPerCluster;
USHORT ReservedSectors;
UCHAR Fats;
USHORT RootEntries;
USHORT Sectors;
UCHAR Media;
USHORT SectorsPerFat;
USHORT SectorsPerTrack;
USHORT Heads;
ULONG32 HiddenSectors;
ULONG32 LargeSectors;
ULONG32 LargeSectorsPerFat;
union {
USHORT ExtendedFlags;
struct {
ULONG ActiveFat:4;
ULONG Reserved0:3;
ULONG MirrorDisabled:1;
ULONG Reserved1:8;
};
};
USHORT FsVersion;
ULONG32 RootDirFirstCluster;
USHORT FsInfoSector;
USHORT BackupBootSector;
} BIOS_PARAMETER_BLOCK, *PBIOS_PARAMETER_BLOCK;
//
// Define the boot sector
//
typedef struct _PACKED_BOOT_SECTOR {
UCHAR Jump[3]; // offset = 0x000 0
UCHAR Oem[8]; // offset = 0x003 3
PACKED_BIOS_PARAMETER_BLOCK PackedBpb; // offset = 0x00B 11
UCHAR PhysicalDriveNumber; // offset = 0x024 36
UCHAR CurrentHead; // offset = 0x025 37
UCHAR Signature; // offset = 0x026 38
UCHAR Id[4]; // offset = 0x027 39
UCHAR VolumeLabel[11]; // offset = 0x02B 43
UCHAR SystemId[8]; // offset = 0x036 54
} PACKED_BOOT_SECTOR;
// Не забудьте про упаковку
C_ASSERT( 0x0E == FIELD_OFFSET( PACKED_BOOT_SECTOR, PackedBpb.ReservedSectors ) );
C_ASSERT( 0x10 == FIELD_OFFSET( PACKED_BOOT_SECTOR, PackedBpb.Fats ) );
C_ASSERT( 0x24 == FIELD_OFFSET( PACKED_BOOT_SECTOR, PackedBpb.LargeSectorsPerFat) );
Если взять за основу приведенные структуры, то на x86 платформах на дисках с 512 байтным сектором начало данных будет вычисляться по такой формуле
union{
PACKED_BOOT_SECTOR boot;
UCHAR BootSector [512];
};
//
// Прочитать 512 байт со смещения 0 тома (не диска!) в область BootSector
//
...
ULONG ZeroLcnOffset = boot.PackedBpb.ReservedSectors;
if ( 0 == boot.PackedBpb.SectorsPerFat )
{
// FAT32
ZeroLcnOffset += boot.PackedBpb.Fats * boot.PackedBpb.LargeSectorsPerFat;
}
else
{
// FAT16/12
ZeroLcnOffset += boot.PackedBpb.Fats * (ULONG)boot.PackedBpb.SectorsPerFat;
ZeroLcnOffset += (boot.PackedBpb.RootEntries * 32 + 511 ) >> 9;
}
ZeroLcnOffset <<= 9;
В принципе приведенный код будет работать и на не x86 платформах.
Обратите внимание, что хотя в FAT нумерация кластеров LCN начинается с 2, FSCTL_GET_RETRIEVAL_POINTERS вертает 0 based.
P.S. Писал без проверок.