* \todo Implement changing of the parent directory when a file is written to\r
* \todo Implement file creation / deletion\r
*/\r
-#define DEBUG 1\r
+#define DEBUG 0\r
#define VERBOSE 1\r
\r
#define CACHE_FAT 0 //!< Caches the FAT in memory\r
typedef struct sFAT_LFNCacheEnt\r
{\r
int ID;\r
+ // TODO: Handle UTF16 names correctly\r
char Data[256];\r
} tFAT_LFNCacheEnt;\r
/**\r
// === 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
// --- 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
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
}\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
// - 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
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
\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
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
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
\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
{\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
{\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
tFAT_VolInfo *disk = Parent->ImplPtr;\r
\r
ENTER("pParent pFT", Parent, Entry);\r
- LOG("disk = %p\n", disk);\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
// 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
}\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
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
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
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
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
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
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
\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
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
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
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
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