3 * - AllocHandle, GetHandle
13 #define MAX_KERNEL_FILES 128
14 #define MAX_USER_FILES 64
17 extern int Server_GetClientID(void);
20 tVFS_Handle *VFS_GetHandle(int FD);
21 int VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode);
24 typedef struct sUserHandles
26 struct sUserHandles *Next;
28 tVFS_Handle Handles[MAX_USER_FILES];
32 tUserHandles *gpUserHandles = NULL;
33 tVFS_Handle gaKernelHandles[MAX_KERNEL_FILES];
36 tUserHandles *VFS_int_GetUserHandles(int PID, int bCreate)
38 tUserHandles *ent, *prev = NULL;
39 for( ent = gpUserHandles; ent; prev = ent, ent = ent->Next ) {
40 if( ent->PID == PID ) {
42 // Log_Warning("VFS", "Process %i already has a handle list", PID);
43 LOG("Found list for %i", PID);
46 if( ent->PID > PID ) break;
50 LOG("Not creating for %i", PID);
54 ent = calloc( 1, sizeof(tUserHandles) );
57 ent->Next = prev->Next;
61 ent->Next = gpUserHandles;
64 LOG("Created handle list for process %i", PID);
69 * \brief Clone the handle list of the current process into another
71 void VFS_CloneHandleList(int PID)
74 const tUserHandles *cur;
77 cur = VFS_int_GetUserHandles(Threads_GetPID(), 0);
78 if(!cur) return ; // Don't need to do anything if the current list is empty
80 ent = VFS_int_GetUserHandles(PID, 1);
82 maxhandles = *Threads_GetMaxFD();
83 memcpy(ent->Handles, cur->Handles, maxhandles*sizeof(tVFS_Handle));
86 for( int i = 0; i < maxhandles; i ++ )
88 if(!ent->Handles[i].Node) continue;
90 if(ent->Handles[i].Node->Type->Reference)
91 ent->Handles[i].Node->Type->Reference(ent->Handles[i].Node);
95 void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[])
98 const tUserHandles *cur;
101 cur = VFS_int_GetUserHandles(Threads_GetPID(), 0);
102 if(!cur) return ; // Don't need to do anything if the current list is empty
104 ent = VFS_int_GetUserHandles(PID, 1);
106 LOG("Copying %i FDs from %i", nFD, PID);
108 maxhandles = *Threads_GetMaxFD();
109 if( nFD > maxhandles )
111 for( int i = 0; i < nFD; i ++ )
114 if( fd >= maxhandles ) {
115 ent->Handles[i].Node = NULL;
118 memcpy(&ent->Handles[i], &cur->Handles[fd], sizeof(tVFS_Handle));
120 for( int i = nFD; i < maxhandles; i ++ )
121 ent->Handles[i].Node = NULL;
124 for( int i = 0; i < maxhandles; i ++ )
126 if(!ent->Handles[i].Node) continue;
128 if(ent->Handles[i].Node->Type->Reference)
129 ent->Handles[i].Node->Type->Reference(ent->Handles[i].Node);
134 * \fn tVFS_Handle *VFS_GetHandle(int FD)
135 * \brief Gets a pointer to the handle information structure
137 tVFS_Handle *VFS_GetHandle(int FD)
141 //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
144 LOG("FD (%i) < 0, RETURN NULL", FD);
148 if(FD & VFS_KERNEL_FLAG) {
149 FD &= (VFS_KERNEL_FLAG - 1);
150 if(FD >= MAX_KERNEL_FILES) {
151 LOG("FD (%i) > MAX_KERNEL_FILES (%i), RETURN NULL", FD, MAX_KERNEL_FILES);
154 h = &gaKernelHandles[ FD ];
158 int pid = Threads_GetPID();
159 int maxhandles = *Threads_GetMaxFD();
161 tUserHandles *ent = VFS_int_GetUserHandles(pid, 0);
163 Log_Error("VFS", "Client %i does not have a handle list (>)", pid);
167 if(FD >= maxhandles) {
168 LOG("FD (%i) > Limit (%i), RETURN NULL", FD, maxhandles);
171 h = &ent->Handles[ FD ];
172 LOG("FD (%i) -> %p (Mode:0x%x,Node:%p)", FD, h, h->Mode, h->Node);
175 if(h->Node == NULL) {
176 LOG("FD (%i) Unused", FD);
179 //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
183 int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode)
186 if(FD < 0) return -1;
188 if( FD & VFS_KERNEL_FLAG ) {
189 FD &= (VFS_KERNEL_FLAG -1);
190 if( FD >= MAX_KERNEL_FILES ) return -1;
191 h = &gaKernelHandles[FD];
195 int pid = Threads_GetPID();
196 int maxhandles = *Threads_GetMaxFD();
198 ent = VFS_int_GetUserHandles(pid, 0);
200 Log_Error("VFS", "Client %i does not have a handle list (>)", pid);
204 if(FD >= maxhandles) {
205 LOG("FD (%i) > Limit (%i), RETURN NULL", FD, maxhandles);
208 h = &ent->Handles[ FD ];
216 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
218 // Check for a user open
222 int maxhandles = *Threads_GetMaxFD();
223 // Find the PID's handle list
224 ent = VFS_int_GetUserHandles(Threads_GetPID(), 1);
226 for( int i = 0; i < maxhandles; i ++ )
228 if(ent->Handles[i].Node) continue;
229 ent->Handles[i].Node = Node;
230 ent->Handles[i].Position = 0;
231 ent->Handles[i].Mode = Mode;
238 for(int i = 0; i < MAX_KERNEL_FILES; i ++)
240 if(gaKernelHandles[i].Node) continue;
241 gaKernelHandles[i].Node = Node;
242 gaKernelHandles[i].Position = 0;
243 gaKernelHandles[i].Mode = Mode;
244 return i|VFS_KERNEL_FLAG;
251 void VFS_ClearHandles(int PID)
253 // Find the PID's handle list
254 tUserHandles *ent = VFS_int_GetUserHandles(PID, 0);
257 int maxhandles = *Threads_GetMaxFD();
258 for( int i = 0; i < maxhandles; i ++ )
260 if(ent->Handles[i].Node) continue;
261 _CloseNode(ent->Handles[i].Node);
262 ent->Handles[i].Node = NULL;