* arch/x86/time.c
*/
#include <acess.h>
+#include <timers.h>
// === MACROS ===
#define TIMER_QUANTUM 100
// === IMPORTS ===
extern void Threads_Dump(void);
-extern void Heap_Dump(void)
- ;
+extern void Heap_Dump(void);
extern void KernelPanic_SetMode(void);
extern void KernelPanic_PutChar(char Ch);
extern void IPStack_SendDebugText(const char *Text);
void Debug_FmtS(int bUseKTerm, const char *format, ...);
void Debug_Fmt(int bUseKTerm, const char *format, va_list args);
void Debug_SetKTerminal(const char *File);
-void LogFV(const char *Fmt, va_list args);
// === GLOBALS ===
int gDebug_Level = 0;
// - Root
tVFS_Node *IPCPipe_Root_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int IPCPipe_Root_ReadDir(tVFS_Node *Node, int ID, char Name[FILENAME_MAX]);
-tVFS_Node *IPCPipe_Root_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *IPCPipe_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
// - Server
int IPCPipe_Server_ReadDir(tVFS_Node *Node, int ID, char Name[FILENAME_MAX]);
-tVFS_Node *IPCPipe_Server_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *IPCPipe_Server_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
void IPCPipe_Server_Close(tVFS_Node *Node);
// - Socket
tIPCPipe_Channel *IPCPipe_int_GetEPs(tVFS_Node *Node, tIPCPipe_Endpoint **lep, tIPCPipe_Endpoint **rep);
-size_t IPCPipe_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Dest);
-size_t IPCPipe_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Src);
+size_t IPCPipe_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Dest, Uint Flags);
+size_t IPCPipe_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Src, Uint Flags);
void IPCPipe_Client_Close(tVFS_Node *Node);
// === GLOBALS ===
/**
* \return New client pointer
*/
-tVFS_Node *IPCPipe_Root_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPCPipe_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tIPCPipe_Server *srv;
ENTER("pNode sName", Node, Name);
return NULL;
}
+ if( Flags & VFS_FDIRFLAG_STAT ) {
+ // LEAVE('p', srv->TplClientNode);
+ // return &srv->TplClientNode;
+ }
+
// Create new client
- tIPCPipe_Channel *new_client;
-
+ tIPCPipe_Channel *new_client;
+
new_client = calloc(1, sizeof(tIPCPipe_Channel));
new_client->Server = srv;
new_client->ClientEP.Node.Type = &gIPCPipe_ChannelNodeType;
// 'next' is a valid entry, but readdir should never be called on this node
return -1;
}
-tVFS_Node *IPCPipe_Server_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPCPipe_Server_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tIPCPipe_Server *srv = Node->ImplPtr;
return NULL;
}
+ // TODO: Need VFS_FDIRFLAG_NOBLOCK?
VFS_SelectNode(Node, VFS_SELECT_READ, 0, "IPCPipe Server");
tIPCPipe_Channel *conn;
}
return ch;
}
-size_t IPCPipe_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Dest)
+size_t IPCPipe_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Dest, Uint Flags)
{
tIPCPipe_Endpoint *lep, *rep;
tIPCPipe_Channel *channel = IPCPipe_int_GetEPs(Node, &lep, &rep);
}
// Wait for a packet to be ready
- VFS_SelectNode(Node, VFS_SELECT_READ, 0, "IPCPipe Endpoint");
+ tTime timeout_z = 0, *timeout = ((Flags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL);
+ int rv = VFS_SelectNode(Node, VFS_SELECT_READ, timeout, "IPCPipe Endpoint");
+ if( !rv ) {
+ errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+ LEAVE('i', -1);
+ return -1;
+ }
if( channel->Server == NULL ) {
+ //errno = EIO;
LEAVE('i', -1);
return -1;
}
if( !rep->Node.ImplPtr )
{
Mutex_Release(&rep->lList);
+ //errno = EIO;
LEAVE('i', -1);
return -1;
}
return ret;
}
-size_t IPCPipe_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Src)
+size_t IPCPipe_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Src, Uint Flags)
{
tIPCPipe_Endpoint *lep, *rep;
tIPCPipe_Channel *channel = IPCPipe_int_GetEPs(Node, &lep, &rep);
return 0;
}
- // Create packet structure
+ // TODO: Ensure that no more than DEF_MAX_BYTE_LIMIT bytes are in flight at one time
+
+ // Create packet structure
tIPCPipe_Packet *pkt = malloc(sizeof(tIPCPipe_Packet)+Length);
pkt->Next = NULL;
pkt->Offset = 0;
int FIFO_Install(char **Arguments);
int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data);
int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
-tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
+tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags);
tVFS_Node *FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
void FIFO_Reference(tVFS_Node *Node);
void FIFO_Close(tVFS_Node *Node);
int FIFO_Unlink(tVFS_Node *Node, const char *OldName);
-size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
tPipe *FIFO_Int_NewPipe(int Size, const char *Name);
// === GLOBALS ===
* \brief Find a file in the FIFO root
* \note Creates an anon pipe if anon is requested
*/
-tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
+tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
{
tPipe *tmp;
if(!Filename) return NULL;
// Anon Pipe
if( strcmp(Filename, "anon") == 0 )
{
+ if( Flags & VFS_FDIRFLAG_STAT ) {
+ //return &gFIFI_TemplateAnonNode;
+ }
tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
return &tmp->Node;
}
/**
* \brief Read from a fifo pipe
*/
-size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tPipe *pipe = Node->ImplPtr;
Uint len;
while(remaining)
{
// Wait for buffer to fill
- if(pipe->Flags & PF_BLOCKING)
+ if( (pipe->Flags & PF_BLOCKING) && !(Flags & VFS_IOFLAG_NOBLOCK) )
{
if( pipe->ReadPos == pipe->WritePos )
VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
/**
* \brief Write to a fifo pipe
*/
-size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tPipe *pipe = Node->ImplPtr;
Uint len;
while(remaining)
{
// Wait for buffer to empty
- if(pipe->Flags & PF_BLOCKING)
+ if( (pipe->Flags & PF_BLOCKING) && !(Flags & VFS_IOFLAG_NOBLOCK) )
{
if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize ) {
LOG("Blocking write on FIFO");
return Length;
}
-// --- HELPERS ---
+// --- HeLPERS ---
/**
* \fn tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
* \brief Create a new pipe
int PCI_ScanBus(int ID, int bFill);\r
\r
int PCI_int_ReadDirRoot(tVFS_Node *node, int pos, char Dest[FILENAME_MAX]);\r
-tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename);\r
+tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename, Uint Flags);\r
Uint32 PCI_int_GetBusAddr(Uint16 Bus, Uint16 Slot, Uint16 Fcn, Uint8 Offset);\r
-size_t PCI_int_ReadDevice(tVFS_Node *node, off_t Offset, size_t Length, void *buffer);\r
+size_t PCI_int_ReadDevice(tVFS_Node *node, off_t Offset, size_t Length, void *buffer, Uint Flags);\r
int PCI_int_EnumDevice(Uint16 bus, Uint16 dev, Uint16 fcn, tPCIDevice *info);\r
\r
// === GLOBALS ===\r
}\r
/**\r
*/\r
-tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename)\r
+tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename, Uint Flags)\r
{\r
- int i;\r
- \r
// Find Match\r
- for(i=0;i<giPCI_DeviceCount;i++)\r
+ for( int i = 0; i < giPCI_DeviceCount; i ++ )\r
{\r
int cmp = strcmp(gPCI_Devices[i].Name, filename);\r
if( cmp > 0 ) // Sorted list\r
/**\r
* \brief Read the PCI configuration space of a device\r
*/\r
-size_t PCI_int_ReadDevice(tVFS_Node *node, off_t pos, size_t length, void *buffer)\r
+size_t PCI_int_ReadDevice(tVFS_Node *node, off_t pos, size_t length, void *buffer, Uint Flags)\r
{ \r
if( pos + length > 256 ) return 0;\r
\r
#endif
int SysFS_Comm_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
-tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, const char *Filename);
-size_t SysFS_Comm_ReadFile(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
+tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags);
+size_t SysFS_Comm_ReadFile(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
void SysFS_Comm_CloseFile(tVFS_Node *Node);
// === GLOBALS ===
* \fn tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, const char *Filename)
* \brief Find a file in a SysFS directory
*/
-tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, const char *Filename)
+tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
{
tSysFS_Ent *child = (tSysFS_Ent*)Node->ImplPtr;
/**
* \brief Read from an exposed buffer
*/
-size_t SysFS_Comm_ReadFile(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t SysFS_Comm_ReadFile(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
if( Offset > Node->Size ) return -1;
if( Length > Node->Size ) Length = Node->Size;
// === PROTOTYPES ===
int VT_Install(char **Arguments);
int VT_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *VT_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *VT_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data);
-size_t VT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t VT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+size_t VT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t VT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data);
void VT_Terminal_Reference(tVFS_Node *Node);
void VT_Terminal_Close(tVFS_Node *Node);
* \param Node Root node
* \param Name Name (number) of the terminal
*/
-tVFS_Node *VT_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *VT_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
int num;
/**
* \brief Read from a virtual terminal
*/
-size_t VT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t VT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
- int pos, avail;
+ int pos, avail, rv;
tVTerm *term = &gVT_Terminals[ Node->Inode ];
Uint32 *codepoint_buf = Buffer;
Uint32 *codepoint_in;
+ tTime timeout_zero = 0;
Mutex_Acquire( &term->ReadingLock );
case TERM_MODE_TEXT:
VT_int_UpdateCursor(term, 1);
- VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "VT_Read (UTF-8)");
+ rv = VFS_SelectNode(Node, VFS_SELECT_READ,
+ (Flags & VFS_IOFLAG_NOBLOCK ? &timeout_zero : NULL), "VT_Read (UTF-8)");
+ if(!rv) {
+ errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+ return -1;
+ }
avail = term->InputWrite - term->InputRead;
if(avail < 0)
//case TERM_MODE_FB:
// Other - UCS-4
default:
- VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "VT_Read (UCS-4)");
+ rv = VFS_SelectNode(Node, VFS_SELECT_READ,
+ (Flags & VFS_IOFLAG_NOBLOCK ? &timeout_zero : NULL), "VT_Read (UCS-4)");
+ if(!rv) {
+ errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+ return -1;
+ }
avail = term->InputWrite - term->InputRead;
if(avail < 0)
/**
* \brief Write to a virtual terminal
*/
-size_t VT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t VT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tVTerm *term = &gVT_Terminals[ Node->Inode ];
int size;
// === PROTOTYPES ===
int CoreDevs_Install(char **Arguments);
-size_t CoreDevs_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
-size_t CoreDevs_Read_Zero(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t CoreDevs_Read_One (tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t CoreDevs_Read_Null(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t CoreDevs_Read_FRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t CoreDevs_Read_GRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
+size_t CoreDevs_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
+size_t CoreDevs_Read_Zero(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t CoreDevs_Read_One (tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t CoreDevs_Read_Null(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t CoreDevs_Read_FRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t CoreDevs_Read_GRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
// === GLOBALS ===
MODULE_DEFINE(0, 0x0100, CoreDevs, CoreDevs_Install, NULL, NULL);
return MODULE_ERR_OK;
}
-size_t CoreDevs_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t CoreDevs_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
return Length; // Ignore
}
-size_t CoreDevs_Read_Zero(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t CoreDevs_Read_Zero(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
memset(Buffer, 0, Length);
return Length;
}
-size_t CoreDevs_Read_One (tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t CoreDevs_Read_One (tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
Uint8 *ptr = Buffer;
size_t rem;
return Length;
}
-size_t CoreDevs_Read_Null(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t CoreDevs_Read_Null(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
return 0;
}
//! Fast random number generator
-size_t CoreDevs_Read_FRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t CoreDevs_Read_FRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
Uint8 *cbuf = Buffer;
for( int i = 0; i < Length; i ++ )
return Length;
}
-size_t CoreDevs_Read_GRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t CoreDevs_Read_GRandom(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
+ // TODO: VFS_IOFLAG_NOBLOCK
Log_Error("CoreDevs", "GRandom is unimplimented");
return -1;
}
extern char *strrchr(const char *__s, int __c);
extern void itoa(char *buf, Uint64 num, int base, int minLength, char pad);
extern int atoi(const char *string);
+extern long atol(const char *string);
+extern long long atoll(const char *string);
extern unsigned long long strtoull(const char *str, char **end, int base);
extern unsigned long strtoul(const char *str, char **end, int base);
extern signed long long strtoll(const char *str, char **end, int base);
extern void Panic(const char *Msg, ...); //!< Print a panic message (initiates a kernel panic)
extern void Warning(const char *Msg, ...); //!< Print a warning message
extern void LogF(const char *Fmt, ...); //!< Print a log message without a trailing newline
+extern void LogFV(const char *Fmt, va_list Args); //!< va_list non-newline log message
extern void Log(const char *Fmt, ...); //!< Print a log message
extern void Debug(const char *Fmt, ...); //!< Print a debug message (doesn't go to KTerm)
extern void LogV(const char *Fmt, va_list Args); //!< va_list Log message
*/
extern void Time_Delay(int Delay);
+/**
+ * \brief Busy wait for a period of milliseconds
+ */
+extern void Time_MicroSleep(Uint16 Delay);
+
#endif
*/
} tVFS_Node;
+/**
+ * \name tVFS_NodeType.FindDir Flags
+ * \brief
+ * \{
+ */
+//\! Attempt non-blocking IO
+#define VFS_IOFLAG_NOBLOCK 0x001
+/**
+ * \}
+ */
+
+/**
+ * \name tVFS_NodeType.FindDir Flags
+ * \brief
+ * \{
+ */
+//\! Call was triggered by VFS_Stat (as opposed to open)
+#define VFS_FDIRFLAG_STAT 0x001
+/**
+ * \}
+ */
+
/**
* \brief Functions for a specific node type
*/
* \param Buffer Destination for read data
* \return Number of bytes read
*/
- size_t (*Read)(struct sVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
+ size_t (*Read)(struct sVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
/**
* \brief Write to the file
* \param Node Pointer to this node
* \param Buffer Source of written data
* \return Number of bytes read
*/
- size_t (*Write)(struct sVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+ size_t (*Write)(struct sVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
/**
* \brief Map a region of a file into memory
* \note The node returned must be accessable until tVFS_NodeType::Close
* is called and ReferenceCount reaches zero.
*/
- struct sVFS_Node *(*FindDir)(struct sVFS_Node *Node, const char *Name);
+ struct sVFS_Node *(*FindDir)(struct sVFS_Node *Node, const char *Name, Uint Flags);
/**
* \brief Read from a directory
* \param Flags Flags to apply to the new child (directory or symlink)
* \return Created node or NULL on error
*/
- tVFS_Node *(*MkNod)(struct sVFS_Node *Node, const char *Name, Uint Flags);
+ tVFS_Node *(*MkNod)(struct sVFS_Node *Node, const char *Name, Uint Mode);
/**
* \brief Relink (Rename/Remove) a file/directory
* \{
*/
//! Open for execution
-#define VFS_OPENFLAG_EXEC 0x01
+#define VFS_OPENFLAG_EXEC 0x001
//! Open for reading
-#define VFS_OPENFLAG_READ 0x02
+#define VFS_OPENFLAG_READ 0x002
//! Open for writing
-#define VFS_OPENFLAG_WRITE 0x04
+#define VFS_OPENFLAG_WRITE 0x004
//! Do not resolve the final symbolic link
-#define VFS_OPENFLAG_NOLINK 0x40
+#define VFS_OPENFLAG_NOLINK 0x040
//! Create the file if it doesn't exist
-#define VFS_OPENFLAG_CREATE 0x80
+#define VFS_OPENFLAG_CREATE 0x080
+//! Open file as non-blocking
+#define VFS_OPENFLAG_NONBLOCK 0x100
//! Treat as a directory
#define VFS_OPENFLAG_DIRECTORY 0x1000
//! Open as a user
#include "vfs.h"
#include "vfs_int.h"
+// === PROTOTYPES ===
+Uint VFS_int_CheckACLs(tVFS_ACL *ACLs, int Num, int bDeny, Uint Perms, tUID UID, tGID GID);
+
// === GLOBALS ===
tVFS_ACL gVFS_ACL_EveryoneRWX = { {1,-1}, {0,VFS_PERM_ALL} };
tVFS_ACL gVFS_ACL_EveryoneRW = { {1,-1}, {0,VFS_PERM_ALL^VFS_PERM_EXECUTE} };
tVFS_Node *DevFS_InitDevice(const char *Device, const char **Options);
void DevFS_Unmount(tVFS_Node *RootNode);
int DevFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
// === GLOBALS ===
tVFS_Driver gDevFS_Info = {
* \fn tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name)
* \brief Get an entry from the devices directory
*/
-tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tDevFS_Driver *dev;
/*
- * AcessMicro VFS
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * vfs/fs/root.c
* - Root Filesystem Driver
+ *
+ * TODO: Restrict to directories only
*/
#define DEBUG 0
#include <acess.h>
// === PROTOTYPES ===
tVFS_Node *Root_InitDevice(const char *Device, const char **Options);
tVFS_Node *Root_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
-tVFS_Node *Root_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-size_t Root_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t Root_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+size_t Root_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t Root_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
tRamFS_File *Root_int_AllocFile(void);
// === GLOBALS ===
* \fn tVFS_Node *Root_FindDir(tVFS_Node *Node, const char *Name)
* \brief Find an entry in the filesystem
*/
-tVFS_Node *Root_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tRamFS_File *parent = Node->ImplPtr;
tRamFS_File *child = parent->Data.FirstChild;
/**
* \brief Read from a file in the root directory
*/
-size_t Root_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t Root_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tRamFS_File *file = Node->ImplPtr;
/**
* \brief Write to a file in the root directory
*/
-size_t Root_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t Root_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tRamFS_File *file = Node->ImplPtr;
/*
- * AcessMicro VFS
- * - File IO Passthru's
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * vfs/io.c
+ * - VFS IO Handling (Read/Write)
+ *
+ * TODO: VFS-level caching to support non-blocking IO?
*/
#define DEBUG 0
#include <acess.h>
}
LOG("Position=%llx", h->Position);
- ret = h->Node->Type->Read(h->Node, h->Position, Length, Buffer);
+ Uint flags = 0;
+ flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
+ ret = h->Node->Type->Read(h->Node, h->Position, Length, Buffer, flags);
if(ret == (size_t)-1) LEAVE_RET('i', -1);
h->Position += ret;
}
if( !MM_GetPhysAddr(h->Node->Type->Read) ) {
- Log_Error("VFS", "Node type %p(%s) read method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName,
+ Log_Error("VFS", "Node type %p(%s) read method is junk %p",
+ h->Node->Type, h->Node->Type->TypeName,
h->Node->Type->Read);
LEAVE_RET('i', -1);
}
- ret = h->Node->Type->Read(h->Node, Offset, Length, Buffer);
+ Uint flags = 0;
+ flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
+ ret = h->Node->Type->Read(h->Node, Offset, Length, Buffer, flags);
if(ret == (size_t)-1) return -1;
return ret;
}
}
if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
- Log_Error("VFS", "Node type %p(%s) write method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName,
+ Log_Error("VFS", "Node type %p(%s) write method is junk %p",
+ h->Node->Type, h->Node->Type->TypeName,
h->Node->Type->Write);
return -1;
}
- ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer);
+ Uint flags = 0;
+ flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
+ ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer, flags);
if(ret == (size_t)-1) return -1;
h->Position += ret;
if(!h->Node->Type || !h->Node->Type->Write) return 0;
if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
- Log_Error("VFS", "Node type %p(%s) write method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName,
+ Log_Error("VFS", "Node type %p(%s) write method is junk %p",
+ h->Node->Type, h->Node->Type->TypeName,
h->Node->Type->Write);
return -1;
}
- ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer);
+ Uint flags = 0;
+ flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
+ ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer, flags);
if(ret == (size_t)-1) return -1;
return ret;
}
// === PROTOTYPES ===
tVFS_Node *VFS_MemFile_Create(const char *Path);
void VFS_MemFile_Close(tVFS_Node *Node);
-size_t VFS_MemFile_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t VFS_MemFile_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+size_t VFS_MemFile_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t VFS_MemFile_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
// === GLOBALS ===
tVFS_NodeType gVFS_MemFileType = {
/**
* \brief Read from a memory file
*/
-size_t VFS_MemFile_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t VFS_MemFile_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
// Check for use of free'd file
if(Node->ImplPtr == NULL) return 0;
/**
* \brief Write to a memory file
*/
-size_t VFS_MemFile_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t VFS_MemFile_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
// Check for use of free'd file
if(Node->ImplPtr == NULL) return 0;
return NULL;
}
// TODO: Clip read length
- read_len = nt->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
+ read_len = nt->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE,
+ (void*)mapping_dest, 0);
// TODO: This was commented out, why?
if( read_len != PAGE_SIZE ) {
memset( (void*)(mapping_dest+read_len), 0, PAGE_SIZE-read_len );
// Check permissions on root of filesystem
if( !VFS_CheckACL(curNode, VFS_PERM_EXECUTE) ) {
LOG("Permissions failure on '%s'", Path);
+ errno = EPERM;
goto _error;
}
}
LOG("FindDir{=%p}(%p, '%s')", curNode->Type->FindDir, curNode, pathEle);
// Get Child Node
- tmpNode = curNode->Type->FindDir(curNode, pathEle);
+ tmpNode = curNode->Type->FindDir(curNode, pathEle, 0);
LOG("tmpNode = %p", tmpNode);
_CloseNode( curNode );
curNode = tmpNode;
// Error Check
if(!curNode) {
LOG("Node '%s' not found in dir '%s'", pathEle, Path);
+ errno = ENOENT;
goto _error;
}
if(!curNode->Type || !curNode->Type->Read) {
Log_Warning("VFS", "VFS_ParsePath - Read of symlink node %p'%s' is NULL",
curNode, Path);
+ errno = EINTERNAL;
goto _error;
}
if(iNestedLinks > MAX_NESTED_LINKS) {
Log_Notice("VFS", "VFS_ParsePath - Nested link limit exceeded");
+ errno = ENOENT;
goto _error;
}
int remlen = strlen(Path) - (ofs + nextSlash);
if( curNode->Size + remlen > MAX_PATH_LEN ) {
Log_Warning("VFS", "VFS_ParsePath - Symlinked path too long");
+ errno = ENOENT;
goto _error;
}
- curNode->Type->Read( curNode, 0, curNode->Size, path_buffer );
+ curNode->Type->Read( curNode, 0, curNode->Size, path_buffer, 0 );
path_buffer[ curNode->Size ] = '\0';
LOG("path_buffer = '%s'", path_buffer);
strcat(path_buffer, Path + ofs+nextSlash);
if( !(curNode->Flags & VFS_FFLAG_DIRECTORY) )
{
Log_Warning("VFS", "VFS_ParsePath - Path segment is not a directory");
+ errno = ENOTDIR;
goto _error;
}
// Check if allocation succeeded
if(!tmp) {
Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer");
+ errno = ENOMEM;
goto _error;
}
*TruePath = tmp;
// Check final finddir call
if( !curNode->Type || !curNode->Type->FindDir ) {
Log_Warning("VFS", "VFS_ParsePath - FindDir doesn't exist for element of '%s'", Path);
+ errno = ENOENT;
goto _error;
}
// Get last node
LOG("FindDir(%p, '%s')", curNode, &Path[ofs]);
- tmpNode = curNode->Type->FindDir(curNode, &Path[ofs]);
+ tmpNode = curNode->Type->FindDir(curNode, &Path[ofs], 0);
LOG("tmpNode = %p", tmpNode);
// Check if file was found
if(!tmpNode) {
LOG("Node '%s' not found in dir '%.*s'", &Path[ofs], ofs, Path);
+ errno = ENOENT;
goto _error;
}
_CloseNode( curNode );
// Check if allocation succeeded
if(!tmp) {
Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer");
+ errno = ENOMEM;
goto _error;
}
*TruePath = tmp;
}
// Open failed, so decrement the open handle count
_DereferenceMount(mnt, "ParsePath - error");
-
LEAVE('n');
return NULL;
}
goto _error;
}
// Read symlink's path
- node->Type->Read( node, 0, node->Size, tmppath );
+ node->Type->Read( node, 0, node->Size, tmppath, 0 );
tmppath[ node->Size ] = '\0';
_CloseNode( node );
_DereferenceMount(mnt, "Open - symlink");
}
// Find Child
- node = h->Node->Type->FindDir(h->Node, Name);
+ node = h->Node->Type->FindDir(h->Node, Name, 0);
if(!node) {
errno = ENOENT;
LEAVE_RET('i', -1);
int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info);\r
int BGA_int_MapFB(void *Dest);\r
// Filesystem\r
-size_t BGA_Read(tVFS_Node *Node, off_t off, size_t len, void *buffer);\r
-size_t BGA_Write(tVFS_Node *Node, off_t off, size_t len, const void *buffer);\r
+size_t BGA_Read(tVFS_Node *Node, off_t off, size_t len, void *buffer, Uint Flags);\r
+size_t BGA_Write(tVFS_Node *Node, off_t off, size_t len, const void *buffer, Uint Flags);\r
int BGA_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
\r
// === GLOBALS ===\r
/**\r
* \brief Read from the framebuffer\r
*/\r
-size_t BGA_Read(tVFS_Node *node, off_t off, size_t len, void *buffer)\r
+size_t BGA_Read(tVFS_Node *node, off_t off, size_t len, void *buffer, Uint Flags)\r
{\r
// Check Mode\r
if(giBGA_CurrentMode == -1) return -1;\r
/**\r
* \brief Write to the framebuffer\r
*/\r
-size_t BGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)\r
+size_t BGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)\r
{\r
if( giBGA_CurrentMode == -1 ) BGA_int_UpdateMode(0);\r
return DrvUtil_Video_WriteLFB(&gBGA_DrvUtil_BufInfo, Offset, Length, Buffer);\r
// === PROTOTYPES ===\r
int Vesa_Install(char **Arguments);\r
int VBE_int_GetModeList(void);\r
-size_t Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);\r
+size_t Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);\r
int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
int Vesa_Int_SetMode(int Mode);\r
int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data);\r
/**\r
* \brief Write to the framebuffer\r
*/\r
-size_t Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)\r
+size_t Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)\r
{\r
if( gVesa_Modes[giVesaCurrentMode].framebuffer == 0 ) {\r
Log_Warning("VESA", "Vesa_Write - Non-LFB Modes not yet supported.");\r
// === PROTOTYPES ===
int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName);
+tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName, Uint Flags);
tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int Ext2_Unlink(tVFS_Node *Node, const char *OldName);
int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
* \param Filename Name of wanted file
* \return VFS Node of file
*/
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename)
+tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
{
tExt2_Disk *disk = Node->ImplPtr;
tExt2_Inode inode;
while(size > 0)
{
VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
- // TODO: Possible overrun if name_len == 255?
- dirent.name[ dirent.name_len ] = '\0'; // Cap off string
// If it matches, create a node and return it
- if(dirent.name_len == filenameLen && strcmp(dirent.name, Filename) == 0)
+ if(dirent.name_len == filenameLen && strncmp(dirent.name, Filename, filenameLen) == 0)
return Ext2_int_CreateNode( disk, dirent.inode );
// Increment pointers
ofs += dirent.rec_len;
extern int Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode);
// --- Dir ---
extern int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName);
-extern tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName, Uint Flags);
+extern tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Mode);
extern int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
extern tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId);
extern int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node);
// --- Read ---
-extern size_t Ext2_Read(tVFS_Node *node, off_t offset, size_t length, void *buffer);
+extern size_t Ext2_Read(tVFS_Node *node, off_t offset, size_t length, void *buffer, Uint Flags);
// --- Write ---
-extern size_t Ext2_Write(tVFS_Node *node, off_t offset, size_t length, const void *buffer);
+extern size_t Ext2_Write(tVFS_Node *node, off_t offset, size_t length, const void *buffer, Uint Flags);
extern Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 LastBlock);
extern void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
extern int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
/**
* \brief Read from a file
*/
-size_t Ext2_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t Ext2_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tExt2_Disk *disk = Node->ImplPtr;
tExt2_Inode inode;
}
// Read first block
+ // TODO: If (Flags & VFS_IOFLAG_NOBLOCK) trigger read and return EWOULDBLOCK?
remLen = Length;
VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer);
remLen -= disk->BlockSize - Offset;
{
base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
if(base == 0) {
- Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
+ Log_Warning("EXT2", "NULL Block Detected in INode 0x%llx", Node->Inode);
LEAVE('i', 0);
return 0;
}
/**
* \brief Write to a file
*/
-size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tExt2_Disk *disk = Node->ImplPtr;
tExt2_Inode inode;
int bNewBlocks = 0;
Debug_HexDump("Ext2_Write", Buffer, Length);
-
+
+ // TODO: Handle (Flags & VFS_IOFLAG_NOBLOCK)
+
Ext2_int_ReadInode(disk, Node->Inode, &inode);
// Get the ammount of space already allocated
// --- Directory Access ---
extern int FAT_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
-extern tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name);
+extern tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
extern tVFS_Node *FAT_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode);
extern int FAT_int_GetEntryByCluster(tVFS_Node *DirNode, Uint32 Cluster, fat_filetable *Entry);
#if SUPPORT_WRITE
void FAT_int_DelLFN(tVFS_Node *Node, int ID);
#endif
int FAT_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
-tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
tVFS_Node *FAT_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode);
#if SUPPORT_WRITE
tVFS_Node *FAT_Mknod(tVFS_Node *Node, const char *Name, Uint Flags);
* \fn tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)
* \brief Finds an entry in the current directory
*/
-tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
fat_filetable fileent;
// --- Helpers\r
int FAT_int_GetAddress(tVFS_Node *Node, Uint64 Offset, Uint64 *Addr, Uint32 *Cluster);\r
// --- File IO\r
-size_t FAT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);\r
+size_t FAT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);\r
#if SUPPORT_WRITE\r
-size_t FAT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);\r
+size_t FAT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);\r
#endif\r
void FAT_CloseFile(tVFS_Node *node);\r
\r
/**\r
* \brief Reads data from a specified file\r
*/\r
-size_t FAT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)\r
+size_t FAT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)\r
{\r
int preSkip, count;\r
Uint64 final_bytes;\r
}\r
}\r
\r
+ // TODO: Handle (Flags & VFS_IOFLAG_NOBLOCK)\r
+\r
// Reading from within one cluster\r
if((int)Offset + (int)Length <= bpc)\r
{\r
* \param Length Size of data to write\r
* \param Buffer Data source\r
*/\r
-size_t FAT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)\r
+size_t FAT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)\r
{\r
tFAT_VolInfo *disk = Node->ImplPtr;\r
char tmpBuf[disk->BytesPerCluster];\r
off_t original_offset = Offset;\r
\r
if(Offset > Node->Size) return 0;\r
+ // TODO: Handle (Flags & VFS_IOFLAG_NOBLOCK)\r
\r
ENTER("pNode Xoffset xlength pbuffer", Node, Offset, Length, Buffer);\r
\r
tVFS_Node *InitRD_InitDevice(const char *Device, const char **Arguments);
void InitRD_Unmount(tVFS_Node *Node);
tVFS_Node *InitRD_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode);
-size_t InitRD_ReadFile(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer);
+size_t InitRD_ReadFile(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer, Uint Flags);
int InitRD_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
-tVFS_Node *InitRD_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *InitRD_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
void InitRD_DumpDir(tVFS_Node *Node, int Indent);
// === GLOBALS ===
/**
* \brief Read from a file
*/
-size_t InitRD_ReadFile(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t InitRD_ReadFile(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
if(Offset > Node->Size)
return 0;
/**
* \brief Find an element in a directory
*/
-tVFS_Node *InitRD_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *InitRD_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
int i;
tInitRD_File *dir = Node->ImplPtr;
};
} PACKED tNTFS_FILE_Attrib;
+// -- dir.c
extern int NTFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-extern tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name);
+extern tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
#endif
// === PROTOTYPES ===
int NTFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
Uint64 NTFS_int_IndexLookup(Uint64 Inode, const char *IndexName, const char *Str);
// === CODE ===
/**
* \brief Get an entry from a directory by name
*/
-tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tNTFS_Disk *disk = Node->ImplPtr;
Uint64 inode = NTFS_int_IndexLookup(Node->Inode, "$I30", Name);
void RAMFS_Unmount(tVFS_Node *Node);
// --- Directories ---
int RAMFS_ReadDir(tVFS_Node *Node, int Index, char Dest[256]);
-tVFS_Node *RAMFS_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *RAMFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
tVFS_Node *RAMFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int RAMFS_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *Node);
int RAMFS_Unlink(tVFS_Node *Node, const char *Name);
// --- Files ---
-size_t RAMFS_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer);
-size_t RAMFS_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer);
+size_t RAMFS_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer, Uint Flags);
+size_t RAMFS_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer, Uint Flags);
// --- Internals --
void RAMFS_int_RefFile(tRAMFS_Inode *Inode);
void RAMFS_int_DerefFile(tRAMFS_Inode *Inode);
return -ENOENT;
}
-tVFS_Node *RAMFS_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *RAMFS_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tRAMFS_Dir *dir = Node->ImplPtr;
tVFS_Node *RAMFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
{
tRAMFS_Dir *dir = Node->ImplPtr;
- if( RAMFS_FindDir(Node, Name) != NULL )
+ if( RAMFS_FindDir(Node, Name, 0) != NULL )
return NULL;
tRAMFS_DirEnt *de = malloc( sizeof(tRAMFS_DirEnt) + strlen(Name) + 1 );
return Size;
}
-size_t RAMFS_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer)
+size_t RAMFS_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer, Uint Flags)
{
tRAMFS_File *file = Node->ImplPtr;
return RAMFS_int_DoIO(file, Offset, Size, Buffer, 1);
}
-size_t RAMFS_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer)
+size_t RAMFS_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer, Uint Flags)
{
tRAMFS_File *file = Node->ImplPtr;
void IPStack_Adapter_Del(void *Handle);
// --- VFS API ---
int Adapter_ReadDir(tVFS_Node *Node, int Pos, char Name[FILENAME_MAX]);
-tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int Adapter_DirIOCtl(tVFS_Node *Node, int Num, void *Data);
int Adapter_IOCtl(tVFS_Node *Node, int Num, void *Data);
// --- "Internal" (IPStack) API ---
return -EINVAL;
}
-tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tAdapter *a = Adapter_GetByName(Name);
if(!a)
// === PROTOTYPES ===
int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
int IPStack_AddFile(tSocketFile *File);
tInterface *IPStack_AddInterface(const char *Device, int Type, const char *Name);
int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data);
// === GLOBALS ===
/**
* \brief Get the node of an interface
*/
-tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
- #if 0
- int i, num;
- #endif
tInterface *iface;
ENTER("pNode sName", Node, Name);
/**
* \brief Gets a named node from an interface directory
*/
-tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tSocketFile *file = gIP_FileTemplates;
// === PROTOTYPES ===
// - Routes directory
int IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
tVFS_Node *IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int IPStack_RouteDir_Unlink(tVFS_Node *Node, const char *OldName);
tRoute *_Route_FindExactRoute(int Type, void *Network, int Subnet, int Metric);
/**
* \brief FindDir for the /Devices/ip/routes/ directory
*/
-tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
// Interpret the name as <type>:<addr>, returning the interface for
// needed to access that address.
// --- Server
tVFS_Node *TCP_Server_Init(tInterface *Interface);
int TCP_Server_ReadDir(tVFS_Node *Node, int Pos, char Name[FILENAME_MAX]);
-tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
void TCP_Server_Close(tVFS_Node *Node);
// --- Client
tVFS_Node *TCP_Client_Init(tInterface *Interface);
-size_t TCP_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t TCP_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+size_t TCP_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t TCP_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data);
void TCP_Client_Close(tVFS_Node *Node);
// --- Helpers
* \param Node Server node
* \param Name Hexadecimal ID of the node
*/
-tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tTCPConnection *conn;
tTCPListener *srv = Node->ImplPtr;
* \note If \a Length is smaller than the size of the packet, the rest
* of the packet's data will be discarded.
*/
-size_t TCP_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t TCP_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tTCPConnection *conn = Node->ImplPtr;
size_t len;
if( len == 0 ) {
VFS_MarkAvaliable(Node, 0);
+ errno = 0;
LEAVE('i', -1);
return -1;
}
}
// Wait
- VFS_SelectNode(Node, VFS_SELECT_READ|VFS_SELECT_ERROR, NULL, "TCP_Client_Read");
+ {
+ tTime *timeout = NULL;
+ tTime timeout_zero = 0;
+ if( Flags & VFS_IOFLAG_NOBLOCK )
+ timeout = &timeout_zero;
+ if( !VFS_SelectNode(Node, VFS_SELECT_READ|VFS_SELECT_ERROR, timeout, "TCP_Client_Read") ) {
+ errno = EWOULDBLOCK;
+ LEAVE('i', -1);
+ return -1;
+ }
+ }
// Lock list and read as much as possible (up to `Length`)
Mutex_Acquire( &conn->lRecievedPackets );
/**
* \brief Send some bytes on a connection
*/
-size_t TCP_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t TCP_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tTCPConnection *conn = Node->ImplPtr;
size_t rem = Length;
// Don't allow a write to a closed connection
if( conn->State > TCP_ST_OPEN ) {
VFS_MarkError(Node, 1);
+ errno = 0;
LEAVE('i', -1);
return -1;
}
// Wait
- VFS_SelectNode(Node, VFS_SELECT_WRITE|VFS_SELECT_ERROR, NULL, "TCP_Client_Write");
+ {
+ tTime *timeout = NULL;
+ tTime timeout_zero = 0;
+ if( Flags & VFS_IOFLAG_NOBLOCK )
+ timeout = &timeout_zero;
+ if( !VFS_SelectNode(Node, VFS_SELECT_WRITE|VFS_SELECT_ERROR, timeout, "TCP_Client_Write") ) {
+ errno = EWOULDBLOCK;
+ LEAVE('i', -1);
+ return -1;
+ }
+ }
do
{
void UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, const void *Address, Uint16 Port, const void *Data, size_t Length);
// --- Client Channels
tVFS_Node *UDP_Channel_Init(tInterface *Interface);
-size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data);
void UDP_Channel_Close(tVFS_Node *Node);
// --- Helpers
/**
* \brief Read from the channel file (wait for a packet)
*/
-size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tUDPChannel *chan = Node->ImplPtr;
tUDPPacket *pack;
for(;;)
{
- VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "UDP_Channel_Read");
+ tTime timeout_z = 0, *timeout = (Flags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL;
+ int rv = VFS_SelectNode(Node, VFS_SELECT_READ, timeout, "UDP_Channel_Read");
+ if( rv ) {
+ errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+ }
SHORTLOCK(&chan->lQueue);
if(chan->Queue == NULL) {
SHORTREL(&chan->lQueue);
/**
* \brief Write to the channel file (send a packet)
*/
-size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tUDPChannel *chan = Node->ImplPtr;
const tUDPEndpoint *ep;
int Mouse_Cleanup(void);
// - "User" side
int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data);
-size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data);
+size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data, Uint Flags);
// - Device Side
tMouse *Mouse_Register(const char *Name, int NumButtons, int NumAxies);
void Mouse_RemoveInstance(tMouse *Handle);
return 0;
}
-tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
if( strcmp(Name, "system") != 0 ) return NULL;
return &gMouse_Pointer.Node;
/**
* \brief Read from a device
*/
-size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data)
+size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data, Uint Flags)
{
tPointer *ptr = Node->ImplPtr;
int n_buttons = ptr->FileHeader->NButtons;
int FDD_RegisterFS(void);
// --- VFS
int FDD_ReadDir(tVFS_Node *Node, int pos, char dest[FILENAME_MAX]);
-tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, const char *Name);
+tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, const char *Name, Uint Flags);
int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);
-size_t FDD_ReadFS(tVFS_Node *node, off_t Offset, size_t Len, void *buffer);
+size_t FDD_ReadFS(tVFS_Node *node, off_t Offset, size_t Len, void *buffer, Uint Flags);
// --- Helpers
int FDD_int_ReadWriteWithinTrack(int Disk, int Track, int bWrite, size_t Offset, size_t Length, void *Buffer);
* \param Name Drive name
* \return Pointer to node structure
*/
-tVFS_Node *FDD_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *FDD_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
int pos;
if( '0' > Name[0] || Name[0] > '9' ) return NULL;
* \param Buffer Destination buffer
* \return Number of bytes read
*/
-size_t FDD_ReadFS(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t FDD_ReadFS(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
int disk = Node->Inode;
int track;
rem_len = Length;
track = Offset / BYTES_PER_TRACK;
- Offset %= BYTES_PER_TRACK;
+ Offset %= BYTES_PER_TRACK;
+
+ // TODO: Handle (Flags & VFS_IOFLAG_NOBLOCK)
if( Offset )
{
int LVM_Cleanup(void);
// ---
int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
-tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
-tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name);
-size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
-size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
+size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
+size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
void LVM_CloseNode(tVFS_Node *Node);
Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument);
else
return -ENOENT;
}
-tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tLVM_Vol *vol;
for( vol = gpLVM_FirstVolume; vol; vol = vol->Next )
strncpy(Dest, src, FILENAME_MAX);
return 0;
}
-tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
tLVM_Vol *vol = Node->ImplPtr;
return NULL;
}
-size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tLVM_Vol *vol = Node->ImplPtr;
Uint64 byte_size = vol->BlockCount * vol->BlockSize;
);
}
-size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
return 0;
}
-size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tLVM_SubVolume *sv = Node->ImplPtr;
Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
LVM_int_DrvUtil_ReadBlock, sv->Vol->BlockSize, sv->Vol
);
}
-size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tLVM_SubVolume *sv = Node->ImplPtr;
Uint64 byte_size = sv->BlockCount * sv->Vol->BlockSize;
int USB_Install(char **Arguments);
void USB_Cleanup(void);
int USB_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *USB_FindDir(tVFS_Node *Node, const char *Name);
+tVFS_Node *USB_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
int USB_IOCtl(tVFS_Node *Node, int Id, void *Data);
// === GLOBALS ===
* \fn tVFS_Node *USB_FindDir(tVFS_Node *Node, const char *Name)
* \brief Locate an entry in the USB root
*/
-tVFS_Node *USB_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *USB_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
{
return NULL;
}
// === PROTOTYPES ===
int VGA_Install(char **Arguments);
-size_t VGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+size_t VGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
int VGA_IOCtl(tVFS_Node *Node, int Id, void *Data);
Uint8 VGA_int_GetColourNibble(Uint16 col);
Uint16 VGA_int_GetWord(const tVT_Char *Char);
/**
* \brief Writes a string of bytes to the VGA controller
*/
-size_t VGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+size_t VGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
if( giVGA_BufferFormat == VIDEO_BUFFMT_TEXT )
{