X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fvfs%2Ffs%2Ffat.c;h=3ebe89ad9812a52235caca16ca66c0b5cf4c21b0;hb=bf7d1cd5635d41bd7c58bf99c61cdc670291c543;hp=533e9ccf974bf0e1f22753b9745a160c9d2b5e5e;hpb=72b35e39ee35d38819ee847318cdde533d5b7fdc;p=tpg%2Facess2.git diff --git a/Kernel/vfs/fs/fat.c b/Kernel/vfs/fs/fat.c index 533e9ccf..3ebe89ad 100644 --- a/Kernel/vfs/fs/fat.c +++ b/Kernel/vfs/fs/fat.c @@ -1,31 +1,19 @@ /* - * Acess2 + * Acess 2 * FAT12/16/32 Driver Version (Incl LFN) */ -//INCLUDES -#include -#include -#include -#include "fs_fat.h" - #define DEBUG 0 #define VERBOSE 1 -#if DEBUG -# define DEBUGS(v...) Log(v) -#else -# define DEBUGS(v...) -# undef ENTER -# undef LOG -# undef LEAVE -# define ENTER(...) -# define LOG(...) -# define LEAVE(...) -#endif - #define CACHE_FAT 1 //!< Caches the FAT in memory #define USE_LFN 1 //!< Enables the use of Long File Names +#include +#include +#include +#include "fs_fat.h" + + // === TYPES === #if USE_LFN typedef struct s_lfncache { @@ -38,7 +26,7 @@ typedef struct s_lfncache { // === PROTOTYPES === int FAT_Install(char **Arguments); -tVFS_Node *FAT_InitDevice(char *device, char *options); +tVFS_Node *FAT_InitDevice(char *device, char **options); void FAT_Unmount(tVFS_Node *Node); Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer); @@ -49,12 +37,9 @@ tVFS_Node *FAT_FindDir(tVFS_Node *dirNode, char *file); void FAT_CloseFile(tVFS_Node *node); // === SEMI-GLOBALS === -MODULE_DEFINE(0, 0x5B /*v0.90*/, FAT32, FAT_Install, NULL); +MODULE_DEFINE(0, 0x51 /*v0.80*/, VFAT, FAT_Install, NULL, NULL); tFAT_VolInfo gFAT_Disks[8]; int giFAT_PartCount = 0; -#if CACHE_FAT -Uint32 *fat_cache[8]; -#endif #if USE_LFN t_lfncache *fat_lfncache; #endif @@ -70,14 +55,14 @@ tVFS_Driver gFAT_FSInfo = { int FAT_Install(char **Arguments) { VFS_AddDriver( &gFAT_FSInfo ); - return 0; + return MODULE_INIT_SUCCESS; } /** - * \fn tVFS_Node *FAT_InitDevice(char *Device, char *options) + * \fn tVFS_Node *FAT_InitDevice(char *Device, char **options) * \brief Reads the boot sector of a disk and prepares the structures for it */ -tVFS_Node *FAT_InitDevice(char *Device, char *options) +tVFS_Node *FAT_InitDevice(char *Device, char **options) { fat_bootsect *bs; int i; @@ -131,6 +116,7 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options) case FAT12: sFatType = "FAT12"; break; case FAT16: sFatType = "FAT16"; break; case FAT32: sFatType = "FAT32"; break; + default: sFatType = "UNKNOWN"; break; } if(iSize <= 2*1024) { sSize = "KiB"; @@ -172,8 +158,8 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options) #if CACHE_FAT { Uint32 Ofs; - fat_cache[ giFAT_PartCount ] = (Uint32*)malloc(sizeof(Uint32)*CountofClusters); - if(fat_cache[giFAT_PartCount] == NULL) { + diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*CountofClusters); + if(diskInfo->FATCache == NULL) { Warning("FAT_InitDisk - Heap Exhausted\n"); return NULL; } @@ -189,8 +175,8 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options) Ofs += 3*512; } val = *((int*)(buf+j*3)); - fat_cache[giFAT_PartCount][i*2] = val & 0xFFF; - fat_cache[giFAT_PartCount][i*2+1] = (val>>12) & 0xFFF; + diskInfo->FATCache[i*2] = val & 0xFFF; + diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF; } } if(diskInfo->type == FAT16) { @@ -200,7 +186,7 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options) VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf); Ofs += 512; } - fat_cache[giFAT_PartCount][i] = buf[i&255]; + diskInfo->FATCache[i] = buf[i&255]; } } if(diskInfo->type == FAT32) { @@ -210,22 +196,19 @@ tVFS_Node *FAT_InitDevice(char *Device, char *options) VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf); Ofs += 512; } - fat_cache[giFAT_PartCount][i] = buf[i&127]; + diskInfo->FATCache[i] = buf[i&127]; } } - DEBUGS(" FAT_InitDisk: FAT Fully Cached\n"); + LOG("FAT Fully Cached"); } #endif /*CACHE_FAT*/ //Initalise inode cache for FAT - gFAT_Disks[giFAT_PartCount].inodeHandle = Inode_GetHandle(); - - #if DEBUG - Log(" FAT_InitDisk: Inode Cache handle is %i\n", gFAT_Disks[giFAT_PartCount].inodeHandle); - #endif + diskInfo->inodeHandle = Inode_GetHandle(); + LOG("Inode Cache handle is %i", diskInfo->inodeHandle); // == VFS Interface - node = &gFAT_Disks[giFAT_PartCount].rootNode; + node = &diskInfo->rootNode; node->Inode = diskInfo->rootOffset; node->Size = bs->files_in_root; // Unknown - To be set on readdir node->ImplInt = giFAT_PartCount; @@ -265,23 +248,32 @@ void FAT_Unmount(tVFS_Node *Node) } /** - * \fn static Uint32 FAT_int_GetFatValue(int handle, Uint32 cluster) + * \fn static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster) * \brief Fetches a value from the FAT */ -static Uint32 FAT_int_GetFatValue(int handle, Uint32 cluster) +static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster) { - Uint32 val; - ENTER("iHandle xCluster", handle, cluster); + Uint32 val = 0; + #if !CACHE_FAT + Uint32 ofs = Disk->bootsect.resvSectCount*512; + #endif + ENTER("pDisk xCluster", Disk, cluster); #if CACHE_FAT - val = fat_cache[handle][cluster]; + val = Disk->FATCache[cluster]; + if(Disk->type == FAT12 && val == EOC_FAT12) val = -1; + if(Disk->type == FAT16 && val == EOC_FAT16) val = -1; + if(Disk->type == FAT32 && val == EOC_FAT32) val = -1; #else - if(gFAT_Disks[handle].type == FAT12) { - VFS_ReadAt(gFAT_Disks[handle].fileHandle, 512+(cluster&~1)*3, 3, &val); + if(Disk->type == FAT12) { + VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val); val = (cluster&1 ? val&0xFFF : val>>12); - } else if(gFAT_Disks[handle].type == FAT16) { - VFS_ReadAt(gFAT_Disks[handle].fileHandle, 512+cluster*2, 2, &val); + if(val == EOC_FAT12) val = -1; + } else if(Disk->type == FAT16) { + VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val); + if(val == EOC_FAT16) val = -1; } else { - VFS_ReadAt(gFAT_Disks[handle].fileHandle, 512+cluster*4, 4, &val); + VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val); + if(val == EOC_FAT32) val = -1; } #endif /*CACHE_FAT*/ LEAVE('x', val); @@ -292,9 +284,8 @@ static Uint32 FAT_int_GetFatValue(int handle, Uint32 cluster) */ static void FAT_int_ReadCluster(int Handle, Uint32 Cluster, int Length, void *Buffer) { - #if DEBUG ENTER("iHandle xCluster iLength pBuffer", Handle, Cluster, Length, Buffer); - #endif + //Log("Cluster = %i (0x%x)", Cluster, Cluster); VFS_ReadAt( gFAT_Disks[Handle].fileHandle, (gFAT_Disks[Handle].firstDataSect + (Cluster-2)*gFAT_Disks[Handle].bootsect.spc ) @@ -302,9 +293,7 @@ static void FAT_int_ReadCluster(int Handle, Uint32 Cluster, int Length, void *Bu Length, Buffer ); - #if DEBUG LEAVE('-'); - #endif } /** @@ -318,7 +307,6 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer) int i, cluster, pos; int bpc; void *tmpBuf; - Uint eocMarker; tFAT_VolInfo *disk = &gFAT_Disks[node->ImplInt]; ENTER("Xoffset Xlength pbuffer", offset, length, buffer); @@ -331,27 +319,17 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer) // Cluster is stored in Inode Field cluster = node->Inode; - // Get EOC Marker - if (disk->type == FAT12) eocMarker = EOC_FAT12; - else if(disk->type == FAT16) eocMarker = EOC_FAT16; - else if(disk->type == FAT32) eocMarker = EOC_FAT32; - else { - Log("ERROR: Unsupported FAT Variant.\n"); - free(tmpBuf); - LEAVE('i', 0); - return 0; - } - // Sanity Check offset if(offset > node->Size) { - Log("FAT_Read: Reading past EOF (%i > %i)", offset, node->Size); + //LOG("Reading past EOF (%i > %i)", offset, node->Size); + LEAVE('i', 0); return 0; } // Clamp Size if(offset + length > node->Size) { - Log("FAT_Read: Reading past EOF (%i+%i+ > %i), clamped to %i", - offset, length, node->Size, offset - node->Size); - length = offset - node->Size; + //LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli", + // offset, length, node->Size, node->Size - offset); + length = node->Size - offset; } // Single Cluster including offset @@ -368,9 +346,11 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer) //Skip previous clusters for(i=preSkip;i--;) { - cluster = FAT_int_GetFatValue(handle, cluster); - if(cluster == eocMarker) { + cluster = FAT_int_GetFatValue(disk, cluster); + if(cluster == -1) { Warning("FAT_Read - Offset is past end of cluster chain mark"); + LEAVE('i', 0); + return 0; } } @@ -394,7 +374,7 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer) return length; } - cluster = FAT_int_GetFatValue(handle, cluster); + cluster = FAT_int_GetFatValue(disk, cluster); #if DEBUG LOG("pos=%i\n", pos); @@ -408,8 +388,8 @@ Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer) FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf); memcpy((void*)(buffer+pos), tmpBuf, bpc); pos += bpc; - cluster = FAT_int_GetFatValue(handle, cluster); - if(cluster == eocMarker) { + cluster = FAT_int_GetFatValue(disk, cluster); + if(cluster == -1) { Warning("FAT_Read - Read past End of Cluster Chain"); free(tmpBuf); LEAVE('i', 0); @@ -504,6 +484,7 @@ tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFi // Set Other Data node.Inode = ft->cluster | (ft->clusterHi<<16); node.Size = ft->size; + LOG("ft->size = %i", ft->size); node.ImplInt = parent->ImplInt; node.UID = 0; node.GID = 0; node.NumACLs = 1; @@ -630,25 +611,23 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos) // Get Byte Offset and skip offset = dirpos * sizeof(fat_filetable); - preSkip = (offset >> 9) / disk->bootsect.spc; // >>9 == /512 + preSkip = offset / (512 * disk->bootsect.spc); + LOG("disk->bootsect.spc = %i", disk->bootsect.spc); + LOG("dirNode->size = %i", dirNode->Size); cluster = dirNode->Inode; // Cluster ID // Do Cluster Skip // - Pre FAT32 had a reserved area for the root. - if( !(disk->type != FAT32 && cluster == disk->rootOffset) ) + if( disk->type == FAT32 || cluster != disk->rootOffset ) { //Skip previous clusters for(a=preSkip;a--;) { - cluster = FAT_int_GetFatValue(dirNode->ImplInt, cluster); + cluster = FAT_int_GetFatValue(disk, cluster); + // Check for end of cluster chain + if(cluster == -1) { LEAVE('n'); return NULL;} } } - // Check for end of cluster chain - if((disk->type == FAT12 && cluster == EOC_FAT12) - || (disk->type == FAT16 && cluster == EOC_FAT16) - || (disk->type == FAT32 && cluster == EOC_FAT32)) - return NULL; - // Bounds Checking (Used to spot heap overflows) if(cluster > disk->clusterCount + 2) { @@ -658,7 +637,7 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos) return NULL; } - LOG("cluster=0x%x, dirpos=%i\n", cluster, dirpos); + LOG("cluster=0x%x, dirpos=%i", cluster, dirpos); // Compute Offsets // - Pre FAT32 cluster base (in sectors) @@ -670,21 +649,19 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos) offset += (cluster - 2) * disk->bootsect.spc; } // Sector in cluster - if(disk->bootsect.spc == 1) - offset += (dirpos / 16); - else + if(disk->bootsect.spc != 1) offset += (dirpos / 16) % disk->bootsect.spc; // Offset in sector - a = dirpos & 0xF; + a = dirpos % 16; - LOG("offset=%i, a=%i", (Uint)offset, a); + LOG("offset=%i, a=%i", offset, a); // Read Sector VFS_ReadAt(disk->fileHandle, offset*512, 512, fileinfo); // Read Dir Data LOG("name[0] = 0x%x", (Uint8)fileinfo[a].name[0]); //Check if this is the last entry - if(fileinfo[a].name[0] == '\0') { + if( fileinfo[a].name[0] == '\0' ) { dirNode->Size = dirpos; LOG("End of list"); LEAVE('n'); @@ -692,8 +669,8 @@ char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos) } // Check for empty entry - if((Uint8)fileinfo[a].name[0] == 0xE5) { - LOG("Empty Entry\n"); + if( (Uint8)fileinfo[a].name[0] == 0xE5 ) { + LOG("Empty Entry"); LEAVE('p', VFS_SKIP); return VFS_SKIP; // Skip } @@ -781,8 +758,10 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name) ENTER("pnode sname", node, name); // Fast Returns - if(!name) return NULL; - if(name[0] == '\0') return NULL; + if(!name || name[0] == '\0') { + LEAVE('n'); + return NULL; + } #if USE_LFN lfn = FAT_int_GetLFN(node); @@ -799,6 +778,7 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name) { // Load sector if((i & 0xF) == 0) { + //Log("FAT_FindDir: diskOffset = 0x%x", diskOffset); VFS_ReadAt(disk->fileHandle, diskOffset, 512, fileinfo); diskOffset += 512; } @@ -838,7 +818,7 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name) // Get Real Filename FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name); - LOG("tmpName = '%s'\n", tmpName); + LOG("tmpName = '%s'", tmpName); //Only Long name is case sensitive, 8.3 is not #if USE_LFN @@ -872,7 +852,8 @@ tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name) { if( dirCluster == disk->rootOffset && disk->type != FAT32 ) continue; - dirCluster = FAT_int_GetFatValue(node->ImplInt, dirCluster); + dirCluster = FAT_int_GetFatValue(disk, dirCluster); + if(dirCluster == -1) break; diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc)*512; } }