Usermode/libaxwin4 - Handle demarshal failure
[tpg/acess2.git] / KernelLand / Modules / Filesystems / NTFS / main.c
index 5e1c2ae..18caf46 100644 (file)
@@ -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;
@@ -122,6 +127,7 @@ tVFS_Node *NTFS_InitDevice(const char *Device, const char **Options)
 #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);
@@ -133,10 +139,11 @@ 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);
@@ -177,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;
@@ -195,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;
 }
 
@@ -284,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 ;
                }
@@ -297,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);
@@ -348,17 +408,26 @@ tNTFS_Attrib *NTFS_GetAttrib(tNTFS_Disk *Disk, Uint32 MFTEntry, int Type, const
                {
                        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 )
@@ -437,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);
@@ -508,5 +573,5 @@ void NTFS_DumpEntry(tNTFS_Disk *Disk, Uint32 Entry)
                attr = (void*)( (tVAddr)attr + attr->Size );
        }
        
-       free(hdr);
+       NTFS_ReleaseMFT(Disk, Entry, hdr);
 }

UCC git Repository :: git.ucc.asn.au