2 * Acess2 FAT12/16/32 Driver
3 * - By John Hodge (thePowersGang)
6 * - FAT-Specific node caching
13 extern tVFS_Node *FAT_int_CacheNode(tFAT_VolInfo *Disk, const tVFS_Node *Node);
17 * \brief Creates a tVFS_Node structure for a given file entry
18 * \param Parent Parent directory VFS node
19 * \param Entry File table entry for the new node
21 tVFS_Node *FAT_int_CreateNode(tVFS_Node *Parent, fat_filetable *Entry)
25 tFAT_VolInfo *disk = Parent->ImplPtr;
27 ENTER("pParent pEntry", Parent, Entry);
28 LOG("disk = %p", disk);
30 if( (ret = FAT_int_GetNode(disk, Entry->cluster | (Entry->clusterHi<<16))) ) {
35 memset(&node, 0, sizeof(tVFS_Node));
38 // 0-27: Cluster, 32-59: Parent Cluster
39 node.Inode = Entry->cluster | (Entry->clusterHi<<16) | (Parent->Inode << 32);
40 LOG("node.Inode = %llx", node.Inode);
44 node.Size = Entry->size;
45 LOG("Entry->size = %i", Entry->size);
47 node.UID = 0; node.GID = 0;
51 if(Entry->attrib & ATTR_DIRECTORY) node.Flags |= VFS_FFLAG_DIRECTORY;
52 if(Entry->attrib & ATTR_READONLY) {
53 node.Flags |= VFS_FFLAG_READONLY;
54 node.ACLs = &gVFS_ACL_EveryoneRX; // R-XR-XR-X
57 node.ACLs = &gVFS_ACL_EveryoneRWX; // RWXRWXRWX
61 node.ATime = timestamp(0,0,0,
62 ((Entry->adate&0x1F) - 1), // Days
63 ((Entry->adate&0x1E0) - 1), // Months
64 1980+((Entry->adate&0xFF00)>>8) // Years
67 node.CTime = Entry->ctimems * 10; // Miliseconds
68 node.CTime += timestamp(
69 ((Entry->ctime&0x1F)<<1), // Seconds
70 ((Entry->ctime&0x3F0)>>5), // Minutes
71 ((Entry->ctime&0xF800)>>11), // Hours
72 ((Entry->cdate&0x1F)-1), // Days
73 ((Entry->cdate&0x1E0)-1), // Months
74 1980+((Entry->cdate&0xFF00)>>8) // Years
77 node.MTime = timestamp(
78 ((Entry->mtime&0x1F)<<1), // Seconds
79 ((Entry->mtime&0x3F0)>>5), // Minutes
80 ((Entry->mtime&0xF800)>>11), // Hours
81 ((Entry->mdate&0x1F)-1), // Days
82 ((Entry->mdate&0x1E0)-1), // Months
83 1980+((Entry->mdate&0xFF00)>>8) // Years
87 if(node.Flags & VFS_FFLAG_DIRECTORY) {
88 //Log_Debug("FAT", "Directory %08x has size 0x%x", node.Inode, node.Size);
89 node.Type = &gFAT_DirType;
93 node.Type = &gFAT_FileType;
97 ret = FAT_int_CacheNode(disk, &node);
102 tVFS_Node *FAT_int_CreateIncompleteDirNode(tFAT_VolInfo *Disk, Uint32 Cluster)
104 // If the directory isn't in the cache, what do?
105 // - we want to lock it such that we don't collide, but don't want to put crap data in the cache
106 // - Put a temp node in with a flag that indicates it's incomplete?
110 tVFS_Node *FAT_int_GetNode(tFAT_VolInfo *Disk, Uint32 Cluster)
112 if( Cluster == Disk->rootOffset )
113 return &Disk->rootNode;
114 Mutex_Acquire(&Disk->lNodeCache);
115 tFAT_CachedNode *cnode;
117 for(cnode = Disk->NodeCache; cnode; cnode = cnode->Next)
119 if( (cnode->Node.Inode & 0xFFFFFFFF) == Cluster ) {
120 cnode->Node.ReferenceCount ++;
121 Mutex_Release(&Disk->lNodeCache);
126 Mutex_Release(&Disk->lNodeCache);
130 tVFS_Node *FAT_int_CacheNode(tFAT_VolInfo *Disk, const tVFS_Node *Node)
132 tFAT_CachedNode *cnode, *prev = NULL;
133 Mutex_Acquire(&Disk->lNodeCache);
135 for(cnode = Disk->NodeCache; cnode; prev = cnode, cnode = cnode->Next )
137 if( cnode->Node.Inode == Node->Inode ) {
138 cnode->Node.ReferenceCount ++;
139 Mutex_Release(&Disk->lNodeCache);
144 cnode = malloc(sizeof(tFAT_CachedNode));
146 memcpy(&cnode->Node, Node, sizeof(tVFS_Node));
147 cnode->Node.ReferenceCount = 1;
152 Disk->NodeCache = cnode;
154 Mutex_Release(&Disk->lNodeCache);
158 int FAT_int_DerefNode(tVFS_Node *Node)
160 tFAT_VolInfo *Disk = Node->ImplPtr;
161 tFAT_CachedNode *cnode, *prev = NULL;
164 if( Node == &Disk->rootNode )
167 Mutex_Acquire(&Disk->lNodeCache);
168 Node->ReferenceCount --;
169 for(cnode = Disk->NodeCache; cnode; prev = cnode, cnode = cnode->Next )
171 if(Node == &cnode->Node) {
173 prev->Next = cnode->Next;
175 Disk->NodeCache = cnode->Next;
179 if(Node->ReferenceCount == 0 && cnode) {
180 // Already out of the list :)
181 free(cnode->Node.Data);
185 Mutex_Release(&Disk->lNodeCache);
194 void FAT_int_ClearNodeCache(tFAT_VolInfo *Disk)
196 // TODO: In theory when this is called, all handles will be closed