DiskTool - Compiling again, now with modules
[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 #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 size_t  NativeFS_Read(tVFS_Node *Node, off_t Offset, size_t 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", "ERROR: 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)(tVAddr)dp;\r
82         ret->Flags = VFS_FFLAG_DIRECTORY;\r
83 \r
84         ret->Type = &gNativeFS_DirNodeType;     \r
85 \r
86         return ret;\r
87 }\r
88 \r
89 void NativeFS_Unmount(tVFS_Node *Node)\r
90 {\r
91         tNativeFS       *info = Node->ImplPtr;\r
92         Inode_ClearCache( info->InodeHandle );\r
93         closedir( (void *)(tVAddr)Node->Inode );\r
94         free(Node->Data);\r
95         free(Node);\r
96         free(info);\r
97 }\r
98 \r
99 void NativeFS_Close(tVFS_Node *Node)\r
100 {\r
101         tNativeFS       *info = Node->ImplPtr;\r
102         Inode_UncacheNode( info->InodeHandle, Node->Inode );\r
103 }\r
104 \r
105 tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name)\r
106 {\r
107         char    *path = malloc(Node->ImplInt + 1 + strlen(Name) + 1);\r
108         tNativeFS       *info = Node->ImplPtr;\r
109         tVFS_Node       baseRet;\r
110         struct stat statbuf;\r
111 \r
112         ENTER("pNode sName", Node, Name);\r
113         \r
114         // Create path\r
115         strcpy(path, Node->Data);\r
116         path[Node->ImplInt] = '/';\r
117         strcpy(path + Node->ImplInt + 1, Name);\r
118         \r
119         LOG("path = '%s'", path);\r
120         \r
121         // Check if file exists\r
122         if( stat(path, &statbuf) ) {\r
123                 free(path);\r
124                 LOG("Doesn't exist");\r
125                 LEAVE('n');\r
126                 return NULL;\r
127         }\r
128         \r
129         memset(&baseRet, 0, sizeof(tVFS_Node));\r
130         \r
131         // Check file type\r
132         if( S_ISDIR(statbuf.st_mode) )\r
133         {\r
134                 LOG("Directory");\r
135                 baseRet.Inode = (Uint64)(tVAddr) opendir(path);\r
136                 baseRet.Type = &gNativeFS_DirNodeType;\r
137                 baseRet.Flags |= VFS_FFLAG_DIRECTORY;\r
138                 baseRet.Size = -1;\r
139         }\r
140         else\r
141         {\r
142                 LOG("File");\r
143                 baseRet.Inode = (Uint64)(tVAddr) fopen(path, "r+");\r
144                 baseRet.Type = &gNativeFS_FileNodeType;\r
145                 \r
146                 fseek( (FILE*)(tVAddr)baseRet.Inode, 0, SEEK_END );\r
147                 baseRet.Size = ftell( (FILE*)(tVAddr)baseRet.Inode );\r
148         }\r
149         \r
150         // Create new node\r
151         baseRet.ImplPtr = info;\r
152         baseRet.ImplInt = strlen(path);\r
153         baseRet.Data = path;\r
154         \r
155         LEAVE('-');\r
156         return Inode_CacheNode(info->InodeHandle, &baseRet);\r
157 }\r
158 \r
159 char *NativeFS_ReadDir(tVFS_Node *Node, int Position)\r
160 {\r
161         struct dirent   *ent;\r
162         DIR     *dp = (void*)(tVAddr)Node->Inode;\r
163         char    *ret;\r
164 \r
165         ENTER("pNode iPosition", Node, Position);\r
166 \r
167         // TODO: Keep track of current position in the directory\r
168         // TODO: Lock node during this\r
169         rewinddir(dp);\r
170         do {\r
171                 ent = readdir(dp);\r
172         } while(Position-- && ent);\r
173 \r
174         if( !ent ) {\r
175                 LEAVE('n');\r
176                 return NULL;\r
177         }\r
178         \r
179         ret = strdup(ent->d_name);\r
180 \r
181         // TODO: Unlock node    \r
182 \r
183         LEAVE('s', ret);\r
184         return ret;\r
185 }\r
186 \r
187 size_t NativeFS_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)\r
188 {\r
189         ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);\r
190         if( fseek( (void *)(tVAddr)Node->Inode, Offset, SEEK_SET ) != 0 )\r
191         {\r
192                 LEAVE('i', 0);\r
193                 return 0;\r
194         }\r
195         LEAVE('-');\r
196         return fread( Buffer, 1, Length, (void *)(tVAddr)Node->Inode );\r
197 }\r

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