2 * Acess2 Native Kernel
\r
3 * - Acess kernel emulation on another OS using SDL and UDP
\r
6 * - Host filesystem access
\r
9 #define off_t _acess_off_t
\r
10 #define sprintf _acess_sprintf
\r
11 #include <acess.h> // Acess
\r
12 #include <vfs.h> // Acess
\r
15 #include <dirent.h> // Posix
\r
16 #include <sys/stat.h> // Posix
\r
17 #include <stdio.h> // C
\r
20 // tVFS_Node->ImplPtr is a pointer to the filesystem flags (tNativeFS)
\r
21 // tVFS_Node->Data is the path string (heap string)
\r
22 // tVFS_Node->ImplInt is the path length
\r
24 // === STRUCTURES ===
\r
31 // === PROTOTYPES ===
\r
32 int NativeFS_Install(char **Arguments);
\r
33 tVFS_Node *NativeFS_Mount(const char *Device, const char **Arguments);
\r
34 void NativeFS_Unmount(tVFS_Node *Node);
\r
35 tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
\r
36 int NativeFS_ReadDir(tVFS_Node *Node, int Position, char Dest[FILENAME_MAX]);
\r
37 tVFS_Node *NativeFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
\r
38 size_t NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void *Buffer, Uint Flags);
\r
39 size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer, Uint Flags);
\r
40 void NativeFS_Close(tVFS_Node *Node);
\r
43 tVFS_NodeType gNativeFS_FileNodeType = {
\r
44 .Read = NativeFS_Read,
\r
45 .Write = NativeFS_Write,
\r
46 .Close = NativeFS_Close
\r
48 tVFS_NodeType gNativeFS_DirNodeType = {
\r
49 .FindDir = NativeFS_FindDir,
\r
50 .ReadDir = NativeFS_ReadDir,
\r
51 .MkNod = NativeFS_MkNod,
\r
52 .Close = NativeFS_Close
\r
54 tVFS_Driver gNativeFS_Driver = {
\r
56 .InitDevice = NativeFS_Mount,
\r
57 .Unmount = NativeFS_Unmount
\r
61 int NativeFS_Install(char **Arguments)
\r
63 VFS_AddDriver(&gNativeFS_Driver);
\r
67 tVFS_Node *NativeFS_Mount(const char *Device, const char **Arguments)
\r
73 dp = opendir(Device);
\r
75 Log_Warning("NativeFS", "ERROR: Unable to open device root '%s'", Device);
\r
79 // Check if directory exists
\r
80 // Parse flags from arguments
\r
81 info = malloc(sizeof(tNativeFS));
\r
82 info->InodeHandle = Inode_GetHandle(NULL);
\r
83 info->bReadOnly = 0;
\r
85 ret = malloc(sizeof(tVFS_Node));
\r
86 memset(ret, 0, sizeof(tVFS_Node));
\r
87 ret->Data = strdup(Device);
\r
88 ret->ImplInt = strlen(ret->Data);
\r
89 ret->ImplPtr = info;
\r
90 ret->Inode = (Uint64)(tVAddr)dp;
\r
91 ret->Flags = VFS_FFLAG_DIRECTORY;
\r
93 ret->Type = &gNativeFS_DirNodeType;
\r
98 void NativeFS_Unmount(tVFS_Node *Node)
\r
100 tNativeFS *info = Node->ImplPtr;
\r
101 Inode_ClearCache( info->InodeHandle );
\r
102 closedir( (void *)(tVAddr)Node->Inode );
\r
108 void NativeFS_Close(tVFS_Node *Node)
\r
110 tNativeFS *info = Node->ImplPtr;
\r
111 DIR *dp = (Node->Flags & VFS_FFLAG_DIRECTORY) ? (DIR*)(tVAddr)Node->Inode : 0;
\r
112 FILE *fp = (Node->Flags & VFS_FFLAG_DIRECTORY) ? 0 : (FILE*)(tVAddr)Node->Inode;
\r
114 if( Inode_UncacheNode( info->InodeHandle, Node->Inode ) == 1 ) {
\r
115 if(dp) closedir(dp);
\r
120 tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
\r
123 tNativeFS *info = Node->ImplPtr;
\r
125 struct stat statbuf;
\r
127 ENTER("pNode sName", Node, Name);
\r
130 path = malloc(Node->ImplInt + 1 + strlen(Name) + 1);
\r
131 strcpy(path, Node->Data);
\r
132 path[Node->ImplInt] = '/';
\r
133 strcpy(path + Node->ImplInt + 1, Name);
\r
135 LOG("path = '%s'", path);
\r
137 // Check if file exists
\r
138 if( stat(path, &statbuf) ) {
\r
140 LOG("Doesn't exist");
\r
145 memset(&baseRet, 0, sizeof(tVFS_Node));
\r
148 if( S_ISDIR(statbuf.st_mode) )
\r
151 baseRet.Inode = (Uint64)(tVAddr) opendir(path);
\r
152 baseRet.Type = &gNativeFS_DirNodeType;
\r
153 baseRet.Flags |= VFS_FFLAG_DIRECTORY;
\r
159 FILE *fp = fopen(path, "r+");
\r
161 Log_Error("NativeFS", "fopen of '%s' failed: %s", path, strerror(errno));
\r
166 baseRet.Inode = (Uint64)(tVAddr) fp;
\r
167 baseRet.Type = &gNativeFS_FileNodeType;
\r
169 fseek( fp, 0, SEEK_END );
\r
170 baseRet.Size = ftell( fp );
\r
174 baseRet.ImplPtr = info;
\r
175 baseRet.ImplInt = strlen(path);
\r
176 baseRet.Data = path;
\r
179 return Inode_CacheNode(info->InodeHandle, &baseRet);
\r
182 int NativeFS_ReadDir(tVFS_Node *Node, int Position, char Dest[FILENAME_MAX])
\r
184 struct dirent *ent;
\r
185 DIR *dp = (void*)(tVAddr)Node->Inode;
\r
187 ENTER("pNode iPosition", Node, Position);
\r
189 // TODO: Keep track of current position in the directory
\r
190 // TODO: Lock node during this
\r
194 } while(Position-- && ent);
\r
197 LEAVE('i', -ENOENT);
\r
201 strncpy(Dest, ent->d_name, FILENAME_MAX);
\r
203 // TODO: Unlock node
\r
209 tVFS_Node *NativeFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
\r
211 char path[Node->ImplInt+1+strlen(Name)+1];
\r
212 sprintf(path, "%s/%s", Node->Data, Name);
\r
213 if( Flags & VFS_FFLAG_DIRECTORY )
\r
219 FILE *tmp = fopen(path, "w");
\r
220 if(!tmp) return NULL;
\r
223 return NativeFS_FindDir(Node, Name, 0);
\r
226 size_t NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void *Buffer, Uint Flags)
\r
228 ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
\r
229 if( fseek( (FILE *)(tVAddr)Node->Inode, Offset, SEEK_SET ) != 0 )
\r
234 size_t ret = fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );
\r
239 size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer, Uint Flags)
\r
241 FILE *fp = (FILE *)(tVAddr)Node->Inode;
\r
242 ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
\r
243 if( fseek( fp, Offset, SEEK_SET ) != 0 )
\r
248 size_t ret = fwrite( Buffer, 1, Length, fp );
\r