AcessNative - Updates for recent changes
[tpg/acess2.git] / AcessNative / acesskernel_src / nativefs.c
1 /*\r
2  * Acess2 Native Kernel\r
3  * - Acess kernel emulation on another OS using SDL and UDP\r
4  *\r
5  * nativefs.c\r
6  * - Host filesystem access\r
7  */\r
8 #define DEBUG   0\r
9 #define off_t   _acess_off_t\r
10 #define sprintf _acess_sprintf\r
11 #include <acess.h>      // Acess\r
12 #include <vfs.h>        // Acess\r
13 #undef off_t\r
14 #undef sprintf\r
15 #include <dirent.h>     // Posix\r
16 #include <sys/stat.h>   // Posix\r
17 #include <stdio.h>      // Posix\r
18 \r
19 //NOTES:\r
20 // tVFS_Node->ImplPtr is a pointer to the filesystem flags (tNativeFS)\r
21 // tVFS_Node->Data is the path string (heap string)\r
22 // tVFS_Node->ImplInt is the path length\r
23 \r
24 // === STRUCTURES ===\r
25 typedef struct\r
26 {\r
27         void    *InodeHandle;\r
28          int    bReadOnly;\r
29 }       tNativeFS;\r
30 \r
31 // === PROTOTYPES ===\r
32  int    NativeFS_Install(char **Arguments);\r
33 tVFS_Node       *NativeFS_Mount(const char *Device, const char **Arguments);\r
34 void    NativeFS_Unmount(tVFS_Node *Node);\r
35 tVFS_Node       *NativeFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);\r
36  int    NativeFS_ReadDir(tVFS_Node *Node, int Position, char Dest[FILENAME_MAX]);\r
37 size_t  NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void *Buffer, Uint Flags);\r
38 size_t  NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer, Uint Flags);\r
39 void    NativeFS_Close(tVFS_Node *Node);\r
40 \r
41 // === GLOBALS ===\r
42 tVFS_NodeType   gNativeFS_FileNodeType = {\r
43         .Read = NativeFS_Read,\r
44         .Write = NativeFS_Write,\r
45         .Close = NativeFS_Close\r
46 };\r
47 tVFS_NodeType   gNativeFS_DirNodeType = {\r
48         .FindDir = NativeFS_FindDir,\r
49         .ReadDir = NativeFS_ReadDir,\r
50         .Close = NativeFS_Close\r
51 };\r
52 tVFS_Driver     gNativeFS_Driver = {\r
53         .Name = "nativefs",\r
54         .InitDevice = NativeFS_Mount,\r
55         .Unmount = NativeFS_Unmount\r
56 };\r
57 \r
58 // === CODE ===\r
59 int NativeFS_Install(char **Arguments)\r
60 {\r
61         VFS_AddDriver(&gNativeFS_Driver);\r
62         return 0;\r
63 }\r
64 \r
65 tVFS_Node *NativeFS_Mount(const char *Device, const char **Arguments)\r
66 {\r
67         tVFS_Node       *ret;\r
68         tNativeFS       *info;\r
69         DIR     *dp;\r
70         \r
71         dp = opendir(Device);\r
72         if(!dp) {\r
73                 Log_Warning("NativeFS", "ERROR: Unable to open device root '%s'", Device);\r
74                 return NULL;\r
75         }\r
76         \r
77         // Check if directory exists\r
78         // Parse flags from arguments\r
79         info = malloc(sizeof(tNativeFS));\r
80         info->InodeHandle = Inode_GetHandle(NULL);\r
81         info->bReadOnly = 0;\r
82         // Create node\r
83         ret = malloc(sizeof(tVFS_Node));\r
84         memset(ret, 0, sizeof(tVFS_Node));\r
85         ret->Data = strdup(Device);\r
86         ret->ImplInt = strlen(ret->Data);\r
87         ret->ImplPtr = info;\r
88         ret->Inode = (Uint64)(tVAddr)dp;\r
89         ret->Flags = VFS_FFLAG_DIRECTORY;\r
90 \r
91         ret->Type = &gNativeFS_DirNodeType;     \r
92 \r
93         return ret;\r
94 }\r
95 \r
96 void NativeFS_Unmount(tVFS_Node *Node)\r
97 {\r
98         tNativeFS       *info = Node->ImplPtr;\r
99         Inode_ClearCache( info->InodeHandle );\r
100         closedir( (void *)(tVAddr)Node->Inode );\r
101         free(Node->Data);\r
102         free(Node);\r
103         free(info);\r
104 }\r
105 \r
106 void NativeFS_Close(tVFS_Node *Node)\r
107 {\r
108         tNativeFS       *info = Node->ImplPtr;\r
109         DIR     *dp = (Node->Flags & VFS_FFLAG_DIRECTORY) ? (DIR*)(tVAddr)Node->Inode : 0;\r
110         FILE    *fp = (Node->Flags & VFS_FFLAG_DIRECTORY) ? 0 : (FILE*)(tVAddr)Node->Inode;\r
111         \r
112         if( Inode_UncacheNode( info->InodeHandle, Node->Inode ) == 1 ) {\r
113                 if(dp)  closedir(dp);\r
114                 if(fp)  fclose(fp);\r
115         }\r
116 }\r
117 \r
118 tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)\r
119 {\r
120         char    *path;\r
121         tNativeFS       *info = Node->ImplPtr;\r
122         tVFS_Node       baseRet;\r
123         struct stat statbuf;\r
124 \r
125         ENTER("pNode sName", Node, Name);\r
126         \r
127         // Create path\r
128         path = malloc(Node->ImplInt + 1 + strlen(Name) + 1);\r
129         strcpy(path, Node->Data);\r
130         path[Node->ImplInt] = '/';\r
131         strcpy(path + Node->ImplInt + 1, Name);\r
132         \r
133         LOG("path = '%s'", path);\r
134         \r
135         // Check if file exists\r
136         if( stat(path, &statbuf) ) {\r
137                 free(path);\r
138                 LOG("Doesn't exist");\r
139                 LEAVE('n');\r
140                 return NULL;\r
141         }\r
142         \r
143         memset(&baseRet, 0, sizeof(tVFS_Node));\r
144         \r
145         // Check file type\r
146         if( S_ISDIR(statbuf.st_mode) )\r
147         {\r
148                 LOG("Directory");\r
149                 baseRet.Inode = (Uint64)(tVAddr) opendir(path);\r
150                 baseRet.Type = &gNativeFS_DirNodeType;\r
151                 baseRet.Flags |= VFS_FFLAG_DIRECTORY;\r
152                 baseRet.Size = -1;\r
153         }\r
154         else\r
155         {\r
156                 LOG("File");\r
157                 FILE    *fp = fopen(path, "r+");\r
158                 if( !fp ) {\r
159                         Log_Error("NativeFS", "fopen of '%s' failed: %s", path, strerror(errno));\r
160                         free(path);\r
161                         LEAVE('n');\r
162                         return NULL;\r
163                 }\r
164                 baseRet.Inode = (Uint64)(tVAddr) fp;\r
165                 baseRet.Type = &gNativeFS_FileNodeType;\r
166                 \r
167                 fseek( fp, 0, SEEK_END );\r
168                 baseRet.Size = ftell( fp );\r
169         }\r
170         \r
171         // Create new node\r
172         baseRet.ImplPtr = info;\r
173         baseRet.ImplInt = strlen(path);\r
174         baseRet.Data = path;\r
175         \r
176         LEAVE('-');\r
177         return Inode_CacheNode(info->InodeHandle, &baseRet);\r
178 }\r
179 \r
180 int NativeFS_ReadDir(tVFS_Node *Node, int Position, char Dest[FILENAME_MAX])\r
181 {\r
182         struct dirent   *ent;\r
183         DIR     *dp = (void*)(tVAddr)Node->Inode;\r
184 \r
185         ENTER("pNode iPosition", Node, Position);\r
186 \r
187         // TODO: Keep track of current position in the directory\r
188         // TODO: Lock node during this\r
189         rewinddir(dp);\r
190         do {\r
191                 ent = readdir(dp);\r
192         } while(Position-- && ent);\r
193 \r
194         if( !ent ) {\r
195                 LEAVE('i', -ENOENT);\r
196                 return -ENOENT;\r
197         }\r
198         \r
199         strncpy(Dest, ent->d_name, FILENAME_MAX);\r
200 \r
201         // TODO: Unlock node    \r
202 \r
203         LEAVE('i', 0);\r
204         return 0;\r
205 }\r
206 \r
207 size_t NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void *Buffer, Uint Flags)\r
208 {\r
209         ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);\r
210         if( fseek( (FILE *)(tVAddr)Node->Inode, Offset, SEEK_SET ) != 0 )\r
211         {\r
212                 LEAVE('i', 0);\r
213                 return 0;\r
214         }\r
215         size_t ret = fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );\r
216         LEAVE('x', ret);\r
217         return ret;\r
218 }\r
219 \r
220 size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer, Uint Flags)\r
221 {\r
222         FILE    *fp = (FILE *)(tVAddr)Node->Inode;\r
223         ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);\r
224         if( fseek( fp, Offset, SEEK_SET ) != 0 )\r
225         {\r
226                 LEAVE('i', 0);\r
227                 return 0;\r
228         }\r
229         size_t ret = fwrite( Buffer, 1, Length, fp );\r
230         fflush( fp );\r
231         LEAVE('i', ret);\r
232         return ret;\r
233 \r
234 }\r

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