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

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