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

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