3 * - Kernel Status Driver
12 #define VERSION ((0 << 8) | (1)) // 0.01
13 #define KERNEL_VERSION_STRING ("Acess2 " EXPAND_STR(KERNEL_VERSION) " build " EXPAND_STR(BUILD_NUM))
16 typedef struct sSysFS_Ent
18 struct sSysFS_Ent *Next;
19 struct sSysFS_Ent *ListNext;
20 struct sSysFS_Ent *Parent;
26 int SysFS_Install(char **Arguments);
27 int SysFS_IOCtl(tVFS_Node *Node, int Id, void *Data);
29 int SysFS_RegisterFile(char *Path, char *Data, int Length);
30 int SysFS_UpdateFile(int ID, char *Data, int Length);
31 int SysFS_RemoveFile(int ID);
33 char *SysFS_Comm_ReadDir(tVFS_Node *Node, int Id);
34 tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, char *Filename);
35 Uint64 SysFS_Comm_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
36 void SysFS_Comm_CloseFile(tVFS_Node *Node);
39 extern tSysFS_Ent gSysFS_Version; // Defined Later
40 extern tSysFS_Ent gSysFS_Root; // Defined Later
41 MODULE_DEFINE(0, VERSION, SysFS, SysFS_Install, NULL, NULL);
42 tSysFS_Ent gSysFS_Version_Kernel = {
44 &gSysFS_Version, // Parent
47 .Inode = 1, // File #1
48 .ImplPtr = KERNEL_VERSION_STRING,
49 .ImplInt = (Uint)&gSysFS_Version_Kernel, // Self-Link
50 .Size = sizeof(KERNEL_VERSION_STRING)-1,
52 .ACLs = &gVFS_ACL_EveryoneRO,
53 .Read = SysFS_Comm_ReadFile
56 tSysFS_Ent gSysFS_Version = {
62 .ImplPtr = &gSysFS_Version_Kernel,
63 .ImplInt = (Uint)&gSysFS_Version, // Self-Link
65 .ACLs = &gVFS_ACL_EveryoneRX,
66 .Flags = VFS_FFLAG_DIRECTORY,
67 .ReadDir = SysFS_Comm_ReadDir,
68 .FindDir = SysFS_Comm_FindDir
71 // Root of the SysFS tree (just used for clean code)
72 tSysFS_Ent gSysFS_Root = {
78 .ImplPtr = &gSysFS_Version,
79 .ImplInt = (Uint)&gSysFS_Root // Self-Link
81 // .ACLs = &gVFS_ACL_EveryoneRX,
82 // .Flags = VFS_FFLAG_DIRECTORY,
83 // .ReadDir = SysFS_Comm_ReadDir,
84 // .FindDir = SysFS_Comm_FindDir
87 tDevFS_Driver gSysFS_DriverInfo = {
91 .ACLs = &gVFS_ACL_EveryoneRX,
92 .Flags = VFS_FFLAG_DIRECTORY,
93 .ImplPtr = &gSysFS_Version,
94 .Size = sizeof(gSysFS_Root)/sizeof(tSysFS_Ent),
95 .ReadDir = SysFS_Comm_ReadDir,
96 .FindDir = SysFS_Comm_FindDir,
100 int giSysFS_NextFileID = 2;
101 tSysFS_Ent *gSysFS_FileList;
105 * \fn int SysFS_Install(char **Options)
106 * \brief Installs the SysFS Driver
108 int SysFS_Install(char **Options)
110 DevFS_AddDevice( &gSysFS_DriverInfo );
111 return MODULE_INIT_SUCCESS;
115 * \fn int SysFS_RegisterFile(char *Path, char *Data, int Length)
116 * \brief Registers a file (buffer) for the user to be able to read from
117 * \param Path Path for the file to be accessable from (relative to SysFS root)
118 * \param Data Pointer to the data buffer (must be non-volatile)
119 * \param Length Length of the data buffer
120 * \return The file's identifier
122 int SysFS_RegisterFile(char *Path, char *Data, int Length)
126 tSysFS_Ent *ent = NULL;
127 tSysFS_Ent *child, *prev;
129 // Find parent directory
130 while( (tmp = strpos(&Path[start], '/')) != -1 )
135 child = ent->Node.ImplPtr;
137 child = gSysFS_DriverInfo.RootNode.ImplPtr;
138 for( ; child; prev = child, child = child->Next )
140 if( strncmp( &Path[start], child->Name, tmp+1 ) == '/' )
144 // Need a new directory?
147 child = calloc( 1, sizeof(tSysFS_Ent) );
149 child->Name = malloc(tmp+1);
150 memcpy(child->Name, &Path[start], tmp);
151 child->Name[tmp] = '\0';
153 child->Node.Inode = 0;
154 child->Node.ImplPtr = NULL;
155 child->Node.ImplInt = (Uint)child; // Uplink
156 child->Node.NumACLs = 1;
157 child->Node.ACLs = &gVFS_ACL_EveryoneRX;
158 child->Node.Flags = VFS_FFLAG_DIRECTORY;
159 child->Node.ReadDir = SysFS_Comm_ReadDir;
160 child->Node.FindDir = SysFS_Comm_FindDir;
163 ent->Node.ImplPtr = child;
165 // gSysFS_DriverInfo.RootNode.ImplPtr = child;
166 // ^^^ Impossible (There is already /Version)
173 gSysFS_DriverInfo.RootNode.Size ++;
174 Log("[SYSFS] Added directory '%s'", child->Name);
182 // ent: Parent tSysFS_Ent or NULL
183 // start: beginning of last path element
185 // Check if the name is taken
188 child = ent->Node.ImplPtr;
190 child = gSysFS_DriverInfo.RootNode.ImplPtr;
191 for( child = ent->Node.ImplPtr; child; prev = child, child = child->Next )
193 if( strcmp( &Path[start], child->Name ) == 0 )
197 Warning("[SYSFS] '%s' is taken (in '%s')\n", &Path[start], Path);
202 child = calloc( 1, sizeof(tSysFS_Ent) );
204 child->Name = strdup(&Path[start]);
207 child->Node.Inode = giSysFS_NextFileID++;
208 child->Node.ImplPtr = Data;
209 child->Node.ImplInt = (Uint)child; // Uplink
210 child->Node.Size = Length;
211 child->Node.NumACLs = 1;
212 child->Node.ACLs = &gVFS_ACL_EveryoneRO;
213 child->Node.Read = SysFS_Comm_ReadFile;
214 child->Node.Close = SysFS_Comm_CloseFile;
216 // Add to parent's child list
219 child->Next = ent->Node.ImplPtr;
220 ent->Node.ImplPtr = child;
223 gSysFS_DriverInfo.RootNode.Size ++;
224 child->Next = gSysFS_DriverInfo.RootNode.ImplPtr;
225 gSysFS_DriverInfo.RootNode.ImplPtr = child;
227 // Add to global file list
228 child->ListNext = gSysFS_FileList;
229 gSysFS_FileList = child;
231 Log("[SYSFS] Added '%s' (%p)", Path, Data);
233 return child->Node.Inode;
237 * \fn int SysFS_UpdateFile(int ID, char *Data, int Length)
238 * \brief Updates a file
239 * \param ID Identifier returned by ::SysFS_RegisterFile
240 * \param Data Pointer to the data buffer
241 * \param Length Length of the data buffer
242 * \return Boolean Success
244 int SysFS_UpdateFile(int ID, char *Data, int Length)
248 for( ent = gSysFS_FileList; ent; ent = ent->Next )
250 // It's a reverse sorted list
251 if(ent->Node.Inode < ID) return 0;
252 if(ent->Node.Inode == ID)
254 ent->Node.ImplPtr = Data;
255 ent->Node.Size = Length;
264 * \fn int SysFS_RemoveFile(int ID)
265 * \brief Removes a file from user access
266 * \param ID Identifier returned by ::SysFS_RegisterFile
267 * \return Boolean Success
268 * \note If a handle is still open to the file, it will be invalidated
270 int SysFS_RemoveFile(int ID)
273 tSysFS_Ent *ent, *parent, *prev;
276 for( ent = gSysFS_FileList; ent; prev = ent, ent = ent->Next )
278 // It's a reverse sorted list
279 if(ent->Node.Inode < ID) return 0;
280 if(ent->Node.Inode == ID) break;
285 // Set up for next part
287 parent = file->Parent;
289 // Remove from file list
290 prev->ListNext = file->ListNext;
292 file->Node.ImplPtr = NULL;
294 // Search parent directory
295 for( ent = parent->Node.ImplPtr; ent; prev = ent, ent = ent->Next )
297 if( ent == file ) break;
300 Warning("[SYSFS] Bookkeeping Error: File in list, but not in directory");
304 // Remove from parent directory
305 prev->Next = ent->Next;
307 // Free if not in use
308 if(file->Node.ReferenceCount == 0)
315 * \fn char *SysFS_Comm_ReadDir(tVFS_Node *Node, int Pos)
316 * \brief Reads from a SysFS directory
318 char *SysFS_Comm_ReadDir(tVFS_Node *Node, int Pos)
320 tSysFS_Ent *child = (tSysFS_Ent*)Node->ImplPtr;
321 if(Pos < 0 || Pos >= Node->Size) return NULL;
323 for( ; child; child = child->Next, Pos-- )
325 if( Pos == 0 ) return strdup(child->Name);
331 * \fn tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, char *Filename)
332 * \brief Find a file in a SysFS directory
334 tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, char *Filename)
336 tSysFS_Ent *child = (tSysFS_Ent*)Node->ImplPtr;
338 for( ; child; child = child->Next )
340 if( strcmp(child->Name, Filename) == 0 )
348 * \fn Uint64 SysFS_Comm_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
349 * \brief Read from an exposed buffer
351 Uint64 SysFS_Comm_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
353 if( Offset > Node->Size ) return -1;
354 if( Length > Node->Size ) Length = Node->Size;
355 if( Offset + Length > Node->Size) Length = Node->Size - Offset;
358 memcpy(Buffer, (void*)((Uint)Node->ImplPtr+(Uint)Offset), Length);
366 * \fn void SysFS_Comm_CloseFile(tVFS_Node *Node)
367 * \brief Closes an open file
368 * \param Node Node to close
370 void SysFS_Comm_CloseFile(tVFS_Node *Node)
373 Node->ReferenceCount --;
374 if( Node->ReferenceCount > 0 ) return;
376 // Check if it is still valid
377 if( Node->ImplPtr ) return;
380 free( (void*)Node->ImplInt );