reactos/drivers/filesystems/ntfs/mft.c
Amine Khaldi c424146e2c Create a branch for cmake bringup.
svn path=/branches/cmake-bringup/; revision=48236
2010-07-24 18:52:44 +00:00

321 lines
7.2 KiB
C

/*
* ReactOS kernel
* Copyright (C) 2002 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystem/ntfs/mft.c
* PURPOSE: NTFS filesystem driver
* PROGRAMMER: Eric Kohl
* Updated by Valentin Verkhovsky 2003/09/12
*/
/* INCLUDES *****************************************************************/
#include "ntfs.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS *****************************************************************/
/* FUNCTIONS ****************************************************************/
NTSTATUS
NtfsOpenMft (PDEVICE_EXTENSION Vcb)
{
// PVOID Bitmap;
PFILE_RECORD_HEADER MftRecord;
PFILE_RECORD_HEADER FileRecord;
// PATTRIBUTE Attribute;
// PATTRIBUTE AttrData;
// PRESIDENT_ATTRIBUTE ResAttr;
NTSTATUS Status;
ULONG BytesPerFileRecord;
ULONG n;
ULONG i;
DPRINT1("NtfsOpenMft() called\n");
BytesPerFileRecord = Vcb->NtfsInfo.BytesPerFileRecord;
MftRecord = ExAllocatePoolWithTag(NonPagedPool,
BytesPerFileRecord, TAG_NTFS);
if (MftRecord == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = NtfsReadSectors(Vcb->StorageDevice,
Vcb->NtfsInfo.MftStart.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
BytesPerFileRecord / Vcb->NtfsInfo.BytesPerSector,
Vcb->NtfsInfo.BytesPerSector,
(PVOID)MftRecord,
FALSE);
if (!NT_SUCCESS(Status))
{
ExFreePool(MftRecord);
return Status;
}
FixupUpdateSequenceArray(MftRecord);
// Attribute = FindAttribute(MftRecord, AttributeBitmap, 0);
/* Get number of file records*/
n = AttributeDataLength (FindAttribute (MftRecord, AttributeData, 0))
/ BytesPerFileRecord;
FileRecord = ExAllocatePoolWithTag(NonPagedPool, BytesPerFileRecord, TAG_NTFS);
if (FileRecord == NULL)
{
ExFreePool(MftRecord);
return(STATUS_INSUFFICIENT_RESOURCES);
}
/* Enumerate MFT Records */
DPRINT("Enumerate MFT records\n");
for ( i=0; i < n; i++)
{
ReadFileRecord(Vcb, i, FileRecord, MftRecord);
if (FileRecord->Ntfs.Type == NRH_FILE_TYPE && (FileRecord->Flags & FRH_IN_USE))
{
DPRINT("\nFile %lu\n\n", i);
/* Enumerate attributtes */
NtfsDumpFileAttributes (FileRecord);
DbgPrint("\n\n");
}
}
ExFreePool(FileRecord);
ExFreePool(MftRecord);
return Status;
}
PATTRIBUTE
FindAttribute (PFILE_RECORD_HEADER FileRecord,
ATTRIBUTE_TYPE Type,
PWSTR name)
{
PATTRIBUTE Attribute;
Attribute = (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
while (Attribute < (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
Attribute->AttributeType != (ATTRIBUTE_TYPE)-1)
{
if (Attribute->AttributeType == Type)
{
return Attribute;
}
Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
}
return NULL;
}
ULONG
AttributeAllocatedLength (PATTRIBUTE Attribute)
{
if (Attribute->Nonresident)
{
return ((PNONRESIDENT_ATTRIBUTE)Attribute)->AllocatedSize;
}
return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
}
ULONG
AttributeDataLength (PATTRIBUTE Attribute)
{
if (Attribute->Nonresident)
{
return ((PNONRESIDENT_ATTRIBUTE)Attribute)->DataSize;
}
return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
}
VOID
ReadAttribute (PATTRIBUTE attr,
PVOID buffer,
PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject)
{
PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
if (attr->Nonresident == FALSE)
{
memcpy (buffer,
(PVOID)((ULONG_PTR)attr + ((PRESIDENT_ATTRIBUTE)attr)->ValueOffset),
((PRESIDENT_ATTRIBUTE)attr)->ValueLength);
}
ReadExternalAttribute(Vcb, NresAttr, 0, (ULONG)(NresAttr->LastVcn) + 1,
buffer);
}
NTSTATUS
ReadFileRecord (PDEVICE_EXTENSION Vcb,
ULONG index,
PFILE_RECORD_HEADER file,
PFILE_RECORD_HEADER Mft)
{
PVOID p;
ULONG BytesPerFileRecord = Vcb->NtfsInfo.BytesPerFileRecord;
ULONG clusters = max(BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster, 1);
ULONGLONG vcn = index * BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster;
LONG m = (Vcb->NtfsInfo.BytesPerCluster / BytesPerFileRecord) - 1;
ULONG n = m > 0 ? (index & m) : 0;
p = ExAllocatePoolWithTag(NonPagedPool, clusters * Vcb->NtfsInfo.BytesPerCluster, TAG_NTFS);
ReadVCN (Vcb, Mft, AttributeData, vcn, clusters, p);
memcpy(file, (PVOID)((ULONG_PTR)p + n * BytesPerFileRecord), BytesPerFileRecord);
ExFreePool(p);
FixupUpdateSequenceArray(file);
return STATUS_SUCCESS;
}
VOID
ReadExternalAttribute (PDEVICE_EXTENSION Vcb,
PNONRESIDENT_ATTRIBUTE NresAttr,
ULONGLONG vcn,
ULONG count,
PVOID buffer)
{
ULONGLONG lcn;
ULONGLONG runcount;
ULONG readcount;
ULONG left;
ULONG n;
PUCHAR bytes = (PUCHAR)buffer;
for (left = count; left>0; left -=readcount)
{
FindRun(NresAttr, vcn, &lcn, &runcount);
// readcount = (ULONG)(__min(runcount, left));
readcount = (ULONG)min (runcount, left);
n = readcount * Vcb->NtfsInfo.BytesPerCluster;
if (lcn == 0)
memset(bytes, 0, n);
else
ReadLCN(Vcb, lcn, readcount, bytes);
vcn += readcount;
bytes += n;
}
}
VOID
ReadVCN (PDEVICE_EXTENSION Vcb,
PFILE_RECORD_HEADER file,
ATTRIBUTE_TYPE type,
ULONGLONG vcn,
ULONG count,
PVOID buffer)
{
PNONRESIDENT_ATTRIBUTE NresAttr;
PATTRIBUTE attr;
attr = FindAttribute(file, type, 0);
NresAttr = (PNONRESIDENT_ATTRIBUTE) attr;
if (NresAttr == 0 || (vcn < NresAttr->StartVcn ||vcn > NresAttr->LastVcn))
{
// PATTRIBUTE attrList = FindAttribute(file,AttributeAttributeList,0);
DbgPrint("Exeption \n");
// KeDebugCheck(0);
}
ReadExternalAttribute(Vcb, NresAttr, vcn, count, buffer);
}
#if 0
BOOL bitset(PUCHAR bitmap, ULONG i)
{
return (bitmap[i>>3] & (1 << (i & 7))) !=0;
}
#endif
VOID FixupUpdateSequenceArray(PFILE_RECORD_HEADER file)
{
PUSHORT usa = (PUSHORT)((ULONG_PTR)file + file->Ntfs.UsaOffset);
PUSHORT sector = (PUSHORT)file;
ULONG i;
for( i =1; i < file->Ntfs.UsaCount; i++)
{
sector[255] = usa[i];
sector += 256;
}
}
NTSTATUS
ReadLCN (PDEVICE_EXTENSION Vcb,
ULONGLONG lcn,
ULONG count,
PVOID buffer)
{
LARGE_INTEGER DiskSector;
DiskSector.QuadPart = lcn;
return NtfsReadSectors (Vcb->StorageDevice,
DiskSector.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
count * Vcb->NtfsInfo.SectorsPerCluster,
Vcb->NtfsInfo.BytesPerSector,
buffer,
FALSE);
}
/* EOF */