AcessNative - Fixing for recent kernel 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   1\r
9 #include <acess.h>      // Acess\r
10 #include <vfs.h>        // Acess\r
11 #include <dirent.h>     // Posix\r
12 #include <sys/stat.h>   // Posix\r
13 #include <stdio.h>      // Posix\r
14 \r
15 //NOTES:\r
16 // tVFS_Node->ImplPtr is a pointer to the filesystem flags (tNativeFS)\r
17 // tVFS_Node->Data is the path string (heap string)\r
18 // tVFS_Node->ImplInt is the path length\r
19 \r
20 // === STRUCTURES ===\r
21 typedef struct\r
22 {\r
23          int    InodeHandle;\r
24          int    bReadOnly;\r
25 }       tNativeFS;\r
26 \r
27 // === PROTOTYPES ===\r
28  int    NativeFS_Install(char **Arguments);\r
29 tVFS_Node       *NativeFS_Mount(const char *Device, const char **Arguments);\r
30 void    NativeFS_Unmount(tVFS_Node *Node);\r
31 tVFS_Node       *NativeFS_FindDir(tVFS_Node *Node, const char *Name);\r
32 char    *NativeFS_ReadDir(tVFS_Node *Node, int Position);\r
33 Uint64  NativeFS_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
34 \r
35 // === GLOBALS ===\r
36 tVFS_NodeType   gNativeFS_FileNodeType = {\r
37         .Read = NativeFS_Read\r
38 };\r
39 tVFS_NodeType   gNativeFS_DirNodeType = {\r
40         .FindDir = NativeFS_FindDir,\r
41         .ReadDir = NativeFS_ReadDir,\r
42 };\r
43 tVFS_Driver     gNativeFS_Driver = {\r
44         "nativefs", 0,\r
45         NativeFS_Mount, NativeFS_Unmount,\r
46         NULL,\r
47 };\r
48 \r
49 // === CODE ===\r
50 int NativeFS_Install(char **Arguments)\r
51 {\r
52         VFS_AddDriver(&gNativeFS_Driver);\r
53         return 0;\r
54 }\r
55 \r
56 tVFS_Node *NativeFS_Mount(const char *Device, const char **Arguments)\r
57 {\r
58         tVFS_Node       *ret;\r
59         tNativeFS       *info;\r
60         DIR     *dp;\r
61         \r
62         dp = opendir(Device);\r
63         if(!dp) {\r
64                 Log_Warning("NativeFS", "ERRO: Unable to open device root '%s'", Device);\r
65                 return NULL;\r
66         }\r
67         \r
68         // Check if directory exists\r
69         // Parse flags from arguments\r
70         info = malloc(sizeof(tNativeFS));\r
71         info->InodeHandle = Inode_GetHandle();\r
72         info->bReadOnly = 0;\r
73         // Create node\r
74         ret = malloc(sizeof(tVFS_Node));\r
75         memset(ret, 0, sizeof(tVFS_Node));\r
76         ret->Data = strdup(Device);\r
77         ret->ImplInt = strlen(ret->Data);\r
78         ret->ImplPtr = info;\r
79         ret->Inode = (Uint64)dp;\r
80 \r
81         ret->Type = &gNativeFS_DirNodeType;     \r
82         \r
83         return ret;\r
84 }\r
85 \r
86 void NativeFS_Unmount(tVFS_Node *Node)\r
87 {\r
88         tNativeFS       *info = Node->ImplPtr;\r
89         Inode_ClearCache( info->InodeHandle );\r
90         closedir( (void *)Node->Inode );\r
91         free(Node->Data);\r
92         free(Node);\r
93         free(info);\r
94 }\r
95 \r
96 void NativeFS_Close(tVFS_Node *Node)\r
97 {\r
98         tNativeFS       *info = Node->ImplPtr;\r
99         Inode_UncacheNode( info->InodeHandle, Node->Inode );\r
100 }\r
101 \r
102 tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name)\r
103 {\r
104         char    *path = malloc(Node->ImplInt + 1 + strlen(Name) + 1);\r
105         tNativeFS       *info = Node->ImplPtr;\r
106         tVFS_Node       baseRet;\r
107         struct stat statbuf;\r
108 \r
109         ENTER("pNode sName", Node, Name);\r
110         \r
111         // Create path\r
112         strcpy(path, Node->Data);\r
113         path[Node->ImplInt] = '/';\r
114         strcpy(path + Node->ImplInt + 1, Name);\r
115         \r
116         LOG("path = '%s'", path);\r
117         \r
118         // Check if file exists\r
119         if( stat(path, &statbuf) ) {\r
120                 free(path);\r
121                 LOG("Doesn't exist");\r
122                 LEAVE('n');\r
123                 return NULL;\r
124         }\r
125         \r
126         memset(&baseRet, 0, sizeof(tVFS_Node));\r
127         \r
128         // Check file type\r
129         if( S_ISDIR(statbuf.st_mode) )\r
130         {\r
131                 LOG("Directory");\r
132                 baseRet.Inode = (Uint64) opendir(path);\r
133                 baseRet.Type = &gNativeFS_DirNodeType;\r
134                 baseRet.Flags |= VFS_FFLAG_DIRECTORY;\r
135                 baseRet.Size = -1;\r
136         }\r
137         else\r
138         {\r
139                 LOG("File");\r
140                 baseRet.Inode = (Uint64) fopen(path, "r+");\r
141                 baseRet.Type = &gNativeFS_FileNodeType;\r
142                 \r
143                 fseek( (FILE*)(tVAddr)baseRet.Inode, 0, SEEK_END );\r
144                 baseRet.Size = ftell( (FILE*)(tVAddr)baseRet.Inode );\r
145         }\r
146         \r
147         // Create new node\r
148         baseRet.ImplPtr = info;\r
149         baseRet.ImplInt = strlen(path);\r
150         baseRet.Data = path;\r
151         \r
152         LEAVE('-');\r
153         return Inode_CacheNode(info->InodeHandle, &baseRet);\r
154 }\r
155 \r
156 char *NativeFS_ReadDir(tVFS_Node *Node, int Position)\r
157 {\r
158         struct dirent   *ent;\r
159         DIR     *dp = (void*)(tVAddr)Node->Inode;\r
160         char    *ret;\r
161 \r
162         ENTER("pNode iPosition", Node, Position);\r
163 \r
164         // TODO: Keep track of current position in the directory\r
165         // TODO: Lock node during this\r
166         rewinddir(dp);\r
167         do {\r
168                 ent = readdir(dp);\r
169         } while(Position-- && ent);\r
170 \r
171         if( !ent ) {\r
172                 LEAVE('n');\r
173                 return NULL;\r
174         }\r
175         \r
176         ret = strdup(ent->d_name);\r
177 \r
178         // TODO: Unlock node    \r
179 \r
180         LEAVE('s', ret);\r
181         return ret;\r
182 }\r
183 \r
184 Uint64 NativeFS_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
185 {\r
186         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
187         if( fseek( (void *)Node->Inode, Offset, SEEK_SET ) != 0 )\r
188         {\r
189                 LEAVE('i', 0);\r
190                 return 0;\r
191         }\r
192         LEAVE('-');\r
193         return fread( Buffer, 1, Length, (void *)Node->Inode );\r
194 }\r

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