Changes to the module loader to handle specific errors from modules
[tpg/acess2.git] / Kernel / vfs / fs / fat.c
index c0c3fba..32bff8d 100644 (file)
@@ -1,31 +1,19 @@
 /*\r
- * Acess2\r
+ * Acess 2\r
  * FAT12/16/32 Driver Version (Incl LFN)\r
  */\r
-//INCLUDES\r
-#include <common.h>\r
-#include <modules.h>\r
-#include <vfs.h>\r
-#include "fs_fat.h"\r
-\r
-#define DEBUG  1\r
+#define DEBUG  0\r
 #define VERBOSE        1\r
 \r
-#if DEBUG\r
-# define DEBUGS(v...)  Log(v)\r
-#else\r
-# define DEBUGS(v...)\r
-# undef ENTER\r
-# undef LOG\r
-# undef LEAVE\r
-# define ENTER(...)\r
-# define LOG(...)\r
-# define LEAVE(...)\r
-#endif\r
-\r
 #define CACHE_FAT      1       //!< Caches the FAT in memory\r
 #define USE_LFN                1       //!< Enables the use of Long File Names\r
 \r
+#include <acess.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include "fs_fat.h"\r
+\r
+\r
 // === TYPES ===\r
 #if USE_LFN\r
 typedef struct s_lfncache {\r
@@ -38,7 +26,7 @@ typedef struct s_lfncache {
 \r
 // === PROTOTYPES ===\r
  int   FAT_Install(char **Arguments);\r
-tVFS_Node      *FAT_InitDevice(char *device, char *options);\r
+tVFS_Node      *FAT_InitDevice(char *device, char **options);\r
 void   FAT_Unmount(tVFS_Node *Node);\r
 Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
 Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
@@ -49,12 +37,9 @@ tVFS_Node    *FAT_FindDir(tVFS_Node *dirNode, char *file);
 void   FAT_CloseFile(tVFS_Node *node);\r
 \r
 // === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x5B /*v0.90*/, FAT32, FAT_Install, NULL);\r
+MODULE_DEFINE(0, 0x51 /*v0.80*/, VFAT, FAT_Install, NULL, NULL);\r
 tFAT_VolInfo   gFAT_Disks[8];\r
  int   giFAT_PartCount = 0;\r
-#if CACHE_FAT\r
-Uint32 *fat_cache[8];\r
-#endif\r
 #if USE_LFN\r
 t_lfncache     *fat_lfncache;\r
 #endif\r
@@ -70,14 +55,14 @@ tVFS_Driver gFAT_FSInfo = {
 int FAT_Install(char **Arguments)\r
 {\r
        VFS_AddDriver( &gFAT_FSInfo );\r
-       return 0;\r
+       return MODULE_ERR_OK;\r
 }\r
 \r
 /**\r
- * \fn tVFS_Node *FAT_InitDevice(char *Device, char *options)\r
+ * \fn tVFS_Node *FAT_InitDevice(char *Device, char **options)\r
  * \brief Reads the boot sector of a disk and prepares the structures for it\r
  */\r
-tVFS_Node *FAT_InitDevice(char *Device, char *options)\r
+tVFS_Node *FAT_InitDevice(char *Device, char **options)\r
 {\r
        fat_bootsect *bs;\r
         int    i;\r
@@ -131,6 +116,7 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options)
                case FAT12:     sFatType = "FAT12";     break;\r
                case FAT16:     sFatType = "FAT16";     break;\r
                case FAT32:     sFatType = "FAT32";     break;\r
+               default:        sFatType = "UNKNOWN";   break;\r
                }\r
                if(iSize <= 2*1024) {\r
                        sSize = "KiB";\r
@@ -172,8 +158,8 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options)
        #if CACHE_FAT\r
        {\r
        Uint32  Ofs;\r
-       fat_cache[ giFAT_PartCount ] = (Uint32*)malloc(sizeof(Uint32)*CountofClusters);\r
-       if(fat_cache[giFAT_PartCount] == NULL) {\r
+       diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*CountofClusters);\r
+       if(diskInfo->FATCache == NULL) {\r
                Warning("FAT_InitDisk - Heap Exhausted\n");\r
                return NULL;\r
        }\r
@@ -189,8 +175,8 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options)
                                Ofs += 3*512;\r
                        }\r
                        val = *((int*)(buf+j*3));\r
-                       fat_cache[giFAT_PartCount][i*2] = val & 0xFFF;\r
-                       fat_cache[giFAT_PartCount][i*2+1] = (val>>12) & 0xFFF;\r
+                       diskInfo->FATCache[i*2] = val & 0xFFF;\r
+                       diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
                }\r
        }\r
        if(diskInfo->type == FAT16) {\r
@@ -200,7 +186,7 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options)
                                VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
                                Ofs += 512;\r
                        }\r
-                       fat_cache[giFAT_PartCount][i] = buf[i&255];\r
+                       diskInfo->FATCache[i] = buf[i&255];\r
                }\r
        }\r
        if(diskInfo->type == FAT32) {\r
@@ -210,22 +196,19 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options)
                                VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
                                Ofs += 512;\r
                        }\r
-                       fat_cache[giFAT_PartCount][i] = buf[i&127];\r
+                       diskInfo->FATCache[i] = buf[i&127];\r
                }\r
        }\r
-       DEBUGS(" FAT_InitDisk: FAT Fully Cached\n");\r
+       LOG("FAT Fully Cached");\r
        }\r
        #endif /*CACHE_FAT*/\r
        \r
        //Initalise inode cache for FAT\r
-       gFAT_Disks[giFAT_PartCount].inodeHandle = Inode_GetHandle();\r
-       \r
-       #if DEBUG\r
-               Log(" FAT_InitDisk: Inode Cache handle is %i\n", gFAT_Disks[giFAT_PartCount].inodeHandle);\r
-       #endif\r
+       diskInfo->inodeHandle = Inode_GetHandle();\r
+       LOG("Inode Cache handle is %i", diskInfo->inodeHandle);\r
        \r
        // == VFS Interface\r
-       node = &gFAT_Disks[giFAT_PartCount].rootNode;\r
+       node = &diskInfo->rootNode;\r
        node->Inode = diskInfo->rootOffset;\r
        node->Size = bs->files_in_root; // Unknown - To be set on readdir\r
        node->ImplInt = giFAT_PartCount;\r
@@ -265,23 +248,32 @@ void FAT_Unmount(tVFS_Node *Node)
 }\r
 \r
 /**\r
- * \fn static Uint32 FAT_int_GetFatValue(int handle, Uint32 cluster)\r
+ * \fn static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
  * \brief Fetches a value from the FAT\r
  */\r
-static Uint32 FAT_int_GetFatValue(int handle, Uint32 cluster)\r
+static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
 {\r
-       Uint32  val;\r
-       ENTER("iHandle xCluster", handle, cluster);\r
+       Uint32  val = 0;\r
+       #if !CACHE_FAT\r
+       Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
+       #endif\r
+       ENTER("pDisk xCluster", Disk, cluster);\r
        #if CACHE_FAT\r
-       val = fat_cache[handle][cluster];\r
+       val = Disk->FATCache[cluster];\r
+       if(Disk->type == FAT12 && val == EOC_FAT12)     val = -1;\r
+       if(Disk->type == FAT16 && val == EOC_FAT16)     val = -1;\r
+       if(Disk->type == FAT32 && val == EOC_FAT32)     val = -1;\r
        #else\r
-       if(gFAT_Disks[handle].type == FAT12) {\r
-               VFS_ReadAt(gFAT_Disks[handle].fileHandle, 512+(cluster&~1)*3, 3, &val);\r
+       if(Disk->type == FAT12) {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
                val = (cluster&1 ? val&0xFFF : val>>12);\r
-       } else if(gFAT_Disks[handle].type == FAT16) {\r
-               VFS_ReadAt(gFAT_Disks[handle].fileHandle, 512+cluster*2, 2, &val);\r
+               if(val == EOC_FAT12)    val = -1;\r
+       } else if(Disk->type == FAT16) {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);\r
+               if(val == EOC_FAT16)    val = -1;\r
        } else {\r
-               VFS_ReadAt(gFAT_Disks[handle].fileHandle, 512+cluster*4, 4, &val);\r
+               VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
+               if(val == EOC_FAT32)    val = -1;\r
        }\r
        #endif /*CACHE_FAT*/\r
        LEAVE('x', val);\r
@@ -292,9 +284,8 @@ static Uint32 FAT_int_GetFatValue(int handle, Uint32 cluster)
  */\r
 static void FAT_int_ReadCluster(int Handle, Uint32 Cluster, int Length, void *Buffer)\r
 {\r
-       #if DEBUG\r
        ENTER("iHandle xCluster iLength pBuffer", Handle, Cluster, Length, Buffer);\r
-       #endif\r
+       //Log("Cluster = %i (0x%x)", Cluster, Cluster);\r
        VFS_ReadAt(\r
                gFAT_Disks[Handle].fileHandle,\r
                (gFAT_Disks[Handle].firstDataSect + (Cluster-2)*gFAT_Disks[Handle].bootsect.spc )\r
@@ -302,9 +293,7 @@ static void FAT_int_ReadCluster(int Handle, Uint32 Cluster, int Length, void *Bu
                Length,\r
                Buffer\r
                );\r
-       #if DEBUG\r
        LEAVE('-');\r
-       #endif\r
 }\r
 \r
 /**\r
@@ -318,7 +307,6 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)
         int    i, cluster, pos;\r
         int    bpc;\r
        void    *tmpBuf;\r
-       Uint    eocMarker;\r
        tFAT_VolInfo    *disk = &gFAT_Disks[node->ImplInt];\r
        \r
        ENTER("Xoffset Xlength pbuffer", offset, length, buffer);\r
@@ -331,16 +319,18 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)
        // Cluster is stored in Inode Field\r
        cluster = node->Inode;\r
        \r
-       // Get EOC Marker\r
-       if     (disk->type == FAT12)    eocMarker = EOC_FAT12;\r
-       else if(disk->type == FAT16)    eocMarker = EOC_FAT16;\r
-       else if(disk->type == FAT32)    eocMarker = EOC_FAT32;\r
-       else {\r
-               Log("ERROR: Unsupported FAT Variant.\n");\r
-               free(tmpBuf);\r
+       // Sanity Check offset\r
+       if(offset > node->Size) {\r
+               //LOG("Reading past EOF (%i > %i)", offset, node->Size);\r
                LEAVE('i', 0);\r
                return 0;\r
        }\r
+       // Clamp 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
        // Single Cluster including offset\r
        if(length + offset < bpc)\r
@@ -349,16 +339,18 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)
                memcpy( buffer, (void*)( tmpBuf + offset%bpc ), length );\r
                free(tmpBuf);\r
                LEAVE('i', 1);\r
-               return 1;\r
+               return length;\r
        }\r
        \r
        preSkip = offset / bpc;\r
        \r
        //Skip previous clusters\r
        for(i=preSkip;i--;)     {\r
-               cluster = FAT_int_GetFatValue(handle, cluster);\r
-               if(cluster == eocMarker) {\r
+               cluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(cluster == -1) {\r
                        Warning("FAT_Read - Offset is past end of cluster chain mark");\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
                }\r
        }\r
        \r
@@ -379,10 +371,10 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)
        if (count == 1) {\r
                free(tmpBuf);\r
                LEAVE('i', 1);\r
-               return 1;\r
+               return length;\r
        }\r
        \r
-       cluster = FAT_int_GetFatValue(handle, cluster);\r
+       cluster = FAT_int_GetFatValue(disk, cluster);\r
        \r
        #if DEBUG\r
        LOG("pos=%i\n", pos);\r
@@ -396,8 +388,8 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)
                FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
                memcpy((void*)(buffer+pos), tmpBuf, bpc);\r
                pos += bpc;\r
-               cluster = FAT_int_GetFatValue(handle, cluster);\r
-               if(cluster == eocMarker) {\r
+               cluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(cluster == -1) {\r
                        Warning("FAT_Read - Read past End of Cluster Chain");\r
                        free(tmpBuf);\r
                        LEAVE('i', 0);\r
@@ -489,11 +481,10 @@ tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFi
        \r
        ENTER("pParent pFT sLongFileName", parent, ft, LongFileName);\r
        \r
-       // Get Name\r
-       //node.Name = FAT_int_CreateName(parent, ft, LongFileName);\r
        // Set Other Data\r
        node.Inode = ft->cluster | (ft->clusterHi<<16);\r
        node.Size = ft->size;\r
+       LOG("ft->size = %i", ft->size);\r
        node.ImplInt = parent->ImplInt;\r
        node.UID = 0;   node.GID = 0;\r
        node.NumACLs = 1;\r
@@ -529,6 +520,7 @@ tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFi
                node.ReadDir = FAT_ReadDir;\r
                node.FindDir = FAT_FindDir;\r
                node.MkNod = FAT_Mknod;\r
+               node.Size = -1;\r
        } else {\r
                node.Read = FAT_Read;\r
                node.Write = FAT_Write;\r
@@ -619,25 +611,23 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos)
        \r
        // Get Byte Offset and skip\r
        offset = dirpos * sizeof(fat_filetable);\r
-       preSkip = (offset >> 9) / disk->bootsect.spc;   // >>9 == /512\r
+       preSkip = offset / (512 * disk->bootsect.spc);\r
+       LOG("disk->bootsect.spc = %i", disk->bootsect.spc);\r
+       LOG("dirNode->size = %i", dirNode->Size);\r
        cluster = dirNode->Inode;       // Cluster ID\r
        \r
        // Do Cluster Skip\r
        // - Pre FAT32 had a reserved area for the root.\r
-       if( !(disk->type != FAT32 && cluster == disk->rootOffset) )\r
+       if( disk->type == FAT32 || cluster != disk->rootOffset )\r
        {\r
                //Skip previous clusters\r
                for(a=preSkip;a--;)     {\r
-                       cluster = FAT_int_GetFatValue(dirNode->ImplInt, cluster);\r
+                       cluster = FAT_int_GetFatValue(disk, cluster);\r
+                       // Check for end of cluster chain\r
+                       if(cluster == -1) {     LEAVE('n');     return NULL;}\r
                }\r
        }\r
        \r
-       // Check for end of cluster chain\r
-       if((disk->type == FAT12 && cluster == EOC_FAT12)\r
-       || (disk->type == FAT16 && cluster == EOC_FAT16)\r
-       || (disk->type == FAT32 && cluster == EOC_FAT32))\r
-               return NULL;\r
-       \r
        // Bounds Checking (Used to spot heap overflows)\r
        if(cluster > disk->clusterCount + 2)\r
        {\r
@@ -647,7 +637,7 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos)
                return NULL;\r
        }\r
        \r
-       LOG("cluster=0x%x, dirpos=%i\n", cluster, dirpos);\r
+       LOG("cluster=0x%x, dirpos=%i", cluster, dirpos);\r
        \r
        // Compute Offsets\r
        // - Pre FAT32 cluster base (in sectors)\r
@@ -659,30 +649,28 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos)
                offset += (cluster - 2) * disk->bootsect.spc;\r
        }\r
        // Sector in cluster\r
-       if(disk->bootsect.spc == 1)\r
-               offset += (dirpos / 16);\r
-       else\r
+       if(disk->bootsect.spc != 1)\r
                offset += (dirpos / 16) % disk->bootsect.spc;\r
        // Offset in sector\r
-       a = dirpos & 0xF;\r
+       a = dirpos % 16;\r
 \r
-       LOG("offset=%i, a=%i\n", (Uint)offset, a);\r
+       LOG("offset=%i, a=%i", offset, a);\r
        \r
        // Read Sector\r
        VFS_ReadAt(disk->fileHandle, offset*512, 512, fileinfo);        // Read Dir Data\r
        \r
-       LOG("name[0] = 0x%x\n", (Uint8)fileinfo[a].name[0]);\r
+       LOG("name[0] = 0x%x", (Uint8)fileinfo[a].name[0]);\r
        //Check if this is the last entry\r
-       if(fileinfo[a].name[0] == '\0') {\r
+       if( fileinfo[a].name[0] == '\0' ) {\r
                dirNode->Size = dirpos;\r
-               LOG("End of list\n");\r
+               LOG("End of list");\r
                LEAVE('n');\r
                return NULL;    // break\r
        }\r
        \r
        // Check for empty entry\r
-       if((Uint8)fileinfo[a].name[0] == 0xE5) {\r
-               LOG("Empty Entry\n");\r
+       if( (Uint8)fileinfo[a].name[0] == 0xE5 ) {\r
+               LOG("Empty Entry");\r
                LEAVE('p', VFS_SKIP);\r
                return VFS_SKIP;        // Skip\r
        }\r
@@ -744,7 +732,7 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos)
        #endif\r
        \r
        LEAVE('s', ret);\r
-       return VFS_FREEPLZ(ret);\r
+       return ret;\r
 }\r
 \r
 /**\r
@@ -770,8 +758,10 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)
        ENTER("pnode sname", node, name);\r
        \r
        // Fast Returns\r
-       if(!name)       return NULL;\r
-       if(name[0] == '\0')     return NULL;\r
+       if(!name || name[0] == '\0') {\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
        \r
        #if USE_LFN\r
        lfn = FAT_int_GetLFN(node);\r
@@ -788,6 +778,7 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)
        {\r
                // Load sector\r
                if((i & 0xF) == 0) {\r
+                       //Log("FAT_FindDir: diskOffset = 0x%x", diskOffset);\r
                        VFS_ReadAt(disk->fileHandle, diskOffset, 512, fileinfo);\r
                        diskOffset += 512;\r
                }\r
@@ -827,7 +818,7 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)
                        // Get Real Filename\r
                        FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name);\r
                \r
-                       LOG("tmpName = '%s'\n", tmpName);\r
+                       LOG("tmpName = '%s'", tmpName);\r
                \r
                        //Only Long name is case sensitive, 8.3 is not\r
                        #if USE_LFN\r
@@ -861,7 +852,8 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)
                {\r
                        if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
                                continue;\r
-                       dirCluster = FAT_int_GetFatValue(node->ImplInt, dirCluster);\r
+                       dirCluster = FAT_int_GetFatValue(disk, dirCluster);\r
+                       if(dirCluster == -1)    break;\r
                        diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc)*512;\r
                }\r
        }\r

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