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

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