VFS - Rework to remove function pointers from tVFS_Node
[tpg/acess2.git] / Modules / Filesystems / FAT / fat.c
index fbf4f71..f5d1916 100644 (file)
@@ -40,6 +40,7 @@
 typedef struct sFAT_LFNCacheEnt\r
 {\r
         int    ID;\r
+       // TODO: Handle UTF16 names correctly\r
        char    Data[256];\r
 }      tFAT_LFNCacheEnt;\r
 /**\r
@@ -55,7 +56,7 @@ typedef struct sFAT_LFNCache
 // === PROTOTYPES ===\r
 // --- Driver Core\r
  int   FAT_Install(char **Arguments);\r
-tVFS_Node      *FAT_InitDevice(char *device, char **options);\r
+tVFS_Node      *FAT_InitDevice(const char *device, const char **options);\r
 void   FAT_Unmount(tVFS_Node *Node);\r
 // --- Helpers\r
  int   FAT_int_GetAddress(tVFS_Node *Node, Uint64 Offset, Uint64 *Addr, Uint32 *Cluster);\r
@@ -74,6 +75,7 @@ Uint64        FAT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
 // --- Directory IO\r
 char   *FAT_ReadDir(tVFS_Node *Node, int ID);\r
 tVFS_Node      *FAT_FindDir(tVFS_Node *Node, const char *Name);\r
+tVFS_Node      *FAT_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode);\r
 #if SUPPORT_WRITE\r
  int   FAT_Mknod(tVFS_Node *Node, const char *Name, Uint Flags);\r
  int   FAT_Relink(tVFS_Node *node, const char *OldName, const char *NewName);\r
@@ -87,7 +89,25 @@ void FAT_CloseFile(tVFS_Node *node);
 MODULE_DEFINE(0, (0<<8)|50 /*v0.50*/, VFAT, FAT_Install, NULL, NULL);\r
 tFAT_VolInfo   gFAT_Disks[8];\r
  int   giFAT_PartCount = 0;\r
-tVFS_Driver    gFAT_FSInfo = {"fat", 0, FAT_InitDevice, FAT_Unmount, NULL};\r
+tVFS_Driver    gFAT_FSInfo = {"fat", 0, FAT_InitDevice, FAT_Unmount, FAT_GetNodeFromINode, NULL};\r
+tVFS_NodeType  gFAT_DirType = {\r
+       .TypeName = "FAT-Dir",\r
+       .ReadDir = FAT_ReadDir,\r
+       .FindDir = FAT_FindDir,\r
+       #if SUPPORT_WRITE\r
+       .MkNod = FAT_Mknod,\r
+       .Relink = FAT_Relink,\r
+       #endif\r
+       .Close = FAT_CloseFile\r
+       };\r
+tVFS_NodeType  gFAT_FileType = {\r
+       .TypeName = "FAT-File",\r
+       .Read = FAT_Read,\r
+       #if SUPPORT_WRITE\r
+       .Write = FAT_Write,\r
+       #endif\r
+       .Close = FAT_CloseFile\r
+       };\r
 \r
 // === CODE ===\r
 /**\r
@@ -101,10 +121,9 @@ int FAT_Install(char **Arguments)
 }\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
+tVFS_Node *FAT_InitDevice(const char *Device, const char **Options)\r
 {\r
        fat_bootsect *bs;\r
         int    i;\r
@@ -133,11 +152,15 @@ tVFS_Node *FAT_InitDevice(char *Device, char **Options)
        // - 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
+       if(bs->fatSz16 != 0)\r
+               FATSz = bs->fatSz16;\r
+       else\r
+               FATSz = bs->spec.fat32.fatSz32;\r
        \r
-       if(bs->totalSect16 != 0)                TotSec = bs->totalSect16;\r
-       else                                            TotSec = bs->totalSect32;\r
+       if(bs->totalSect16 != 0)\r
+               TotSec = bs->totalSect16;\r
+       else\r
+               TotSec = bs->totalSect32;\r
        \r
        diskInfo->ClusterCount = (TotSec - (bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors)) / bs->spc;\r
        \r
@@ -268,18 +291,8 @@ tVFS_Node *FAT_InitDevice(char *Device, char **Options)
        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
-       #if SUPPORT_WRITE\r
-       node->Relink = FAT_Relink;\r
-       node->MkNod = FAT_Mknod;\r
-       #else\r
-       node->Relink = NULL;\r
-       node->MkNod = NULL;\r
-       #endif\r
-       //node->Close = FAT_Unmount;\r
+\r
+       node->Type = &gFAT_DirType;     \r
        \r
        giFAT_PartCount ++;\r
        return node;\r
@@ -325,8 +338,8 @@ int FAT_int_GetAddress(tVFS_Node *Node, Uint64 Offset, Uint64 *Addr, Uint32 *Clu
        \r
        ENTER("pNode XOffset", Node, Offset);\r
        \r
-       cluster = Node->Inode & 0xFFFFFFFF;     // Cluster ID\r
-       LOG("cluster = %08x", cluster);\r
+       cluster = Node->Inode & 0xFFFFFFF     // Cluster ID\r
+       LOG("cluster = 0x%07x", cluster);\r
        \r
        // Do Cluster Skip\r
        // - Pre FAT32 had a reserved area for the root.\r
@@ -393,7 +406,7 @@ Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)
        Uint32  val = 0;\r
        Uint32  ofs;\r
        ENTER("pDisk xCluster", Disk, cluster);\r
-       LOCK( &Disk->lFAT );\r
+       Mutex_Acquire( &Disk->lFAT );\r
        #if CACHE_FAT\r
        if( Disk->ClusterCount <= giFAT_MaxCachedClusters )\r
        {\r
@@ -420,7 +433,7 @@ Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)
        #if CACHE_FAT\r
        }\r
        #endif /*CACHE_FAT*/\r
-       RELEASE( &Disk->lFAT );\r
+       Mutex_Release( &Disk->lFAT );\r
        LEAVE('x', val);\r
        return val;\r
 }\r
@@ -609,136 +622,110 @@ 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
-        int    bpc;\r
-       void    *tmpBuf;\r
        tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       char    tmpBuf[disk->BytesPerCluster];\r
+        int    bpc = disk->BytesPerCluster;\r
        \r
        ENTER("pNode Xoffset Xlength pbuffer", Node, Offset, Length, Buffer);\r
        \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
        \r
-       // Calculate and Allocate Bytes Per Cluster\r
-       bpc = disk->BytesPerCluster;\r
-       tmpBuf = (void*) malloc(bpc);\r
-       if( !tmpBuf )   return 0;\r
-       \r
        // Cluster is stored in the low 32-bits of the Inode field\r
        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
-               free(tmpBuf);\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
-                       free(tmpBuf);\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 (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
-               free(tmpBuf);\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
-                       Warning("FAT_Read - Read past End of Cluster Chain");\r
-                       free(tmpBuf);\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
-               Warning("FAT_Read - Read past End of Cluster Chain");\r
-               free(tmpBuf);\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
-       free(tmpBuf);\r
        LEAVE('X', Length);\r
        return Length;\r
 }\r
@@ -770,7 +757,7 @@ void FAT_int_WriteCluster(tFAT_VolInfo *Disk, Uint32 Cluster, void *Buffer)
 Uint64 FAT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
 {\r
        tFAT_VolInfo    *disk = Node->ImplPtr;\r
-       void    *tmpBuf;\r
+       char    tmpBuf[disk->BytesPerCluster];\r
         int    remLength = Length;\r
        Uint32  cluster, tmpCluster;\r
         int    bNewCluster = 0;\r
@@ -798,29 +785,24 @@ Uint64 FAT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        \r
        if( Offset + Length < disk->BytesPerCluster )\r
        {\r
-               tmpBuf = malloc( disk->BytesPerCluster );\r
+               char    tmpBuf[disk->BytesPerCluster];\r
                \r
                // Read-Modify-Write\r
                FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
                memcpy( tmpBuf + Offset, Buffer, Length );\r
                FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
                \r
-               free(tmpBuf);\r
                return Length;\r
        }\r
        \r
        // Clean up changes within a cluster\r
        if( Offset )\r
-       {\r
-               tmpBuf = malloc( disk->BytesPerCluster );\r
-               \r
+       {       \r
                // Read-Modify-Write\r
                FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
                memcpy( tmpBuf + Offset, Buffer, disk->BytesPerCluster - Offset );\r
                FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
                \r
-               free(tmpBuf);\r
-               \r
                remLength -= disk->BytesPerCluster - Offset;\r
                Buffer += disk->BytesPerCluster - Offset;\r
                \r
@@ -911,6 +893,7 @@ char *FAT_int_CreateName(fat_filetable *ft, char *LongFileName)
 {\r
        char    *ret;\r
        ENTER("pft sLongFileName", ft, LongFileName);\r
+       //Log_Debug("FAT", "FAT_int_CreateName(ft=%p, LongFileName=%p'%s')", ft, LongFileName);\r
        #if USE_LFN\r
        if(LongFileName && LongFileName[0] != '\0')\r
        {       \r
@@ -920,6 +903,10 @@ char *FAT_int_CreateName(fat_filetable *ft, char *LongFileName)
        {\r
        #endif\r
                ret = (char*) malloc(13);\r
+               if( !ret ) {\r
+                       Log_Warning("FAT", "FAT_int_CreateName: malloc(13) failed");\r
+                       return NULL;\r
+               }\r
                FAT_int_ProperFilename(ret, ft->name);\r
        #if USE_LFN\r
        }\r
@@ -941,11 +928,12 @@ tVFS_Node *FAT_int_CreateNode(tVFS_Node *Parent, fat_filetable *Entry, int Pos)
        tFAT_VolInfo    *disk = Parent->ImplPtr;\r
        \r
        ENTER("pParent pFT", Parent, Entry);\r
+       LOG("disk = %p", disk);\r
        \r
        memset(&node, 0, sizeof(tVFS_Node));\r
        \r
        // Set Other Data\r
-       // 0-31: Cluster, 32-63: Parent Cluster\r
+       // 0-27: Cluster, 32-59: Parent Cluster\r
        node.Inode = Entry->cluster | (Entry->clusterHi<<16) | (Parent->Inode << 32);\r
        LOG("node.Inode = %llx", node.Inode);\r
        // Position in parent directory\r
@@ -997,21 +985,12 @@ tVFS_Node *FAT_int_CreateNode(tVFS_Node *Parent, fat_filetable *Entry, int Pos)
        // Set pointers\r
        if(node.Flags & VFS_FFLAG_DIRECTORY) {\r
                //Log_Debug("FAT", "Directory %08x has size 0x%x", node.Inode, node.Size);\r
-               node.ReadDir = FAT_ReadDir;\r
-               node.FindDir = FAT_FindDir;\r
-               #if SUPPORT_WRITE\r
-               node.MkNod = FAT_Mknod;\r
-               node.Relink = FAT_Relink;\r
-               #endif\r
+               node.Type = &gFAT_DirType;      \r
                node.Size = -1;\r
        }\r
        else {\r
-               node.Read = FAT_Read;\r
-               #if SUPPORT_WRITE\r
-               node.Write = FAT_Write;\r
-               #endif\r
+               node.Type = &gFAT_FileType;\r
        }\r
-       node.Close = FAT_CloseFile;\r
        \r
        ret = Inode_CacheNode(disk->inodeHandle, &node);\r
        LEAVE('p', ret);\r
@@ -1098,12 +1077,7 @@ int FAT_int_WriteDirEntry(tVFS_Node *Node, int ID, fat_filetable *Entry)
 }\r
 #endif\r
 \r
-#if USE_LFN\r
-// I should probably more tightly associate the LFN cache with the node\r
-// somehow, maybe by adding a field to tVFS_Node before locking it\r
-// Maybe .Cache or something like that (something that is free'd by the\r
-// Inode_UncacheNode function)\r
-       \r
+#if USE_LFN    \r
 /**\r
  * \fn char *FAT_int_GetLFN(tVFS_Node *node)\r
  * \brief Return pointer to LFN cache entry\r
@@ -1116,6 +1090,8 @@ char *FAT_int_GetLFN(tVFS_Node *Node, int ID)
        tFAT_LFNCache   *cache;\r
         int    i, firstFree;\r
        \r
+       Mutex_Acquire( &Node->Lock );\r
+       \r
        // TODO: Thread Safety (Lock things)\r
        cache = Node->Data;\r
        \r
@@ -1125,15 +1101,20 @@ char *FAT_int_GetLFN(tVFS_Node *Node, int ID)
                cache->NumEntries = 1;\r
                cache->Entries[0].ID = ID;\r
                cache->Entries[0].Data[0] = '\0';\r
+               Mutex_Release( &Node->Lock );\r
+               //Log_Debug("FAT", "Return = %p (new)", cache->Entries[0].Data);\r
                return cache->Entries[0].Data;\r
        }\r
        \r
-       // Scan for a current entry\r
+       // Scan for this entry\r
        firstFree = -1;\r
        for( i = 0; i < cache->NumEntries; i++ )\r
        {\r
-               if( cache->Entries[i].ID == ID )\r
+               if( cache->Entries[i].ID == ID ) {\r
+                       Mutex_Release( &Node->Lock );\r
+                       //Log_Debug("FAT", "Return = %p (match)", cache->Entries[i].Data);\r
                        return cache->Entries[i].Data;\r
+               }\r
                if( cache->Entries[i].ID == -1 && firstFree == -1 )\r
                        firstFree = i;\r
        }\r
@@ -1143,9 +1124,11 @@ char *FAT_int_GetLFN(tVFS_Node *Node, int ID)
                i = sizeof(tFAT_LFNCache) + (cache->NumEntries+1)*sizeof(tFAT_LFNCacheEnt);\r
                Node->Data = realloc( Node->Data, i );\r
                if( !Node->Data ) {\r
-                       Log_Error("FAT", "malloc() fail, unable to allocate %i for LFN cache", i);\r
+                       Log_Error("FAT", "realloc() fail, unable to allocate %i for LFN cache", i);\r
+                       Mutex_Release( &Node->Lock );\r
                        return NULL;\r
                }\r
+               //Log_Debug("FAT", "Realloc (%i)\n", i);\r
                cache = Node->Data;\r
                i = cache->NumEntries;\r
                cache->NumEntries ++;\r
@@ -1158,7 +1141,8 @@ char *FAT_int_GetLFN(tVFS_Node *Node, int ID)
        cache->Entries[ i ].ID = ID;\r
        cache->Entries[ i ].Data[0] = '\0';\r
        \r
-       //TODO: Unlock\r
+       Mutex_Release( &Node->Lock );\r
+       //Log_Debug("FAT", "Return = %p (firstFree, i = %i)", cache->Entries[i].Data, i);\r
        return cache->Entries[ i ].Data;\r
 }\r
 \r
@@ -1240,33 +1224,32 @@ char *FAT_ReadDir(tVFS_Node *Node, int ID)
        if(fileinfo[a].attrib == ATTR_LFN)\r
        {\r
                fat_longfilename        *lfnInfo;\r
-                int    len;\r
                \r
                lfnInfo = (fat_longfilename *) &fileinfo[a];\r
                \r
                // Get cache for corresponding file\r
+               // > ID + Index gets the corresponding short node\r
                lfn = FAT_int_GetLFN( Node, ID + (lfnInfo->id & 0x3F) );\r
                \r
                // Bit 6 indicates the start of an entry\r
                if(lfnInfo->id & 0x40)  memset(lfn, 0, 256);\r
                \r
-               // Get the current length\r
-               len = strlen(lfn);\r
+               a = ((lfnInfo->id & 0x3F) - 1) * 13;\r
+               //Log_Debug("FAT", "ID = 0x%02x, a = %i", lfnInfo->id, a);\r
                \r
                // Sanity Check (FAT implementations should not allow >255 character names)\r
-               if(len + 13 > 255)      return VFS_SKIP;\r
-               // Rebase all bytes\r
-               for(a=len+1;a--;)       lfn[a+13] = lfn[a];\r
+               if(a > 255)     return VFS_SKIP;\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
+               lfn[a+ 0] = lfnInfo->name1[0];  lfn[a+ 1] = lfnInfo->name1[1];\r
+               lfn[a+ 2] = lfnInfo->name1[2];  lfn[a+ 3] = lfnInfo->name1[3];\r
+               lfn[a+ 4] = lfnInfo->name1[4];  \r
+               lfn[a+ 5] = lfnInfo->name2[0];  lfn[a+ 6] = lfnInfo->name2[1];\r
+               lfn[a+ 7] = lfnInfo->name2[2];  lfn[a+ 8] = lfnInfo->name2[3];\r
+               lfn[a+ 9] = lfnInfo->name2[4];  lfn[a+10] = lfnInfo->name2[5];\r
+               lfn[a+11] = lfnInfo->name3[0];  lfn[a+12] = lfnInfo->name3[1];\r
                LOG("lfn = '%s'", lfn);\r
+               //Log_Debug("FAT", "lfn = '%s'", lfn);\r
                LEAVE('p', VFS_SKIP);\r
                return VFS_SKIP;\r
        }\r
@@ -1277,11 +1260,16 @@ char *FAT_ReadDir(tVFS_Node *Node, int ID)
                LEAVE('p', VFS_SKIP);\r
                return VFS_SKIP;\r
        }\r
-       // Ignore . and ..\r
-       if(fileinfo[a].name[0] == '.') {\r
+       // Ignore .\r
+       if(fileinfo[a].name[0] == '.' && fileinfo[a].name[1] == ' ') {\r
                LEAVE('p', VFS_SKIP);\r
                return VFS_SKIP;\r
-       }       \r
+       }\r
+       // and ..\r
+       if(fileinfo[a].name[0] == '.' && fileinfo[a].name[1] == '.' && fileinfo[a].name[2] == ' ') {\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'",\r
                fileinfo[a].name[0], fileinfo[a].name[1], fileinfo[a].name[2], fileinfo[a].name[3],\r
@@ -1290,6 +1278,7 @@ char *FAT_ReadDir(tVFS_Node *Node, int ID)
        \r
        #if USE_LFN\r
        lfn = FAT_int_GetLFN(Node, ID);\r
+       //Log_Debug("FAT", "lfn = %p'%s'", lfn, lfn);\r
        ret = FAT_int_CreateName(&fileinfo[a], lfn);\r
        #else\r
        ret = FAT_int_CreateName(&fileinfo[a], NULL);\r
@@ -1317,8 +1306,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
@@ -1347,8 +1336,11 @@ tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name)
                        lfnInfo = (fat_longfilename *) &fileinfo[i&0xF];\r
                        if(lfnInfo->id & 0x40) {\r
                                memset(lfn, 0, 256);\r
-                               lfnPos = 255;\r
+                               lfnPos = (lfnInfo->id & 0x3F) * 13 - 1;\r
                        }\r
+                       // Sanity check the position so we don't overflow\r
+                       if( lfnPos < 12 )\r
+                               continue ;\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
@@ -1358,7 +1350,6 @@ tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name)
                        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
@@ -1398,6 +1389,60 @@ tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name)
        return NULL;\r
 }\r
 \r
+tVFS_Node *FAT_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode)\r
+{\r
+       tFAT_VolInfo    *disk = Root->ImplPtr;\r
+        int    ents_per_sector = 512 / sizeof(fat_filetable); \r
+       fat_filetable   fileinfo[ents_per_sector];\r
+        int    sector = 0, i;\r
+       tVFS_Node       stub_node;\r
+\r
+       ENTER("pRoot XInode", Root, Inode);\r
+\r
+       stub_node.ImplPtr = disk;\r
+       stub_node.Size = -1;\r
+       stub_node.Inode = Inode >> 32;\r
+\r
+       for( i = 0; ; i ++ )\r
+       {\r
+               if( i == 0 || i == ents_per_sector )\r
+               {\r
+                       if(FAT_int_ReadDirSector(&stub_node, sector, fileinfo))\r
+                       {\r
+                               LOG("ReadDirSector failed");\r
+                               LEAVE('n');\r
+                               return NULL;\r
+                       }\r
+                       i = 0;\r
+                       sector ++;\r
+               }\r
+       \r
+               // Check for free/end of list\r
+               if(fileinfo[i].name[0] == '\0') break;  // End of List marker\r
+               if(fileinfo[i].name[0] == '\xE5')       continue;       // Free entry\r
+               \r
+               if(fileinfo[i].attrib == ATTR_LFN)      continue;\r
+\r
+               LOG("fileinfo[i].cluster = %x %04x", fileinfo[i].clusterHi, fileinfo[i].cluster);\r
+               #if DEBUG\r
+               {\r
+                       char    tmpName[13];\r
+                       FAT_int_ProperFilename(tmpName, fileinfo[i].name);\r
+                       LOG("tmpName = '%s'", tmpName);\r
+               }\r
+               #endif\r
+               \r
+       \r
+               if(fileinfo[i].cluster != (Inode & 0xFFFF))     continue;\r
+               if(fileinfo[i].clusterHi != ((Inode >> 16) & 0xFFFF))   continue;\r
+\r
+               LEAVE_RET('p', FAT_int_CreateNode(&stub_node, &fileinfo[i], sector*ents_per_sector+i));\r
+       }\r
+       LOG("sector = %i, i = %i", sector, i);\r
+       LEAVE('n');\r
+       return NULL;\r
+}\r
+\r
 #if SUPPORT_WRITE\r
 /**\r
  * \fn int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r

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