X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fvfs%2Fmemfile.c;fp=KernelLand%2FKernel%2Fvfs%2Fmemfile.c;h=14b39481d0c82d7adc503d605ace864855f27ead;hb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;hp=0000000000000000000000000000000000000000;hpb=a2495c6ea4f4cab16b5d339ae511428e92e89e73;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/vfs/memfile.c b/KernelLand/Kernel/vfs/memfile.c new file mode 100644 index 00000000..14b39481 --- /dev/null +++ b/KernelLand/Kernel/vfs/memfile.c @@ -0,0 +1,135 @@ +/* + * Acess 2 + * Virtual File System + * - Memory Pseudo Files + */ +#include +#include + +// === PROTOTYPES === +tVFS_Node *VFS_MemFile_Create(const char *Path); +void VFS_MemFile_Close(tVFS_Node *Node); +Uint64 VFS_MemFile_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +Uint64 VFS_MemFile_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer); + +// === GLOBALS === +tVFS_NodeType gVFS_MemFileType = { + .Close = VFS_MemFile_Close, + .Read = VFS_MemFile_Read, + .Write = VFS_MemFile_Write + }; + +// === CODE === +/** + * \fn tVFS_Node *VFS_MemFile_Create(const char *Path) + */ +tVFS_Node *VFS_MemFile_Create(const char *Path) +{ + Uint base, size; + const char *str = Path; + tVFS_Node *ret; + + str++; // Eat '$' + + // Read Base address + base = 0; + for( ; ('0' <= *str && *str <= '9') || ('A' <= *str && *str <= 'F'); str++ ) + { + base *= 16; + if('A' <= *str && *str <= 'F') + base += *str - 'A' + 10; + else + base += *str - '0'; + } + + // Check separator + if(*str++ != ':') return NULL; + + // Read buffer size + size = 0; + for( ; ('0' <= *str && *str <= '9') || ('A' <= *str && *str <= 'F'); str++ ) + { + size *= 16; + if('A' <= *str && *str <= 'F') + size += *str - 'A' + 10; + else + size += *str - '0'; + } + + // Check for NULL byte + if(*str != '\0') return NULL; + + // Allocate and fill node + ret = malloc(sizeof(tVFS_Node)); + memset(ret, 0, sizeof(tVFS_Node)); + + // State + ret->ImplPtr = (void*)base; + ret->Size = size; + + // ACLs + ret->NumACLs = 1; + ret->ACLs = &gVFS_ACL_EveryoneRWX; + + // Functions + ret->Type = &gVFS_MemFileType; + + return ret; +} + +/** + * \fn void VFS_MemFile_Close(tVFS_Node *Node) + * \brief Dereference and clean up a memory file + */ +void VFS_MemFile_Close(tVFS_Node *Node) +{ + Node->ReferenceCount --; + if( Node->ReferenceCount == 0 ) { + Node->ImplPtr = NULL; + free(Node); + } +} + +/** + * \fn Uint64 VFS_MemFile_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Read from a memory file + */ +Uint64 VFS_MemFile_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + // Check for use of free'd file + if(Node->ImplPtr == NULL) return 0; + + // Check for out of bounds read + if(Offset > Node->Size) return 0; + + // Truncate data read if needed + if(Offset + Length > Node->Size) + Length = Node->Size - Offset; + + // Copy Data + memcpy(Buffer, (Uint8*)Node->ImplPtr + Offset, Length); + + return Length; +} + +/** + * \fn Uint64 VFS_MemFile_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Write to a memory file + */ +Uint64 VFS_MemFile_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer) +{ + // Check for use of free'd file + if(Node->ImplPtr == NULL) return 0; + + // Check for out of bounds read + if(Offset > Node->Size) return 0; + + // Truncate data read if needed + if(Offset + Length > Node->Size) + Length = Node->Size - Offset; + + // Copy Data + memcpy((Uint8*)Node->ImplPtr + Offset, Buffer, Length); + + return Length; +}