AcessNative - Now can use the `dir` CLIShell builtin
[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         }\r
131         else\r
132         {\r
133                 LOG("File");\r
134                 baseRet.Inode = (Uint64) fopen(path, "r+");\r
135                 baseRet.Read = NativeFS_Read;\r
136         }\r
137         \r
138         // Create new node\r
139         baseRet.ImplPtr = info;\r
140         baseRet.ImplInt = strlen(path);\r
141         baseRet.Data = path;\r
142         \r
143         LEAVE('-');\r
144         return Inode_CacheNode(info->InodeHandle, &baseRet);\r
145 }\r
146 \r
147 char *NativeFS_ReadDir(tVFS_Node *Node, int Position)\r
148 {\r
149         // Keep track of the current directory position\r
150         // TODO: Implement NativeFS_ReadDir\r
151         return NULL;\r
152 }\r
153 \r
154 Uint64 NativeFS_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
155 {\r
156         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
157         if( fseek( (void *)Node->Inode, Offset, SEEK_SET ) != 0 )\r
158         {\r
159                 LEAVE('i', 0);\r
160                 return 0;\r
161         }\r
162         LEAVE('-');\r
163         return fread( Buffer, 1, Length, (void *)Node->Inode );\r
164 }\r

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