3 * - AllocHandle, GetHandle
12 #include <threads.h> // GetMaxFD
13 #include <vfs_threads.h> // Handle maintainance
16 #define MAX_KERNEL_FILES 128
20 tVFS_Handle *VFS_GetHandle(int FD);
22 inline void _ReferenceNode(tVFS_Node *Node);
23 int VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode);
26 tVFS_Handle *gaUserHandles = (void*)MM_PPD_HANDLES;
27 tVFS_Handle *gaKernelHandles = (void*)MM_KERNEL_VFS;
30 inline void _ReferenceNode(tVFS_Node *Node)
32 if( !MM_GetPhysAddr(Node->Type) ) {
33 Log_Error("VFS", "Node %p's type is invalid (%p bad pointer) - %P corrupted",
34 Node, Node->Type, MM_GetPhysAddr(&Node->Type));
37 if( Node->Type && Node->Type->Reference )
38 Node->Type->Reference( Node );
40 Node->ReferenceCount ++;
44 * \fn tVFS_Handle *VFS_GetHandle(int FD)
45 * \brief Gets a pointer to the handle information structure
47 tVFS_Handle *VFS_GetHandle(int FD)
51 //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
53 if(FD < 0) return NULL;
55 if(FD & VFS_KERNEL_FLAG) {
56 FD &= (VFS_KERNEL_FLAG - 1);
57 if(FD >= MAX_KERNEL_FILES) return NULL;
58 h = &gaKernelHandles[ FD ];
60 if(FD >= *Threads_GetMaxFD()) return NULL;
61 h = &gaUserHandles[ FD ];
64 if(h->Node == NULL) return NULL;
65 //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
69 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
73 // Check for a user open
76 int max_handles = *Threads_GetMaxFD();
78 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
81 size = max_handles * sizeof(tVFS_Handle);
82 for(addr = 0; addr < size; addr += 0x1000)
84 if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
86 Warning("OOM - VFS_AllocHandle");
87 Threads_Exit(0, 0xFF); // Terminate user
90 memset( gaUserHandles, 0, size );
93 for( i = 0; i < max_handles; i ++ )
95 if(gaUserHandles[i].Node) continue;
96 gaUserHandles[i].Node = Node;
97 gaUserHandles[i].Position = 0;
98 gaUserHandles[i].Mode = Mode;
104 // Allocate space if not already
105 if( MM_GetPhysAddr( gaKernelHandles ) == 0 )
108 size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
109 for(addr = 0; addr < size; addr += 0x1000)
111 if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) )
113 Panic("OOM - VFS_AllocHandle");
114 Threads_Exit(0, 0xFF); // Terminate application (get some space back)
117 memset( gaKernelHandles, 0, size );
120 for(i=0;i<MAX_KERNEL_FILES;i++)
122 if(gaKernelHandles[i].Node) continue;
123 gaKernelHandles[i].Node = Node;
124 gaKernelHandles[i].Position = 0;
125 gaKernelHandles[i].Mode = Mode;
126 return i|VFS_KERNEL_FLAG;
133 void VFS_ReferenceUserHandles(void)
136 int max_handles = *Threads_GetMaxFD();
138 // Check if this process has any handles
139 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
142 for( i = 0; i < max_handles; i ++ )
145 h = &gaUserHandles[i];
148 _ReferenceNode(h->Node);
149 h->Mount->OpenHandleCount ++;
153 void VFS_CloseAllUserHandles(void)
156 int max_handles = *Threads_GetMaxFD();
158 // Check if this process has any handles
159 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
162 for( i = 0; i < max_handles; i ++ )
165 h = &gaUserHandles[i];
173 * \brief Take a backup of a set of file descriptors
175 void *VFS_SaveHandles(int NumFDs, int *FDs)
179 int max_handles = *Threads_GetMaxFD();
181 // Check if this process has any handles
182 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
186 ret = malloc( NumFDs * sizeof(tVFS_Handle) );
190 if( NumFDs > max_handles )
191 NumFDs = max_handles;
193 // Take copies of the handles
194 for( i = 0; i < NumFDs; i ++ )
198 h = &gaUserHandles[i];
199 else if( FDs[i] == -1 )
201 Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (-1), ignorning", i);
202 memset(&ret[i], 0, sizeof(tVFS_Handle));
207 h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1));
209 Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i",
210 FDs[i] & (VFS_KERNEL_FLAG - 1) );
215 memcpy( &ret[i], h, sizeof(tVFS_Handle) );
220 _ReferenceNode(h->Node);
221 h->Mount->OpenHandleCount ++;
227 void VFS_RestoreHandles(int NumFDs, void *Handles)
229 tVFS_Handle *handles = Handles;
232 // NULL = nothing to do
236 // Check if there is already a set of handles
237 if( MM_GetPhysAddr( gaUserHandles ) != 0 )
241 // Allocate user handle area
244 int max_handles = *Threads_GetMaxFD();
245 size = max_handles * sizeof(tVFS_Handle);
246 for(addr = 0; addr < size; addr += 0x1000)
248 if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
250 Warning("OOM - VFS_AllocHandle");
251 Threads_Exit(0, 0xFF); // Terminate user
254 memset( gaUserHandles, 0, size );
258 memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) );
259 // Reference when copied
260 for( i = 0; i < NumFDs; i ++ )
262 tVFS_Handle *h = &handles[i];
266 _ReferenceNode(h->Node);
267 h->Mount->OpenHandleCount ++;
271 void VFS_FreeSavedHandles(int NumFDs, void *Handles)
273 tVFS_Handle *handles = Handles;
276 // NULL = nothing to do
280 // Dereference all saved nodes
281 for( i = 0; i < NumFDs; i ++ )
283 tVFS_Handle *h = &handles[i];
289 ASSERT(h->Mount->OpenHandleCount > 0);
290 LOG("dec. mntpt '%s' to %i", h->Mount->MountPoint, h->Mount->OpenHandleCount-1);
291 h->Mount->OpenHandleCount --;