.TypeName = "NTFS-Dir",
.ReadDir = NTFS_ReadDir,
.FindDir = NTFS_FindDir,
- .Close = NULL
+ .Close = NTFS_Close
};
tVFS_NodeType gNTFS_FileType = {
.TypeName = "NTFS-File",
- .Close = NULL
+ .Read = NTFS_ReadFile,
+ .Close = NTFS_Close
};
tNTFS_Disk gNTFS_Disks;
if( bs.BytesPerSector == 0 || (bs.BytesPerSector & 511) )
return 0;
-
+ if( bs.SectorsPerCluster == 0 )
+ return 0;
+ if( bs.ClustersPerMFTRecord == 0 )
+ return 0;
+
Uint64 ncluster = bs.TotalSectorCount / bs.SectorsPerCluster;
if( bs.MFTStart >= ncluster || bs.MFTMirrorStart >= ncluster )
return 0;
#endif
disk->ClusterSize = bs.BytesPerSector * bs.SectorsPerCluster;
+ ASSERTR(disk->ClusterSize > 0, NULL);
disk->MFTBase = bs.MFTStart;
Log_Debug("NTFS", "Cluster Size = %i KiB", disk->ClusterSize/1024);
Log_Debug("NTFS", "MFT Base = %i", disk->MFTBase);
else {
disk->MFTRecSize = bs.ClustersPerMFTRecord * disk->ClusterSize;
}
+ ASSERTR(disk->MFTRecSize > 0, NULL);
//NTFS_DumpEntry(disk, 0); // $MFT
//NTFS_DumpEntry(disk, 3); // $VOLUME
- disk->InodeCache = Inode_GetHandle();
+ disk->InodeCache = Inode_GetHandle(NTFS_FreeNode);
disk->MFTDataAttr = NULL;
disk->MFTDataAttr = NTFS_GetAttrib(disk, 0, NTFS_FileAttrib_Data, "", 0);
free(Disk);
}
+void NTFS_Close(tVFS_Node *Node)
+{
+ tNTFS_Disk *Disk = Node->ImplPtr;
+ Inode_UncacheNode(Disk->InodeCache, Node->Inode);
+}
+
+void NTFS_FreeNode(tVFS_Node *Node)
+{
+ if( Node->Type == &gNTFS_DirType ) {
+ tNTFS_Directory *Dir = (void*)Node;
+ NTFS_FreeAttrib(Dir->I30Root);
+ NTFS_FreeAttrib(Dir->I30Allocation);
+ }
+ else {
+ tNTFS_File *File = (void*)Node;
+ NTFS_FreeAttrib(File->Data);
+ }
+}
+
int NTFS_int_ApplyUpdateSequence(void *Buffer, size_t BufLen, const Uint16 *Sequence, size_t NumEntries)
{
Uint16 cksum = Sequence[0];
tNTFS_FILE_Header *NTFS_GetMFT(tNTFS_Disk *Disk, Uint32 MFTEntry)
{
+ // TODO: Cache MFT allocation for short-term
+
+ //
tNTFS_FILE_Header *ret = malloc( Disk->MFTRecSize );
if(!ret) {
Log_Warning("FS_NTFS", "malloc() fail!");
if( attr->Type != Type )
continue;
if( Name ) {
- LOG("Name check = '%s'", Name);
+ if( attr->NameOffset + attr->NameLength*2 > attr->Size ) {
+ break;
+ }
const void *name16 = (char*)attr + attr->NameOffset;
+ LOG("Name check: '%s' == '%.*ls'",
+ Name, attr->NameLength, name16);
if( UTF16_CompareWithUTF8(attr->NameLength, name16, Name) != 0 )
continue ;
}
ASSERT(attr->NameOffset % 1 == 0);
Uint16 *name16 = (Uint16*)attr + attr->NameOffset/2;
size_t namelen = UTF16_ConvertToUTF8(0, NULL, attr->NameLength, name16);
- size_t edatalen = (attr->NonresidentFlag ? 0 : attr->Resident.AttribLen*4);
+ size_t edatalen = (attr->NonresidentFlag ? 0 : attr->Resident.AttribLen);
tNTFS_Attrib *ret = malloc( sizeof(tNTFS_Attrib) + namelen + 1 + edatalen );
if(!ret) {
- LEAVE('n');
- return NULL;
+ goto _error;
}
if( attr->NonresidentFlag )
ret->Name = (void*)(ret + 1);
{
ret->DataSize = edatalen;
memcpy(ret->ResidentData, (char*)attr + attr->Resident.AttribOfs, edatalen);
+ Debug_HexDump("GetAttrib Resident", ret->ResidentData, edatalen);
}
+ NTFS_ReleaseMFT(Disk, MFTEntry, hdr);
LEAVE('p', ret);
return ret;
}
+_error:
NTFS_ReleaseMFT(Disk, MFTEntry, hdr);
LEAVE('n');
return NULL;
}
+void NTFS_FreeAttrib(tNTFS_Attrib *Attrib)
+{
+ if( Attrib )
+ free(Attrib);
+}
+
size_t NTFS_ReadAttribData(tNTFS_Attrib *Attrib, Uint64 Offset, size_t Length, void *Buffer)
{
if( !Attrib )
tNTFS_FILE_Attrib *attr;
int i;
- tNTFS_FILE_Header *hdr = malloc( Disk->MFTRecSize );
+
+ tNTFS_FILE_Header *hdr = NTFS_GetMFT(Disk, Entry);
if(!hdr) {
Log_Warning("FS_NTFS", "malloc() fail!");
return ;
}
- VFS_ReadAt( Disk->FD,
- Disk->MFTBase * Disk->ClusterSize + Entry * Disk->MFTRecSize,
- Disk->MFTRecSize,
- hdr);
-
Log_Debug("FS_NTFS", "MFT Entry #%i", Entry);
Log_Debug("FS_NTFS", "- Magic = 0x%08x (%4C)", hdr->Magic, &hdr->Magic);
Log_Debug("FS_NTFS", "- UpdateSequenceOfs = 0x%x", hdr->UpdateSequenceOfs);
attr = (void*)( (tVAddr)attr + attr->Size );
}
- free(hdr);
+ NTFS_ReleaseMFT(Disk, Entry, hdr);
}