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);
45 if( ent->PID > PID ) break;
51 ent = calloc( 1, sizeof(tUserHandles) );
54 ent->Next = prev->Next;
58 ent->Next = gpUserHandles;
61 Log_Notice("VFS", "Created handle list for process %i", PID);
66 * \brief Clone the handle list of the current process into another
68 void VFS_CloneHandleList(int PID)
74 cur = VFS_int_GetUserHandles(Threads_GetPID(), 0);
75 if(!cur) return ; // Don't need to do anything if the current list is empty
77 ent = VFS_int_GetUserHandles(PID, 1);
79 maxhandles = *Threads_GetMaxFD();
80 memcpy(ent->Handles, cur->Handles, maxhandles*sizeof(tVFS_Handle));
82 for( i = 0; i < maxhandles; i ++ )
84 if(!cur->Handles[i].Node) continue;
86 if(ent->Handles[i].Node->Type->Reference)
87 ent->Handles[i].Node->Type->Reference(ent->Handles[i].Node);
91 void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[])
97 cur = VFS_int_GetUserHandles(Threads_GetPID(), 0);
98 if(!cur) return ; // Don't need to do anything if the current list is empty
100 ent = VFS_int_GetUserHandles(PID, 1);
102 maxhandles = *Threads_GetMaxFD();
103 if( nFD > maxhandles )
105 for( i = 0; i < nFD; i ++ )
107 if( FDs[i] >= maxhandles ) {
108 ent->Handles[i].Node = NULL;
111 memcpy(&ent->Handles[i], &cur->Handles[ FDs[i] ], sizeof(tVFS_Handle));
113 for( ; i < maxhandles; i ++ )
114 cur->Handles[i].Node = NULL;
116 for( i = 0; i < maxhandles; i ++ )
118 if(!cur->Handles[i].Node) continue;
120 if(ent->Handles[i].Node->Type->Reference)
121 ent->Handles[i].Node->Type->Reference(ent->Handles[i].Node);
126 * \fn tVFS_Handle *VFS_GetHandle(int FD)
127 * \brief Gets a pointer to the handle information structure
129 tVFS_Handle *VFS_GetHandle(int FD)
133 //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
136 LOG("FD (%i) < 0, RETURN NULL", FD);
140 if(FD & VFS_KERNEL_FLAG) {
141 FD &= (VFS_KERNEL_FLAG - 1);
142 if(FD >= MAX_KERNEL_FILES) {
143 LOG("FD (%i) > MAX_KERNEL_FILES (%i), RETURN NULL", FD, MAX_KERNEL_FILES);
146 h = &gaKernelHandles[ FD ];
151 int pid = Threads_GetPID();
152 int maxhandles = *Threads_GetMaxFD();
154 ent = VFS_int_GetUserHandles(pid, 0);
156 Log_Error("VFS", "Client %i does not have a handle list (>)", pid);
160 if(FD >= maxhandles) {
161 LOG("FD (%i) > Limit (%i), RETURN NULL", FD, maxhandles);
164 h = &ent->Handles[ FD ];
165 LOG("FD (%i) -> %p (Mode:0x%x,Node:%p)", FD, h, h->Mode, h->Node);
168 if(h->Node == NULL) {
169 LOG("FD (%i) Unused", FD);
172 //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
176 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
180 // Check for a user open
184 int maxhandles = *Threads_GetMaxFD();
185 // Find the PID's handle list
186 ent = VFS_int_GetUserHandles(Threads_GetPID(), 1);
188 for( i = 0; i < maxhandles; i ++ )
190 if(ent->Handles[i].Node) continue;
191 ent->Handles[i].Node = Node;
192 ent->Handles[i].Position = 0;
193 ent->Handles[i].Mode = Mode;
200 for(i=0;i<MAX_KERNEL_FILES;i++)
202 if(gaKernelHandles[i].Node) continue;
203 gaKernelHandles[i].Node = Node;
204 gaKernelHandles[i].Position = 0;
205 gaKernelHandles[i].Mode = Mode;
206 return i|VFS_KERNEL_FLAG;