10 #define DEFAULT_RING_SIZE 2048
14 typedef struct sPipe {
27 int FIFO_Install(char **Arguments);
28 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data);
29 char *FIFO_ReadDir(tVFS_Node *Node, int Id);
30 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
31 int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
32 void FIFO_Close(tVFS_Node *Node);
33 int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName);
34 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
35 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
36 tPipe *FIFO_Int_NewPipe(int Size, const char *Name);
39 MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL);
40 tDevFS_Driver gFIFO_DriverInfo = {
45 .ACLs = &gVFS_ACL_EveryoneRW,
46 .Flags = VFS_FFLAG_DIRECTORY,
47 .ReadDir = FIFO_ReadDir,
48 .FindDir = FIFO_FindDir,
50 .Relink = FIFO_Relink,
54 tVFS_Node gFIFO_AnonNode = {
56 .ACLs = &gVFS_ACL_EveryoneRW,
58 tPipe *gFIFO_NamedPipes = NULL;
62 * \fn int FIFO_Install(char **Options)
63 * \brief Installs the FIFO Driver
65 int FIFO_Install(char **Options)
67 DevFS_AddDevice( &gFIFO_DriverInfo );
72 * \fn int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
74 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
80 * \fn char *FIFO_ReadDir(tVFS_Node *Node, int Id)
81 * \brief Reads from the FIFO root
83 char *FIFO_ReadDir(tVFS_Node *Node, int Id)
85 tPipe *tmp = gFIFO_NamedPipes;
87 // Entry 0 is Anon Pipes
88 if(Id == 0) return strdup("anon");
90 // Find the id'th node
91 while(--Id && tmp) tmp = tmp->Next;
92 // If node found, return it
93 if(tmp) return strdup(tmp->Name);
99 * \fn tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
100 * \brief Find a file in the FIFO root
101 * \note Creates an anon pipe if anon is requested
103 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
106 if(!Filename) return NULL;
109 if(Filename[0] == '\0') return NULL;
112 if(Filename[0] == 'a' && Filename[1] == 'n'
113 && Filename[2] == 'o' && Filename[3] == 'n'
114 && Filename[4] == '\0') {
115 tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
120 tmp = gFIFO_NamedPipes;
123 if(strcmp(tmp->Name, Filename) == 0)
131 * \fn int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
133 int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
139 * \fn void FIFO_Close(tVFS_Node *Node)
140 * \brief Close a FIFO end
142 void FIFO_Close(tVFS_Node *Node)
145 if(!Node->ImplPtr) return ;
147 Node->ReferenceCount --;
148 if(Node->ReferenceCount) return ;
150 pipe = Node->ImplPtr;
152 if(strcmp(pipe->Name, "anon") == 0) {
161 * \fn int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName)
162 * \brief Relink a file (Deletes named pipes)
164 int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName)
168 if(Node != &gFIFO_DriverInfo.RootNode) return 0;
171 if(strcmp(OldName, "anon")) return 0;
174 for(pipe = gFIFO_NamedPipes;
178 if(strcmp(pipe->Name, OldName) == 0)
183 // Relink a named pipe
186 for(tmp = gFIFO_NamedPipes;
190 if(strcmp(tmp->Name, NewName) == 0) return 0;
194 pipe->Name = malloc(strlen(NewName)+1);
195 strcpy(pipe->Name, NewName);
209 * \fn Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
210 * \brief Read from a fifo pipe
212 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
214 tPipe *pipe = Node->ImplPtr;
216 Uint remaining = Length;
222 // Wait for buffer to fill
223 if(pipe->Flags & PF_BLOCKING)
225 len = Semaphore_Wait( &pipe->Semaphore, remaining );
229 if(pipe->ReadPos == pipe->WritePos)
232 if(pipe->WritePos - pipe->ReadPos < remaining)
233 len = pipe->WritePos - pipe->ReadPos;
238 // Check if read overflows buffer
239 if(len > pipe->BufSize - pipe->ReadPos)
241 int ofs = pipe->BufSize - pipe->ReadPos;
242 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], ofs);
243 memcpy((Uint8*)Buffer + ofs, &pipe->Buffer, len-ofs);
247 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], len);
250 // Increment read position
251 pipe->ReadPos += len;
252 pipe->ReadPos %= pipe->BufSize;
254 // Decrement Remaining Bytes
256 // Increment Buffer address
257 Buffer = (Uint8*)Buffer + len;
265 * \fn Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
266 * \brief Write to a fifo pipe
268 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
270 tPipe *pipe = Node->ImplPtr;
272 Uint remaining = Length;
278 // Wait for buffer to empty
279 if(pipe->Flags & PF_BLOCKING) {
280 len = Semaphore_Signal( &pipe->Semaphore, remaining );
284 if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
287 if(pipe->ReadPos - pipe->WritePos < remaining)
288 len = pipe->ReadPos - pipe->WritePos;
293 // Check if write overflows buffer
294 if(len > pipe->BufSize - pipe->WritePos)
296 int ofs = pipe->BufSize - pipe->WritePos;
297 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
298 memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
302 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
305 // Increment read position
306 pipe->WritePos += len;
307 pipe->WritePos %= pipe->BufSize;
309 // Decrement Remaining Bytes
311 // Increment Buffer address
312 Buffer = (Uint8*)Buffer + len;
320 * \fn tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
321 * \brief Create a new pipe
323 tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
326 int namelen = strlen(Name) + 1;
327 int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
329 ret = malloc(allocsize);
330 if(!ret) return NULL;
333 memset(ret, 0, allocsize);
334 ret->Flags = PF_BLOCKING;
338 ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
340 // Set name (and FIFO name)
341 ret->Name = ret->Buffer + Size;
342 strcpy(ret->Name, Name);
343 // - Start empty, max of `Size`
344 Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
348 ret->Node.ImplPtr = ret;
349 ret->Node.UID = Threads_GetUID();
350 ret->Node.GID = Threads_GetGID();
351 ret->Node.NumACLs = 1;
352 ret->Node.ACLs = (void*)( (Uint)ret + sizeof(tPipe) );
353 ret->Node.ACLs->Group = 0;
354 ret->Node.ACLs->ID = ret->Node.UID;
355 ret->Node.ACLs->Inv = 0;
356 ret->Node.ACLs->Perms = -1;
359 = ret->Node.ATime = now();
360 ret->Node.Read = FIFO_Read;
361 ret->Node.Write = FIFO_Write;
362 ret->Node.Close = FIFO_Close;