AcessNative - Fixing Fixing Fixing
[tpg/acess2.git] / AcessNative / acesskernel_src / vfs_handle.c
1 /*
2  * Acess2 VFS
3  * - AllocHandle, GetHandle
4  */
5 #define DEBUG   0
6 #include <acess.h>
7 #include <vfs.h>
8 #include <vfs_int.h>
9 #include <vfs_ext.h>
10
11 // === CONSTANTS ===
12 #define MAX_KERNEL_FILES        128
13 #define MAX_USER_FILES  64
14
15 // === IMPORTS ===
16 extern int      Server_GetClientID(void);
17
18 // === PROTOTYPES ===
19 tVFS_Handle     *VFS_GetHandle(int FD);
20  int    VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode);
21
22 // === Types ===
23 typedef struct sUserHandles
24 {
25         struct sUserHandles     *Next;
26          int    PID;
27         tVFS_Handle     Handles[MAX_USER_FILES];
28 }       tUserHandles;
29
30 // === GLOBALS ===
31 tUserHandles    *gpUserHandles = NULL;
32 tVFS_Handle     gaKernelHandles[MAX_KERNEL_FILES];
33
34 // === CODE ===
35 tUserHandles *VFS_int_GetUserHandles(int PID, int bCreate)
36 {
37         tUserHandles    *ent, *prev = NULL;
38         for( ent = gpUserHandles; ent; prev = ent, ent = ent->Next ) {
39                 if( ent->PID == PID ) {
40                         if( bCreate )
41                                 Log_Warning("VFS", "Process %i already has a handle list", PID);
42                         return ent;
43                 }
44                 if( ent->PID > PID )    break;
45         }
46         
47         if(!bCreate)
48                 return NULL;
49         
50         ent = calloc( 1, sizeof(tUserHandles) );
51         ent->PID = PID;
52         if( prev ) {
53                 ent->Next = prev->Next;
54                 prev->Next = ent;
55         }
56         else {
57                 ent->Next = gpUserHandles;
58                 gpUserHandles = ent;
59         }
60         Log_Notice("VFS", "Created handle list for process %i", PID);
61         return ent;
62 }
63
64 /**
65  * \brief Clone the handle list of the current process into another
66  */
67 void VFS_CloneHandleList(int PID)
68 {
69         tUserHandles    *ent;
70         tUserHandles    *cur;
71          int    i;
72         
73         cur = VFS_int_GetUserHandles(Threads_GetPID(), 0);
74         if(!cur)        return ;        // Don't need to do anything if the current list is empty
75         
76         ent = VFS_int_GetUserHandles(PID, 1);
77         
78         memcpy(ent->Handles, cur->Handles, CFGINT(CFG_VFS_MAXFILES)*sizeof(tVFS_Handle));
79         
80         for( i = 0; i < CFGINT(CFG_VFS_MAXFILES); i ++ )
81         {
82                 if(!cur->Handles[i].Node)       continue;
83                 
84                 if(ent->Handles[i].Node->Reference)
85                         ent->Handles[i].Node->Reference(ent->Handles[i].Node);
86         }
87 }
88
89 /**
90  * \fn tVFS_Handle *VFS_GetHandle(int FD)
91  * \brief Gets a pointer to the handle information structure
92  */
93 tVFS_Handle *VFS_GetHandle(int FD)
94 {
95         tVFS_Handle     *h;
96         
97         //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
98         
99         if(FD < 0) {
100                 LOG("FD (%i) < 0, RETURN NULL", FD);
101                 return NULL;
102         }
103         
104         if(FD & VFS_KERNEL_FLAG) {
105                 FD &= (VFS_KERNEL_FLAG - 1);
106                 if(FD >= MAX_KERNEL_FILES) {
107                         LOG("FD (%i) > MAX_KERNEL_FILES (%i), RETURN NULL", FD, MAX_KERNEL_FILES);
108                         return NULL;
109                 }
110                 h = &gaKernelHandles[ FD ];
111         }
112         else
113         {
114                 tUserHandles    *ent;
115                  int    pid = Threads_GetPID();
116                 
117                 ent = VFS_int_GetUserHandles(pid, 0);
118                 if(!ent) {
119                         Log_Error("VFS", "Client %i does not have a handle list (>)", pid);
120                         return NULL;
121                 }
122                 
123                 if(FD >= CFGINT(CFG_VFS_MAXFILES)) {
124                         LOG("FD (%i) > Limit (%i), RETURN NULL", FD, CFGINT(CFG_VFS_MAXFILES));
125                         return NULL;
126                 }
127                 h = &ent->Handles[ FD ];
128                 LOG("FD (%i) -> %p (Mode:0x%x,Node:%p)", FD, h, h->Mode, h->Node);
129         }
130         
131         if(h->Node == NULL) {
132                 LOG("FD (%i) Unused", FD);
133                 return NULL;
134         }
135         //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
136         return h;
137 }
138
139 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
140 {
141          int    i;
142         
143         // Check for a user open
144         if(bIsUser)
145         {
146                 tUserHandles    *ent;
147                 // Find the PID's handle list
148                 ent = VFS_int_GetUserHandles(Threads_GetPID(), 1);
149                 // Get a handle
150                 for(i=0;i<CFGINT(CFG_VFS_MAXFILES);i++)
151                 {
152                         if(ent->Handles[i].Node)        continue;
153                         ent->Handles[i].Node = Node;
154                         ent->Handles[i].Position = 0;
155                         ent->Handles[i].Mode = Mode;
156                         return i;
157                 }
158         }
159         else
160         {
161                 // Get a handle
162                 for(i=0;i<MAX_KERNEL_FILES;i++)
163                 {
164                         if(gaKernelHandles[i].Node)     continue;
165                         gaKernelHandles[i].Node = Node;
166                         gaKernelHandles[i].Position = 0;
167                         gaKernelHandles[i].Mode = Mode;
168                         return i|VFS_KERNEL_FLAG;
169                 }
170         }
171         
172         return -1;
173 }

UCC git Repository :: git.ucc.asn.au