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 int VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode);
25 tVFS_Handle *gaUserHandles = (void*)MM_PPD_HANDLES;
26 tVFS_Handle *gaKernelHandles = (void*)MM_KERNEL_VFS;
29 inline void _ReferenceNode(tVFS_Node *Node)
31 if( !MM_GetPhysAddr(Node->Type) ) {
32 Log_Error("VFS", "Node %p's type is invalid (%p bad pointer) - %P corrupted",
33 Node, Node->Type, MM_GetPhysAddr(&Node->Type));
36 if( Node->Type && Node->Type->Reference )
37 Node->Type->Reference( Node );
39 Node->ReferenceCount ++;
43 * \fn tVFS_Handle *VFS_GetHandle(int FD)
44 * \brief Gets a pointer to the handle information structure
46 tVFS_Handle *VFS_GetHandle(int FD)
50 //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
52 if(FD < 0) return NULL;
54 if(FD & VFS_KERNEL_FLAG) {
55 FD &= (VFS_KERNEL_FLAG - 1);
56 if(FD >= MAX_KERNEL_FILES) return NULL;
57 h = &gaKernelHandles[ FD ];
59 if(FD >= *Threads_GetMaxFD()) return NULL;
60 h = &gaUserHandles[ FD ];
63 if(h->Node == NULL) return NULL;
64 //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
68 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
72 // Check for a user open
75 int max_handles = *Threads_GetMaxFD();
77 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
80 size = max_handles * sizeof(tVFS_Handle);
81 for(addr = 0; addr < size; addr += 0x1000)
83 if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
85 Warning("OOM - VFS_AllocHandle");
86 Threads_Exit(0, 0xFF); // Terminate user
89 memset( gaUserHandles, 0, size );
92 for( i = 0; i < max_handles; i ++ )
94 if(gaUserHandles[i].Node) continue;
95 gaUserHandles[i].Node = Node;
96 gaUserHandles[i].Position = 0;
97 gaUserHandles[i].Mode = Mode;
103 // Allocate space if not already
104 if( MM_GetPhysAddr( gaKernelHandles ) == 0 )
107 size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
108 for(addr = 0; addr < size; addr += 0x1000)
110 if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) )
112 Panic("OOM - VFS_AllocHandle");
113 Threads_Exit(0, 0xFF); // Terminate application (get some space back)
116 memset( gaKernelHandles, 0, size );
119 for(i=0;i<MAX_KERNEL_FILES;i++)
121 if(gaKernelHandles[i].Node) continue;
122 gaKernelHandles[i].Node = Node;
123 gaKernelHandles[i].Position = 0;
124 gaKernelHandles[i].Mode = Mode;
125 return i|VFS_KERNEL_FLAG;
132 void VFS_ReferenceUserHandles(void)
135 int max_handles = *Threads_GetMaxFD();
137 // Check if this process has any handles
138 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
141 for( i = 0; i < max_handles; i ++ )
144 h = &gaUserHandles[i];
147 _ReferenceNode(h->Node);
148 h->Mount->OpenHandleCount ++;
152 void VFS_CloseAllUserHandles(void)
155 int max_handles = *Threads_GetMaxFD();
157 // Check if this process has any handles
158 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
161 for( i = 0; i < max_handles; i ++ )
164 h = &gaUserHandles[i];
172 * \brief Take a backup of a set of file descriptors
174 void *VFS_SaveHandles(int NumFDs, int *FDs)
178 int max_handles = *Threads_GetMaxFD();
180 // Check if this process has any handles
181 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
185 ret = malloc( NumFDs * sizeof(tVFS_Handle) );
189 if( NumFDs > max_handles )
190 NumFDs = max_handles;
192 // Take copies of the handles
193 for( i = 0; i < NumFDs; i ++ )
197 h = &gaUserHandles[i];
199 h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1));
201 Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i",
202 FDs[i] & (VFS_KERNEL_FLAG - 1) );
207 memcpy( &ret[i], h, sizeof(tVFS_Handle) );
212 _ReferenceNode(h->Node);
213 h->Mount->OpenHandleCount ++;
219 void VFS_RestoreHandles(int NumFDs, void *Handles)
221 tVFS_Handle *handles = Handles;
224 // NULL = nothing to do
228 // Check if there is already a set of handles
229 if( MM_GetPhysAddr( gaUserHandles ) != 0 )
233 // Allocate user handle area
236 int max_handles = *Threads_GetMaxFD();
237 size = max_handles * sizeof(tVFS_Handle);
238 for(addr = 0; addr < size; addr += 0x1000)
240 if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
242 Warning("OOM - VFS_AllocHandle");
243 Threads_Exit(0, 0xFF); // Terminate user
246 memset( gaUserHandles, 0, size );
250 memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) );
251 // Reference when copied
252 for( i = 0; i < NumFDs; i ++ )
254 tVFS_Handle *h = &handles[i];
258 _ReferenceNode(h->Node);
259 h->Mount->OpenHandleCount ++;
263 void VFS_FreeSavedHandles(int NumFDs, void *Handles)
265 tVFS_Handle *handles = Handles;
268 // NULL = nothing to do
272 // Dereference all saved nodes
273 for( i = 0; i < NumFDs; i ++ )
275 tVFS_Handle *h = &handles[i];
281 ASSERT(h->Mount->OpenHandleCount > 0);
282 LOG("dec. mntpt '%s' to %i", h->Mount->MountPoint, h->Mount->OpenHandleCount-1);
283 h->Mount->OpenHandleCount --;