Modules/FAT - Fixed edge cases in read
authorJohn Hodge <[email protected]>
Sat, 12 Nov 2011 03:45:46 +0000 (11:45 +0800)
committerJohn Hodge <[email protected]>
Sat, 12 Nov 2011 03:45:46 +0000 (11:45 +0800)
Modules/Filesystems/FAT/fat.c

index f65cb42..af73322 100644 (file)
@@ -614,6 +614,7 @@ void FAT_int_ReadCluster(tFAT_VolInfo *Disk, Uint32 Cluster, int Length, void *B
 Uint64 FAT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
 {\r
         int    preSkip, count;\r
+       Uint64  final_bytes;\r
         int    i, cluster, pos;\r
        tFAT_VolInfo    *disk = Node->ImplPtr;\r
        char    tmpBuf[disk->BytesPerCluster];\r
@@ -623,7 +624,7 @@ Uint64 FAT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        \r
        // Sanity Check offset\r
        if(Offset > Node->Size) {\r
-               LOG("Reading past EOF (%i > %i)", Offset, Node->Size);\r
+               LOG("Seek past EOF (%i > %i)", Offset, Node->Size);\r
                LEAVE('i', 0);\r
                return 0;\r
        }\r
@@ -632,28 +633,18 @@ Uint64 FAT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        cluster = Node->Inode & 0xFFFFFFFF;\r
        \r
        // Clamp Size\r
-       if(Offset >= Node->Size || Offset + Length > Node->Size) {\r
+       if(Offset + Length > Node->Size) {\r
                LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli",\r
                        Offset, Length, Node->Size, Node->Size - Offset);\r
                Length = Node->Size - Offset;\r
        }\r
        \r
-       // Reading from within the first cluster only?\r
-       if((int)Offset + (int)Length < bpc)\r
-       {\r
-               LOG("First cluster only");\r
-               FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
-               memcpy( Buffer, (void*)( tmpBuf + Offset%bpc ), Length );\r
-               #if DEBUG\r
-               //Debug_HexDump("FAT_Read", Buffer, Length);\r
-               #endif\r
-               LEAVE('i', 1);\r
-               return Length;\r
-       }\r
-       \r
        // Skip previous clusters\r
        preSkip = Offset / bpc;\r
-       for(i = preSkip; i--; ) {\r
+       Offset %= bpc;\r
+       LOG("preSkip = %i, Offset = %i", preSkip, (int)Offset);\r
+       for(i = preSkip; i--; )\r
+       {\r
                cluster = FAT_int_GetFatValue(disk, cluster);\r
                if(cluster == -1) {\r
                        Log_Warning("FAT", "Offset is past end of cluster chain mark");\r
@@ -661,75 +652,69 @@ Uint64 FAT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                        return 0;\r
                }\r
        }\r
-       \r
-       // Get Count of Clusters to read\r
-       count = ((Offset%bpc + Length) / bpc) + 1;\r
-       \r
-       // Get buffer Position after 1st cluster\r
-       pos = bpc - Offset%bpc;\r
-       \r
-       // Read 1st Cluster (performs alignment for us)\r
-       if( pos == bpc && (int)Length >= bpc ) {\r
-               FAT_int_ReadCluster(disk, cluster, bpc, Buffer);\r
-       }\r
-       else {\r
+\r
+       // Reading from within one cluster\r
+       if((int)Offset + (int)Length <= bpc)\r
+       {\r
+               LOG("single cluster only");\r
                FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
-               memcpy(\r
-                       Buffer,\r
-                       (void*)( tmpBuf + (bpc-pos) ),\r
-                       (pos < (int)Length ? (Uint)pos : Length)\r
-                       );\r
-       }\r
-       \r
-       // Simple return\r
-       if( count == 1 ) {\r
-               #if DEBUG\r
-               //Debug_HexDump("FAT_Read", Buffer, Length);\r
-               #endif\r
-               LEAVE('i', 1);\r
+               memcpy( Buffer, (void*)( tmpBuf + Offset%bpc ), Length );\r
+               LEAVE('X', Length);\r
                return Length;\r
        }\r
        \r
-       #if DEBUG\r
-       LOG("pos = %i", pos);\r
-       LOG("Reading the rest of the clusters");\r
-       #endif\r
-       \r
-       // Read the rest of the cluster data\r
-       for( i = 1; i < count-1; i++ )\r
+       // Align read to a cluster\r
+       if( Offset > 0 )\r
        {\r
+               pos = bpc - Offset;\r
+               FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+               memcpy( Buffer, (void*)( tmpBuf + Offset ), pos );\r
+               LOG("pos = %i, Reading the rest of the clusters");\r
                // Get next cluster in the chain\r
                cluster = FAT_int_GetFatValue(disk, cluster);\r
                if(cluster == -1) {\r
-                       Log_Warning("FAT", "FAT_Read: Read past End of Cluster Chain");\r
-                       LEAVE('i', 0);\r
-                       return 0;\r
+                       Log_Warning("FAT", "Read past End of Cluster Chain (Align)");\r
+                       LEAVE('X', pos);\r
+                       return pos;\r
+               }\r
+       }\r
+       else\r
+               pos = 0;\r
+\r
+       // Get Count of Clusters to read\r
+//     count = DivMod64U(Length - pos, bpc, &final_bytes);\r
+       count = (Length - pos) / bpc;\r
+       final_bytes = (Length - pos) % bpc;\r
+       LOG("Offset = %i, Length = %i, count = %i, final_bytes = %i", (int)Offset, (int)Length, count, final_bytes);\r
+       \r
+       // Read the rest of the cluster data\r
+       for( ; count; count -- )\r
+       {\r
+               if(cluster == -1) {\r
+                       Log_Warning("FAT", "Read past End of Cluster Chain (Bulk)");\r
+                       LEAVE('X', pos);\r
+                       return pos;\r
                }\r
                // Read cluster\r
                FAT_int_ReadCluster(disk, cluster, bpc, (void*)(Buffer+pos));\r
                pos += bpc;\r
+               // Get next cluster in the chain\r
+               cluster = FAT_int_GetFatValue(disk, cluster);\r
        }\r
-       \r
-       // Get next cluster in the chain\r
-       cluster = FAT_int_GetFatValue(disk, cluster);\r
-       if(cluster == -1) {\r
-               Log_Warning("FAT", "FAT_Read: Read past End of Cluster Chain");\r
-               LEAVE('i', 0);\r
-               return 0;\r
-       }\r
-       \r
-       // Read final cluster\r
-       if( (int)Length - pos == bpc )\r
+\r
+       if( final_bytes > 0 )\r
        {\r
-               FAT_int_ReadCluster( disk, cluster, bpc, (void*)(Buffer+pos) );\r
-       }\r
-       else {\r
+               if(cluster == -1) {\r
+                       Log_Warning("FAT", "Read past End of Cluster Chain (Final)");\r
+                       LEAVE('X', pos);\r
+                       return pos;\r
+               }\r
+               // Read final cluster\r
                FAT_int_ReadCluster( disk, cluster, bpc, tmpBuf );\r
                memcpy( (void*)(Buffer+pos), tmpBuf, Length-pos );\r
        }\r
-       \r
+               \r
        #if DEBUG\r
-       LOG("Free tmpBuf(0x%x) and Return", tmpBuf);\r
        //Debug_HexDump("FAT_Read", Buffer, Length);\r
        #endif\r
        \r
@@ -1322,8 +1307,8 @@ tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name)
        tFAT_VolInfo    *disk = Node->ImplPtr;\r
        Uint32  cluster;\r
        \r
-       ENTER("pNode sname", Node, Name);\r
-       \r
+       ENTER("pNode sname", Node, Name);       \r
+\r
        // Fast Returns\r
        if(!Name || Name[0] == '\0') {\r
                LEAVE('n');\r

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