X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FFilesystems%2FNTFS%2Fmain.c;h=18caf46245a783d7530b6833f14a1f373d915174;hb=13078002b01ee4f63eb2001d2ef479a2a006ea32;hp=b1fafb95d39c56da3f01b4c5f7c6d0b34a43e801;hpb=7461f3e62b0783a3293828e4da74668f832f78b8;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Filesystems/NTFS/main.c b/KernelLand/Modules/Filesystems/NTFS/main.c index b1fafb95..18caf462 100644 --- a/KernelLand/Modules/Filesystems/NTFS/main.c +++ b/KernelLand/Modules/Filesystems/NTFS/main.c @@ -7,7 +7,7 @@ * * Reference: ntfsdoc.pdf */ -#define DEBUG 1 +#define DEBUG 0 #define VERBOSE 0 #include #include @@ -40,11 +40,12 @@ tVFS_NodeType gNTFS_DirType = { .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; @@ -69,7 +70,11 @@ int NTFS_Detect(int FD) 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; @@ -96,9 +101,9 @@ tVFS_Node *NTFS_InitDevice(const char *Device, const char **Options) return NULL; } - Log_Debug("FS_NTFS", "&bs = %p", &bs); VFS_ReadAt(disk->FD, 0, 512, &bs); - + +#if 0 Log_Debug("FS_NTFS", "Jump = %02x%02x%02x", bs.Jump[0], bs.Jump[1], @@ -119,10 +124,12 @@ tVFS_Node *NTFS_InitDevice(const char *Device, const char **Options) Log_Debug("FS_NTFS", "ClustersPerMFTRecord = %i", bs.ClustersPerMFTRecord); Log_Debug("FS_NTFS", "ClustersPerIndexRecord = %i", bs.ClustersPerIndexRecord); Log_Debug("FS_NTFS", "SerialNumber = 0x%llx", bs.SerialNumber); +#endif disk->ClusterSize = bs.BytesPerSector * bs.SectorsPerCluster; - Log_Debug("NTFS", "Cluster Size = %i KiB", disk->ClusterSize/1024); + 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); Log_Debug("NTFS", "TotalSectorCount = 0x%x", bs.TotalSectorCount); @@ -132,14 +139,15 @@ tVFS_Node *NTFS_InitDevice(const char *Device, const char **Options) 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); - NTFS_DumpEntry(disk, 5); // . + //NTFS_DumpEntry(disk, 5); // . disk->RootDir.I30Root = NTFS_GetAttrib(disk, 5, NTFS_FileAttrib_IndexRoot, "$I30", 0); disk->RootDir.I30Allocation = NTFS_GetAttrib(disk, 5, NTFS_FileAttrib_IndexAllocation, "$I30", 0); @@ -176,9 +184,55 @@ void NTFS_Unmount(tVFS_Node *Node) 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]; + LOG("cksum = %04x", cksum); + Sequence ++; + Uint16 *buf16 = Buffer; + for( int i = 0; i < NumEntries-1; i ++ ) + { + size_t ofs = (i+1)*512 - 2; + if( ofs + 2 > BufLen ) { + // Oops? + Log_Warning("NTFS", "%x > %x", ofs+2, BufLen); + } + Uint16 *cksum_word = &buf16[ofs/2]; + LOG("[%i]: %04x => %04x", i, Sequence[i], *cksum_word); + if( *cksum_word != cksum ) { + Log_Warning("NTFS", "Disk corruption detected"); + return 1; + } + *cksum_word = Sequence[i]; + } + return 0; +} + tNTFS_FILE_Header *NTFS_GetMFT(tNTFS_Disk *Disk, Uint32 MFTEntry) { - void *ret = malloc( Disk->MFTRecSize ); + // TODO: Cache MFT allocation for short-term + + // + tNTFS_FILE_Header *ret = malloc( Disk->MFTRecSize ); if(!ret) { Log_Warning("FS_NTFS", "malloc() fail!"); return NULL; @@ -194,7 +248,11 @@ tNTFS_FILE_Header *NTFS_GetMFT(tNTFS_Disk *Disk, Uint32 MFTEntry) else { NTFS_ReadAttribData(Disk->MFTDataAttr, MFTEntry * Disk->MFTRecSize, Disk->MFTRecSize, ret); } - + + NTFS_int_ApplyUpdateSequence(ret, Disk->MFTRecSize, + (void*)((char*)ret + ret->UpdateSequenceOfs), ret->UpdateSequenceSize + ); + return ret; } @@ -283,8 +341,12 @@ tNTFS_Attrib *NTFS_GetAttrib(tNTFS_Disk *Disk, Uint32 MFTEntry, int Type, const 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 ; } @@ -296,11 +358,10 @@ tNTFS_Attrib *NTFS_GetAttrib(tNTFS_Disk *Disk, Uint32 MFTEntry, int Type, const 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); @@ -345,20 +406,32 @@ tNTFS_Attrib *NTFS_GetAttrib(tNTFS_Disk *Disk, Uint32 MFTEntry, int Type, const } else { + 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 ) + return 0; if( Offset >= Attrib->DataSize ) return 0; if( Length > Attrib->DataSize ) @@ -433,17 +506,13 @@ void NTFS_DumpEntry(tNTFS_Disk *Disk, Uint32 Entry) 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); @@ -504,5 +573,5 @@ void NTFS_DumpEntry(tNTFS_Disk *Disk, Uint32 Entry) attr = (void*)( (tVAddr)attr + attr->Size ); } - free(hdr); + NTFS_ReleaseMFT(Disk, Entry, hdr); }