Various changes, most of them involving the FAT and Ext2 Drivers, adding write support
[tpg/acess2.git] / Kernel / vfs / fs / fat.c
diff --git a/Kernel/vfs/fs/fat.c b/Kernel/vfs/fs/fat.c
deleted file mode 100644 (file)
index 32bff8d..0000000
+++ /dev/null
@@ -1,909 +0,0 @@
-/*\r
- * Acess 2\r
- * FAT12/16/32 Driver Version (Incl LFN)\r
- */\r
-#define DEBUG  0\r
-#define VERBOSE        1\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
-       Uint    Inode, Impl;\r
-        int    id;\r
-       char    Name[256];\r
-       struct s_lfncache       *Next;\r
-}      t_lfncache;\r
-#endif\r
-\r
-// === PROTOTYPES ===\r
- int   FAT_Install(char **Arguments);\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
-char   *FAT_ReadDir(tVFS_Node *dirNode, int dirpos);\r
-tVFS_Node      *FAT_FindDir(tVFS_Node *dirNode, char *file);\r
- int   FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags);\r
- int   FAT_Relink(tVFS_Node *node, char *OldName, char *NewName);\r
-void   FAT_CloseFile(tVFS_Node *node);\r
-\r
-// === SEMI-GLOBALS ===\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 USE_LFN\r
-t_lfncache     *fat_lfncache;\r
-#endif\r
-tVFS_Driver    gFAT_FSInfo = {\r
-       "fat", 0, FAT_InitDevice, FAT_Unmount, NULL\r
-       };\r
-\r
-// === CODE ===\r
-/**\r
- * \fn int FAT_Install(char **Arguments)\r
- * \brief \r
- */\r
-int FAT_Install(char **Arguments)\r
-{\r
-       VFS_AddDriver( &gFAT_FSInfo );\r
-       return MODULE_ERR_OK;\r
-}\r
-\r
-/**\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
-{\r
-       fat_bootsect *bs;\r
-        int    i;\r
-       Uint32  FATSz, RootDirSectors, TotSec, CountofClusters;\r
-       tVFS_Node       *node = NULL;\r
-       tFAT_VolInfo    *diskInfo = &gFAT_Disks[giFAT_PartCount];\r
-       \r
-       //Temporary Pointer\r
-       bs = &diskInfo->bootsect;\r
-       \r
-       //Open device and read boot sector\r
-       diskInfo->fileHandle = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);\r
-       if(diskInfo->fileHandle == -1) {\r
-               Warning("FAT_InitDisk - Unable to open device '%s'", Device);\r
-               return NULL;\r
-       }\r
-       \r
-       VFS_ReadAt(diskInfo->fileHandle, 0, 512, bs);\r
-       \r
-       if(bs->bps == 0 || bs->spc == 0) {\r
-               Warning("FAT_InitDisk - Error in FAT Boot Sector\n");\r
-               return NULL;\r
-       }\r
-       \r
-       //FAT Type Determining\r
-       // From Microsoft FAT Specifcation\r
-       RootDirSectors = ((bs->files_in_root*32) + (bs->bps - 1)) / bs->bps;\r
-       \r
-       if(bs->fatSz16 != 0)            FATSz = bs->fatSz16;\r
-       else                                    FATSz = bs->spec.fat32.fatSz32;\r
-       \r
-       if(bs->totalSect16 != 0)                TotSec = bs->totalSect16;\r
-       else                                            TotSec = bs->totalSect32;\r
-       \r
-       CountofClusters = (TotSec - (bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors)) / bs->spc;\r
-       \r
-       if(CountofClusters < 4085)\r
-               diskInfo->type = FAT12;\r
-       else if(CountofClusters < 65525)\r
-               diskInfo->type = FAT16;\r
-       else\r
-               diskInfo->type = FAT32;\r
-       \r
-       #if VERBOSE\r
-       {\r
-               char    *sFatType, *sSize;\r
-               Uint    iSize = CountofClusters * bs->spc / 2;\r
-               \r
-               switch(diskInfo->type)\r
-               {\r
-               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
-               }\r
-               else if(iSize <= 2*1024*1024) {\r
-                       sSize = "MiB";\r
-                       iSize >>= 10;\r
-               }\r
-               else {\r
-                       sSize = "GiB";\r
-                       iSize >>= 20;\r
-               }\r
-               Log("[FAT ] '%s' %s, %i %s", Device, sFatType, iSize, sSize);\r
-       }\r
-       #endif\r
-       \r
-       //Get Name\r
-       if(diskInfo->type == FAT32) {\r
-               for(i=0;i<11;i++)\r
-                       diskInfo->name[i] = (bs->spec.fat32.label[i] == ' ' ? '\0' : bs->spec.fat32.label[i]);\r
-       }\r
-       else {\r
-               for(i=0;i<11;i++)\r
-                       diskInfo->name[i] = (bs->spec.fat16.label[i] == ' ' ? '\0' : bs->spec.fat16.label[i]);\r
-       }\r
-       diskInfo->name[11] = '\0';\r
-       \r
-       //Compute Root directory offset\r
-       if(diskInfo->type == FAT32)\r
-               diskInfo->rootOffset = bs->spec.fat32.rootClust;\r
-       else\r
-               diskInfo->rootOffset = (FATSz * bs->fatCount) / bs->spc;\r
-       \r
-       diskInfo->clusterCount = CountofClusters;\r
-       \r
-       diskInfo->firstDataSect = bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors;\r
-       \r
-       //Allow for Caching the FAT\r
-       #if CACHE_FAT\r
-       {\r
-       Uint32  Ofs;\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
-       Ofs = bs->resvSectCount*512;\r
-       if(diskInfo->type == FAT12) {\r
-               Uint32  val;\r
-                int    j;\r
-               char    buf[1536];\r
-               for(i=0;i<CountofClusters/2;i++) {\r
-                       j = i & 511;    //%512\r
-                       if( j == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 3*512, buf);\r
-                               Ofs += 3*512;\r
-                       }\r
-                       val = *((int*)(buf+j*3));\r
-                       diskInfo->FATCache[i*2] = val & 0xFFF;\r
-                       diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
-               }\r
-       }\r
-       if(diskInfo->type == FAT16) {\r
-               Uint16  buf[256];\r
-               for(i=0;i<CountofClusters;i++) {\r
-                       if( (i & 255) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
-                       }\r
-                       diskInfo->FATCache[i] = buf[i&255];\r
-               }\r
-       }\r
-       if(diskInfo->type == FAT32) {\r
-               Uint32  buf[128];\r
-               for(i=0;i<CountofClusters;i++) {\r
-                       if( (i & 127) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
-                       }\r
-                       diskInfo->FATCache[i] = buf[i&127];\r
-               }\r
-       }\r
-       LOG("FAT Fully Cached");\r
-       }\r
-       #endif /*CACHE_FAT*/\r
-       \r
-       //Initalise inode cache for FAT\r
-       diskInfo->inodeHandle = Inode_GetHandle();\r
-       LOG("Inode Cache handle is %i", diskInfo->inodeHandle);\r
-       \r
-       // == VFS Interface\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
-       \r
-       node->ReferenceCount = 1;\r
-       \r
-       node->UID = 0;  node->GID = 0;\r
-       node->NumACLs = 1;\r
-       node->ACLs = &gVFS_ACL_EveryoneRWX;\r
-       node->Flags = VFS_FFLAG_DIRECTORY;\r
-       node->CTime = node->MTime = node->ATime = now();\r
-       \r
-       node->Read = node->Write = NULL;\r
-       node->ReadDir = FAT_ReadDir;\r
-       node->FindDir = FAT_FindDir;\r
-       node->Relink = FAT_Relink;\r
-       node->MkNod = FAT_Mknod;\r
-       //node->Close = FAT_CloseDevice;\r
-       \r
-       giFAT_PartCount ++;\r
-       return node;\r
-}\r
-\r
-/**\r
- * \fn void FAT_Unmount(tVFS_Node *Node)\r
- * \brief Closes a mount and marks it as free\r
- */\r
-void FAT_Unmount(tVFS_Node *Node)\r
-{\r
-       // Close Disk Handle\r
-       VFS_Close( gFAT_Disks[Node->ImplInt].fileHandle );\r
-       // Clear Node Cache\r
-       Inode_ClearCache(gFAT_Disks[Node->ImplInt].inodeHandle);\r
-       // Mark as unused\r
-       gFAT_Disks[Node->ImplInt].fileHandle = -2;\r
-       return;\r
-}\r
-\r
-/**\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(tFAT_VolInfo *Disk, Uint32 cluster)\r
-{\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 = 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(Disk->type == FAT12) {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
-               val = (cluster&1 ? val&0xFFF : val>>12);\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(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
-               if(val == EOC_FAT32)    val = -1;\r
-       }\r
-       #endif /*CACHE_FAT*/\r
-       LEAVE('x', val);\r
-       return val;\r
-}\r
-\r
-/* Reads a cluster's data\r
- */\r
-static void FAT_int_ReadCluster(int Handle, Uint32 Cluster, int Length, void *Buffer)\r
-{\r
-       ENTER("iHandle xCluster iLength pBuffer", Handle, Cluster, Length, Buffer);\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
-                       * gFAT_Disks[Handle].bootsect.bps,\r
-               Length,\r
-               Buffer\r
-               );\r
-       LEAVE('-');\r
-}\r
-\r
-/**\r
- * \fn Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
- * \brief Reads data from a specified file\r
- */\r
-Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
-{\r
-        int    preSkip, count;\r
-        int    handle = node->ImplInt;\r
-        int    i, cluster, pos;\r
-        int    bpc;\r
-       void    *tmpBuf;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[node->ImplInt];\r
-       \r
-       ENTER("Xoffset Xlength pbuffer", offset, length, buffer);\r
-       \r
-       // Calculate and Allocate Bytes Per Cluster\r
-       bpc = disk->bootsect.spc * disk->bootsect.bps;\r
-       tmpBuf = (void*) malloc(bpc);\r
-       LOG("malloc'd %i bytes", bpc);\r
-       \r
-       // Cluster is stored in Inode Field\r
-       cluster = node->Inode;\r
-       \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
-       {\r
-               FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-               memcpy( buffer, (void*)( tmpBuf + offset%bpc ), length );\r
-               free(tmpBuf);\r
-               LEAVE('i', 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(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
-       // 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\r
-       FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-       memcpy(\r
-               buffer,\r
-               (void*)( tmpBuf + (bpc-pos) ),\r
-               (pos < length ? pos : length)\r
-               );\r
-       \r
-       if (count == 1) {\r
-               free(tmpBuf);\r
-               LEAVE('i', 1);\r
-               return length;\r
-       }\r
-       \r
-       cluster = FAT_int_GetFatValue(disk, cluster);\r
-       \r
-       #if DEBUG\r
-       LOG("pos=%i\n", pos);\r
-       LOG("Reading the rest of the clusters\n");\r
-       #endif\r
-       \r
-       \r
-       //Read the rest of the cluster data\r
-       for( i = 1; i < count-1; i++ )\r
-       {\r
-               FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-               memcpy((void*)(buffer+pos), tmpBuf, bpc);\r
-               pos += bpc;\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
-                       return 0;\r
-               }\r
-       }\r
-       \r
-       FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-       memcpy((void*)(buffer+pos), tmpBuf, length-pos);\r
-       \r
-       #if DEBUG\r
-       LOG("Free tmpBuf(0x%x) and Return\n", tmpBuf);\r
-       #endif\r
-       \r
-       free(tmpBuf);\r
-       LEAVE('X', length);\r
-       return length;\r
-}\r
-\r
-/**\r
- * \fn Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
- */\r
-Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn static void FAT_int_ProperFilename(char *dest, char *src)\r
- * \brief Converts a FAT directory entry name into a proper filename\r
- */\r
-static void FAT_int_ProperFilename(char *dest, char *src)\r
-{\r
-        int    a, b;\r
-       \r
-       for( a = 0; a < 8; a++) {\r
-               if(src[a] == ' ')       break;\r
-               dest[a] = src[a];\r
-       }\r
-       b = a;\r
-       a = 8;\r
-       if(src[8] != ' ')\r
-               dest[b++] = '.';\r
-       for( ; a < 11; a++, b++)        {\r
-               if(src[a] == ' ')       break;\r
-               dest[b] = src[a];\r
-       }\r
-       dest[b] = '\0';\r
-       #if DEBUG\r
-       //Log("FAT_int_ProperFilename: dest='%s'", dest);\r
-       #endif\r
-}\r
-\r
-/**\r
- * \fn char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
- * \brief Converts either a LFN or a 8.3 Name into a proper name\r
- */\r
-char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
-{\r
-       char    *ret;\r
-        int    len;\r
-       #if USE_LFN\r
-       if(LongFileName && LongFileName[0] != '\0')\r
-       {       \r
-               len = strlen(LongFileName);\r
-               ret = malloc(len+1);\r
-               strcpy(ret, LongFileName);\r
-       }\r
-       else\r
-       {\r
-       #endif\r
-               ret = (char*) malloc(13);\r
-               memset(ret, 13, '\0');\r
-               FAT_int_ProperFilename(ret, ft->name);\r
-       #if USE_LFN\r
-       }\r
-       #endif\r
-       return ret;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
- * \brief Creates a tVFS_Node structure for a given file entry\r
- */\r
-tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
-{\r
-       tVFS_Node       node = {0};\r
-       tVFS_Node       *ret;\r
-       \r
-       ENTER("pParent pFT sLongFileName", parent, ft, LongFileName);\r
-       \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
-       node.ACLs = &gVFS_ACL_EveryoneRWX;      // RWXRWXRWX\r
-       \r
-       node.Flags = 0;\r
-       if(ft->attrib & ATTR_DIRECTORY) node.Flags |= VFS_FFLAG_DIRECTORY;\r
-       if(ft->attrib & ATTR_READONLY)  node.Flags |= VFS_FFLAG_READONLY;\r
-       \r
-       node.ATime = timestamp(0,0,0,\r
-                       ((ft->adate&0x1F)-1),   //Days\r
-                       ((ft->adate&0x1E0)-1),          //Months\r
-                       1980+((ft->adate&0xFF00)>>8));  //Years\r
-       \r
-       node.CTime = ft->ctimems * 10;  //Miliseconds\r
-       node.CTime += timestamp(\r
-                       (ft->ctime&0x1F)<<1,    //Seconds\r
-                       ((ft->ctime&0x3F0)>>5), //Minutes\r
-                       ((ft->ctime&0xF800)>>11),       //Hours\r
-                       ((ft->cdate&0x1F)-1),           //Days\r
-                       ((ft->cdate&0x1E0)-1),          //Months\r
-                       1980+((ft->cdate&0xFF00)>>8));  //Years\r
-                       \r
-       node.MTime = timestamp(\r
-                       (ft->mtime&0x1F)<<1,    //Seconds\r
-                       ((ft->mtime&0x3F0)>>5), //Minuites\r
-                       ((ft->mtime&0xF800)>>11),       //Hours\r
-                       ((ft->mdate&0x1F)-1),           //Days\r
-                       ((ft->mdate&0x1E0)-1),          //Months\r
-                       1980+((ft->mdate&0xFF00)>>8));  //Years\r
-       \r
-       if(node.Flags & VFS_FFLAG_DIRECTORY) {\r
-               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
-       }\r
-       node.Close = FAT_CloseFile;\r
-       node.Relink = FAT_Relink;\r
-       \r
-       ret = Inode_CacheNode(gFAT_Disks[parent->ImplInt].inodeHandle, &node);\r
-       LEAVE('p', ret);\r
-       return ret;\r
-}\r
-\r
-#if USE_LFN\r
-/**\r
- \fn char *FAT_int_GetLFN(tVFS_Node *node)\r
- \brief Return pointer to LFN cache entry\r
- */\r
-char *FAT_int_GetLFN(tVFS_Node *node)\r
-{\r
-       t_lfncache      *tmp;\r
-       tmp = fat_lfncache;\r
-       while(tmp)\r
-       {\r
-               if(tmp->Inode == node->Inode && tmp->Impl == node->ImplInt)\r
-                       return tmp->Name;\r
-               tmp = tmp->Next;\r
-       }\r
-       tmp = malloc(sizeof(t_lfncache));\r
-       tmp->Inode = node->Inode;\r
-       tmp->Impl = node->ImplInt;\r
-       memset(tmp->Name, 0, 256);\r
-       \r
-       tmp->Next = fat_lfncache;\r
-       fat_lfncache = tmp;\r
-       \r
-       return tmp->Name;\r
-}\r
-\r
-/**\r
- \fn void FAT_int_DelLFN(tVFS_Node *node)\r
- \brief Delete a LFN cache entry\r
-*/\r
-void FAT_int_DelLFN(tVFS_Node *node)\r
-{\r
-       t_lfncache      *tmp;\r
-       \r
-       if(!fat_lfncache)       return;\r
-       \r
-       if(!fat_lfncache->Next)\r
-       {\r
-               tmp = fat_lfncache;\r
-               fat_lfncache = tmp->Next;\r
-               free(tmp);\r
-               return;\r
-       }\r
-       tmp = fat_lfncache;\r
-       while(tmp && tmp->Next)\r
-       {\r
-               if(tmp->Inode == node->Inode && tmp->Impl == node->ImplInt)\r
-               {\r
-                       free(tmp->Next);\r
-                       tmp->Next = tmp->Next->Next;\r
-                       return;\r
-               }\r
-               tmp = tmp->Next;\r
-       }\r
-}\r
-#endif\r
-\r
-/**\r
- \fn char *FAT_ReadDir(tVFS_Node *dirNode, int dirPos)\r
- \param dirNode        Node structure of directory\r
- \param dirPos Directory position\r
-**/\r
-char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos)\r
-{\r
-       fat_filetable   fileinfo[16];   //Sizeof=32, 16 per sector\r
-        int    a=0;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[dirNode->ImplInt&7];\r
-       Uint32  cluster, offset;\r
-        int    preSkip;\r
-       char    *ret;\r
-       #if USE_LFN\r
-       char    *lfn = NULL;\r
-       #endif\r
-       \r
-       ENTER("pDirNode iDirPos", dirNode, dirpos);\r
-       \r
-       // Get Byte Offset and skip\r
-       offset = dirpos * sizeof(fat_filetable);\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
-       {\r
-               //Skip previous clusters\r
-               for(a=preSkip;a--;)     {\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
-       // Bounds Checking (Used to spot heap overflows)\r
-       if(cluster > disk->clusterCount + 2)\r
-       {\r
-               Warning("FAT_ReadDir - Cluster ID is over cluster count (0x%x>0x%x)",\r
-                       cluster, disk->clusterCount+2);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       LOG("cluster=0x%x, dirpos=%i", cluster, dirpos);\r
-       \r
-       // Compute Offsets\r
-       // - Pre FAT32 cluster base (in sectors)\r
-       if( cluster == disk->rootOffset && disk->type != FAT32 )\r
-               offset = disk->bootsect.resvSectCount + cluster*disk->bootsect.spc;\r
-       else\r
-       {       // FAT32 cluster base (in sectors)\r
-               offset = disk->firstDataSect;\r
-               offset += (cluster - 2) * disk->bootsect.spc;\r
-       }\r
-       // Sector in cluster\r
-       if(disk->bootsect.spc != 1)\r
-               offset += (dirpos / 16) % disk->bootsect.spc;\r
-       // Offset in sector\r
-       a = dirpos % 16;\r
-\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", (Uint8)fileinfo[a].name[0]);\r
-       //Check if this is the last entry\r
-       if( fileinfo[a].name[0] == '\0' ) {\r
-               dirNode->Size = dirpos;\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");\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;        // Skip\r
-       }\r
-       \r
-       #if USE_LFN\r
-       // Get Long File Name Cache\r
-       lfn = FAT_int_GetLFN(dirNode);\r
-       if(fileinfo[a].attrib == ATTR_LFN)\r
-       {\r
-               fat_longfilename        *lfnInfo;\r
-                int    len;\r
-               \r
-               lfnInfo = (fat_longfilename *) &fileinfo[a];\r
-               if(lfnInfo->id & 0x40)  memset(lfn, 0, 256);\r
-               // Get the current length\r
-               len = strlen(lfn);\r
-               \r
-               // Sanity Check (FAT implementations should not allow >255 bytes)\r
-               if(len + 13 > 255)      return VFS_SKIP;\r
-               // Rebase all bytes\r
-               for(a=len+1;a--;)       lfn[a+13] = lfn[a];\r
-               \r
-               // Append new bytes\r
-               lfn[ 0] = lfnInfo->name1[0];    lfn[ 1] = lfnInfo->name1[1];\r
-               lfn[ 2] = lfnInfo->name1[2];    lfn[ 3] = lfnInfo->name1[3];\r
-               lfn[ 4] = lfnInfo->name1[4];    \r
-               lfn[ 5] = lfnInfo->name2[0];    lfn[ 6] = lfnInfo->name2[1];\r
-               lfn[ 7] = lfnInfo->name2[2];    lfn[ 8] = lfnInfo->name2[3];\r
-               lfn[ 9] = lfnInfo->name2[4];    lfn[10] = lfnInfo->name2[5];\r
-               lfn[11] = lfnInfo->name3[0];    lfn[12] = lfnInfo->name3[1];\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }\r
-       #endif\r
-       \r
-       //Check if it is a volume entry\r
-       if(fileinfo[a].attrib & 0x08) {\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }\r
-       // Ignore . and ..\r
-       if(fileinfo[a].name[0] == '.') {\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }       \r
-       \r
-       LOG("name='%c%c%c%c%c%c%c%c.%c%c%c'\n",\r
-               fileinfo[a].name[0], fileinfo[a].name[1], fileinfo[a].name[2], fileinfo[a].name[3],\r
-               fileinfo[a].name[4], fileinfo[a].name[5], fileinfo[a].name[6], fileinfo[a].name[7],\r
-               fileinfo[a].name[8], fileinfo[a].name[9], fileinfo[a].name[10] );\r
-       \r
-       #if USE_LFN\r
-       //node = FAT_int_CreateNode(dirNode, &fileinfo[a], lfn);\r
-       ret = FAT_int_CreateName(dirNode, &fileinfo[a], lfn);\r
-       lfn[0] = '\0';\r
-       #else\r
-       //node = FAT_int_CreateNode(dirNode, &fileinfo[a], NULL);\r
-       ret = FAT_int_CreateName(dirNode, &fileinfo[a], NULL);\r
-       #endif\r
-       \r
-       LEAVE('s', ret);\r
-       return ret;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
- * \brief Finds an entry in the current directory\r
- */\r
-tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
-{\r
-       fat_filetable   fileinfo[16];\r
-       char    tmpName[11];\r
-       #if USE_LFN\r
-       fat_longfilename        *lfnInfo;\r
-       char    *lfn = NULL;\r
-        int    lfnPos=255, lfnId = -1;\r
-       #endif\r
-        int    i=0;\r
-       tVFS_Node       *tmpNode;\r
-       Uint64  diskOffset;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[node->ImplInt];\r
-       Uint32  dirCluster;\r
-       Uint32  cluster;\r
-       \r
-       ENTER("pnode sname", node, name);\r
-       \r
-       // Fast Returns\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
-       #endif\r
-       \r
-       dirCluster = node->Inode;\r
-       // Seek to Directory\r
-       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
-               diskOffset = (disk->bootsect.resvSectCount+dirCluster*disk->bootsect.spc) << 9;\r
-       else\r
-               diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc) << 9;\r
-       \r
-       for(;;i++)\r
-       {\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
-               \r
-               //Check if the files are free\r
-               if(fileinfo[i&0xF].name[0] == '\0')     break;          //Free and last\r
-               if(fileinfo[i&0xF].name[0] == '\xE5')   goto loadCluster;       //Free\r
-               \r
-               \r
-               #if USE_LFN\r
-               // Long File Name Entry\r
-               if(fileinfo[i&0xF].attrib == ATTR_LFN)\r
-               {\r
-                       lfnInfo = (fat_longfilename *) &fileinfo[i&0xF];\r
-                       if(lfnInfo->id & 0x40) {\r
-                               memset(lfn, 0, 256);\r
-                               lfnPos = 255;\r
-                       }\r
-                       lfn[lfnPos--] = lfnInfo->name3[1];      lfn[lfnPos--] = lfnInfo->name3[0];\r
-                       lfn[lfnPos--] = lfnInfo->name2[5];      lfn[lfnPos--] = lfnInfo->name2[4];\r
-                       lfn[lfnPos--] = lfnInfo->name2[3];      lfn[lfnPos--] = lfnInfo->name2[2];\r
-                       lfn[lfnPos--] = lfnInfo->name2[1];      lfn[lfnPos--] = lfnInfo->name2[0];\r
-                       lfn[lfnPos--] = lfnInfo->name1[4];      lfn[lfnPos--] = lfnInfo->name1[3];\r
-                       lfn[lfnPos--] = lfnInfo->name1[2];      lfn[lfnPos--] = lfnInfo->name1[1];\r
-                       lfn[lfnPos--] = lfnInfo->name1[0];\r
-                       if((lfnInfo->id&0x3F) == 1)\r
-                       {\r
-                               memcpy(lfn, lfn+lfnPos+1, 256-lfnPos);\r
-                               lfnId = i+1;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       // Remove LFN if it does not apply\r
-                       if(lfnId != i)  lfn[0] = '\0';\r
-               #endif\r
-                       // Get Real Filename\r
-                       FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name);\r
-               \r
-                       LOG("tmpName = '%s'", tmpName);\r
-               \r
-                       //Only Long name is case sensitive, 8.3 is not\r
-                       #if USE_LFN\r
-                       if(strucmp(tmpName, name) == 0 || strcmp(lfn, name) == 0) {\r
-                       #else\r
-                       if(strucmp(tmpName, name) == 0) {\r
-                       #endif\r
-                               cluster = fileinfo[i&0xF].cluster | (fileinfo[i&0xF].clusterHi << 16);\r
-                               tmpNode = Inode_GetCache(disk->inodeHandle, cluster);\r
-                               if(tmpNode == NULL)     // Node is not cached\r
-                               {\r
-                                       #if USE_LFN\r
-                                       tmpNode = FAT_int_CreateNode(node, &fileinfo[i&0xF], lfn);\r
-                                       #else\r
-                                       tmpNode = FAT_int_CreateNode(node, &fileinfo[i&0xF], NULL);\r
-                                       #endif\r
-                               }\r
-                               #if USE_LFN\r
-                               lfn[0] = '\0';\r
-                               #endif\r
-                               LEAVE('p', tmpNode);\r
-                               return tmpNode;\r
-                       }\r
-               #if USE_LFN\r
-               }\r
-               #endif\r
-               \r
-       loadCluster:\r
-               //Load Next cluster?\r
-               if( ((i+1) >> 4) % disk->bootsect.spc == 0 && ((i+1) & 0xF) == 0)\r
-               {\r
-                       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
-                               continue;\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
-       \r
-       LEAVE('n');\r
-       return NULL;\r
-}\r
-\r
-/**\r
- * \fn int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
- * \brief Create a new node\r
- */\r
-int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
- * \brief Rename / Delete a file\r
- */\r
-int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn void FAT_CloseFile(tVFS_Node *Node)\r
- * \brief Close an open file\r
- */\r
-void FAT_CloseFile(tVFS_Node *Node)\r
-{\r
-       if(Node == NULL)        return ;\r
-       \r
-       Inode_UncacheNode(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode);\r
-       #if USE_LFN\r
-       if(     !Inode_GetCache(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode)\r
-       &&      Node->Flags & VFS_FFLAG_DIRECTORY)\r
-               FAT_int_DelLFN(Node);\r
-       else    // Get Cache references the node, so dereference it\r
-               Inode_UncacheNode(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode);\r
-       #endif\r
-       return ;\r
-}\r
-\r
-/**\r
- * \fn void fat_install()\r
- * \brief Add the FAT Filesystem to the VFS\r
- */\r
-void fat_install()\r
-{\r
-       VFS_AddDriver( &gFAT_FSInfo );\r
-}\r

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