tThread *cur = Proc_GetCurThread();
Uint eip;
- Log_Warning("Proc", "Proc_Clone is deprecated");
// Sanity, please
if( !(Flags & CLONE_VM) ) {
Log_Error("Proc", "Proc_Clone: Don't leave CLONE_VM unset, use Proc_NewKThread instead");
};
tVFS_NodeType gIPCPipe_ChannelNodeType = {
.TypeName = "IPC Pipe - Channel",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = IPCPipe_Client_Read,
.Write = IPCPipe_Client_Write,
.Close = IPCPipe_Client_Close
new_client->Server = srv;
new_client->ClientEP.Node.Type = &gIPCPipe_ChannelNodeType;
new_client->ClientEP.Node.ImplPtr = new_client;
+ new_client->ClientEP.Node.Size = -1;
new_client->ServerEP.Node.Type = &gIPCPipe_ChannelNodeType;
new_client->ServerEP.Node.ImplPtr = new_client;
+ new_client->ServerEP.Node.Size = -1;
// Append to server list
RWLock_AcquireWrite(&srv->lChannelList);
};
tVFS_NodeType gPTY_NodeType_Client = {
.TypeName = "PTY-Client",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = PTY_ReadClient,
.Write = PTY_WriteClient,
.IOCtl = PTY_IOCtl,
};
tVFS_NodeType gPTY_NodeType_Server = {
.TypeName = "PTY-Server",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = PTY_ReadServer,
.Write = PTY_WriteServer,
.IOCtl = PTY_IOCtl,
if( InitialMode )
ret->Mode = *InitialMode;
// - Client node
+ ret->ClientNode.Size = -1;
ret->ClientNode.ImplPtr = ret;
ret->ClientNode.Type = &gPTY_NodeType_Client;
ret->ClientNode.UID = Threads_GetUID();
MODULE_DEFINE(0, 0x0100, CoreDevs, CoreDevs_Install, NULL, NULL);
tVFS_NodeType gCoreDevs_NT_Null = {
.TypeName = "CoreDevs-null",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = CoreDevs_Read_Null,
.Write = CoreDevs_Write
};
tVFS_NodeType gCoreDevs_NT_Zero = {
.TypeName = "CoreDevs-zero",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = CoreDevs_Read_Zero,
.Write = CoreDevs_Write
};
tVFS_NodeType gCoreDevs_NT_One = {
.TypeName = "CoreDevs-one",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = CoreDevs_Read_One,
.Write = CoreDevs_Write
};
tVFS_NodeType gCoreDevs_NT_FRandom = {
.TypeName = "CoreDevs-frandom",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = CoreDevs_Read_FRandom,
.Write = CoreDevs_Write
};
tVFS_NodeType gCoreDevs_NT_GRandom = {
.TypeName = "CoreDevs-grandom",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = CoreDevs_Read_GRandom,
.Write = CoreDevs_Write
};
tDevFS_Driver gCoreDevs_Null = {
NULL, "null",
{
- .Size = 0, .NumACLs = 1,
+ .Size = -1, .NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRW,
.Type = &gCoreDevs_NT_Null
}
tDevFS_Driver gCoreDevs_Zero = {
NULL, "zero",
{
- .Size = 0, .NumACLs = 1,
+ .Size = -1, .NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRW,
.Type = &gCoreDevs_NT_Zero
}
tDevFS_Driver gCoreDevs_One = {
NULL, "one",
{
- .Size = 0, .NumACLs = 1,
+ .Size = -1, .NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRW,
.Type = &gCoreDevs_NT_One
}
tDevFS_Driver gCoreDevs_FRandom = {
NULL, "frandom",
{
- .Size = 0, .NumACLs = 1,
+ .Size = -1, .NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRW,
.Type = &gCoreDevs_NT_FRandom,
.DataAvaliable = 1
tDevFS_Driver gCoreDevs_GRandom = {
NULL, "grandom",
{
- .Size = 0, .NumACLs = 1,
+ .Size = -1, .NumACLs = 1,
.ACLs = &gVFS_ACL_EveryoneRW,
.Type = &gCoreDevs_NT_GRandom,
.DataAvaliable = 1
#define SYS_READAT 72 // Read from an open file (with offset)
#define SYS_WRITE 73 // Write to an open file
#define SYS_WRITEAT 74 // Write to an open file (with offset)
-#define SYS_IOCTL 75 // Perform an IOCtl Call
-#define SYS_SEEK 76 // Seek to a new position in the file
-#define SYS_READDIR 77 // Read from an open directory
-#define SYS_GETACL 78 // Get an ACL Value
-#define SYS_SETACL 79 // Set an ACL Value
-#define SYS_FINFO 80 // Get file information
-#define SYS_MKDIR 81 // Create a new directory
-#define SYS_LINK 82 // Create a new link to a file
-#define SYS_SYMLINK 83 // Create a symbolic link
-#define SYS_UNLINK 84 // Delete a file
-#define SYS_TELL 85 // Return the current file position
-#define SYS_CHDIR 86 // Change current directory
-#define SYS_GETCWD 87 // Get current directory
-#define SYS_MOUNT 88 // Mount a filesystem
-#define SYS_SELECT 89 // Wait for file handles
-#define SYS_MARSHALFD 90 // Create a reference to a FD suitable for handing to another process
-#define SYS_UNMARSHALFD 91 // Accept a marshaled FD
+#define SYS_TRUNCATE 75 // Change the size of an open file
+#define SYS_IOCTL 76 // Perform an IOCtl Call
+#define SYS_SEEK 77 // Seek to a new position in the file
+#define SYS_READDIR 78 // Read from an open directory
+#define SYS_GETACL 79 // Get an ACL Value
+#define SYS_SETACL 80 // Set an ACL Value
+#define SYS_FINFO 81 // Get file information
+#define SYS_MKDIR 82 // Create a new directory
+#define SYS_LINK 83 // Create a new link to a file
+#define SYS_SYMLINK 84 // Create a symbolic link
+#define SYS_UNLINK 85 // Delete a file
+#define SYS_TELL 86 // Return the current file position
+#define SYS_CHDIR 87 // Change current directory
+#define SYS_GETCWD 88 // Get current directory
+#define SYS_MOUNT 89 // Mount a filesystem
+#define SYS_SELECT 90 // Wait for file handles
+#define SYS_MMAP 91 // Map a file into this address space
+#define SYS_MUNMAP 92 // Unmap a file
+#define SYS_MARSHALFD 93 // Create a reference to a FD suitable for handing to another process
+#define SYS_UNMARSHALFD 94 // Accept a marshaled FD
-#define NUM_SYSCALLS 92
+#define NUM_SYSCALLS 95
#define SYS_DEBUG 0x100
#define SYS_DEBUGHEX 0x101
"SYS_READAT",
"SYS_WRITE",
"SYS_WRITEAT",
+ "SYS_TRUNCATE",
"SYS_IOCTL",
"SYS_SEEK",
"SYS_READDIR",
"SYS_GETCWD",
"SYS_MOUNT",
"SYS_SELECT",
+ "SYS_MMAP",
+ "SYS_MUNMAP",
"SYS_MARSHALFD",
"SYS_UNMARSHALFD",
%define SYS_READAT 72 ;Read from an open file (with offset)
%define SYS_WRITE 73 ;Write to an open file
%define SYS_WRITEAT 74 ;Write to an open file (with offset)
-%define SYS_IOCTL 75 ;Perform an IOCtl Call
-%define SYS_SEEK 76 ;Seek to a new position in the file
-%define SYS_READDIR 77 ;Read from an open directory
-%define SYS_GETACL 78 ;Get an ACL Value
-%define SYS_SETACL 79 ;Set an ACL Value
-%define SYS_FINFO 80 ;Get file information
-%define SYS_MKDIR 81 ;Create a new directory
-%define SYS_LINK 82 ;Create a new link to a file
-%define SYS_SYMLINK 83 ;Create a symbolic link
-%define SYS_UNLINK 84 ;Delete a file
-%define SYS_TELL 85 ;Return the current file position
-%define SYS_CHDIR 86 ;Change current directory
-%define SYS_GETCWD 87 ;Get current directory
-%define SYS_MOUNT 88 ;Mount a filesystem
-%define SYS_SELECT 89 ;Wait for file handles
-%define SYS_MARSHALFD 90 ;Create a reference to a FD suitable for handing to another process
-%define SYS_UNMARSHALFD 91 ;Accept a marshaled FD
+%define SYS_TRUNCATE 75 ;Change the size of an open file
+%define SYS_IOCTL 76 ;Perform an IOCtl Call
+%define SYS_SEEK 77 ;Seek to a new position in the file
+%define SYS_READDIR 78 ;Read from an open directory
+%define SYS_GETACL 79 ;Get an ACL Value
+%define SYS_SETACL 80 ;Set an ACL Value
+%define SYS_FINFO 81 ;Get file information
+%define SYS_MKDIR 82 ;Create a new directory
+%define SYS_LINK 83 ;Create a new link to a file
+%define SYS_SYMLINK 84 ;Create a symbolic link
+%define SYS_UNLINK 85 ;Delete a file
+%define SYS_TELL 86 ;Return the current file position
+%define SYS_CHDIR 87 ;Change current directory
+%define SYS_GETCWD 88 ;Get current directory
+%define SYS_MOUNT 89 ;Mount a filesystem
+%define SYS_SELECT 90 ;Wait for file handles
+%define SYS_MMAP 91 ;Map a file into this address space
+%define SYS_MUNMAP 92 ;Unmap a file
+%define SYS_MARSHALFD 93 ;Create a reference to a FD suitable for handing to another process
+%define SYS_UNMARSHALFD 94 ;Accept a marshaled FD
* \}
*/
+/**
+ * \name tVFS_NodeType.Type flags
+ * \brief Flags for node types
+ * \{
+ */
+//\! Calls to VFS_Write should not generate calls to .Trunctate
+//\!
+//\! If this flag is set, writing over the end of the file will not call .Truncate automatically
+#define VFS_NODETYPEFLAG_NOAUTOEXPAND 0x001
+//\! Node type describes a stream (offset ignored, seeking disallowed)
+#define VFS_NODETYPEFLAG_STREAM 0x002
+/**
+ * \}
+ */
+
/**
* \brief Functions for a specific node type
*/
*/
const char *TypeName;
+ /**
+ * \brief Flags describing operational quirks
+ */
+ unsigned int Flags;
+
/**
* \name Common Functions
* \brief Functions that are used no matter the value of .Flags
*/
int (*MMap)(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest);
+ /**
+ * \brief Resize a file
+ * \param Node Pointer to this node
+ * \param NewSize New file size
+ * \return Actual new file size
+ * \note If NULL, \a Write may be called with Offset + Length > Size
+ *
+ * Called to increase/decrease the size of a file. If the
+ */
+ off_t (*Truncate)(struct sVFS_Node *Node, off_t NewSize);
+
/**
* \}
*/
*/
extern size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer);
+/**
+ * \brief Set the valid size of a file
+ * \param FD File descriptor
+ * \param Size New file size
+ * \return Actual new file size (-1 if error occurred)
+ *
+ * \note Not all files support this call (will return ENOTIMPL)
+ */
+extern off_t VFS_Truncate(int FD, off_t Size);
+
/**
* \brief Sends an IOCtl request to the driver
* \param FD File handle returned by ::VFS_Open
#endif
break;
+ case SYS_TRUNCATE:
+ ret = VFS_Truncate(
+ Regs->Arg1,
+ #if BITS == 32
+ ARG64(2,3)
+ #else
+ Regs->Arg2
+ #endif
+ );
+ break;
+
case SYS_FINFO:
CHECK_NUM_NONULL( (void*)Regs->Arg2, sizeof(tFInfo) + Regs->Arg3*sizeof(tVFS_ACL) );
// FP, Dest, MaxACLs
);
break;
+ case SYS_MMAP:
+ ret = (tVAddr)VFS_MMap(
+ (void*)Regs->Arg1, Regs->Arg2,
+ Regs->Arg3&0xFFFF, Regs->Arg3>>16,
+ Regs->Arg4,
+ #if BITS == 32
+ ARG64(5,6)
+ #else
+ Regs->Arg5
+ #endif
+ );
+ break;
+ case SYS_MUNMAP:
+ ret = VFS_MUnmap( (void*)Regs->Arg1, Regs->Arg2 );
+ break;
// Create a directory
case SYS_MKDIR:
SYS_READAT Read from an open file (with offset)
SYS_WRITE Write to an open file
SYS_WRITEAT Write to an open file (with offset)
+SYS_TRUNCATE Change the size of an open file
SYS_IOCTL Perform an IOCtl Call
SYS_SEEK Seek to a new position in the file
SYS_READDIR Read from an open directory
SYS_GETCWD Get current directory
SYS_MOUNT Mount a filesystem
SYS_SELECT Wait for file handles
-
+SYS_MMAP Map a file into this address space
+SYS_MUNMAP Unmap a file
SYS_MARSHALFD Create a reference to a FD suitable for handing to another process
SYS_UNMARSHALFD Accept a marshaled FD
*/
size_t VFS_Write(int FD, size_t Length, const void *Buffer)
{
- tVFS_Handle *h;
- size_t ret;
-
- h = VFS_GetHandle(FD);
+ tVFS_Handle *h = VFS_GetHandle(FD);
if(!h) {
LOG("FD%i is not open", FD);
errno = EBADF;
return -1;
}
+ size_t ret = VFS_WriteAt(FD, h->Position, Length, Buffer);
+ if(ret == (size_t)-1) return -1;
+
+ if( !(h->Node->Type->Flags & VFS_NODETYPEFLAG_STREAM) )
+ h->Position += ret;
+ return ret;
+}
+
+/**
+ * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
+ * \brief Write data to a file at a given offset
+ */
+size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
+{
+ LOG("FD=%i,Offset=%lli,Length=%i,Buffer=%p",
+ FD, Offset, Length, Buffer);
+ tVFS_Handle *h = VFS_GetHandle(FD);
+ if(!h) return -1;
+
if( !(h->Mode & VFS_OPENFLAG_WRITE) ) {
LOG("FD%i not opened for writing", FD);
errno = EBADF;
return -1;
}
- if( !h->Node->Type || !h->Node->Type->Write ) {
+ const tVFS_NodeType* nodetype = h->Node->Type;
+ if(!nodetype || !nodetype->Write) {
LOG("FD%i has no write method", FD);
errno = EINTERNAL;
return 0;
}
-
- if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
+
+ if( !MM_GetPhysAddr(nodetype->Write) ) {
Log_Error("VFS", "Node type %p(%s) write method is junk %p",
- h->Node->Type, h->Node->Type->TypeName,
- h->Node->Type->Write);
+ nodetype, nodetype->TypeName, nodetype->Write);
errno = EINTERNAL;
return -1;
}
- 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 != Length) LOG("%i/%i written", ret, Length);
- if(ret == (size_t)-1) return -1;
-
- h->Position += ret;
- return ret;
-}
-
-/**
- * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
- * \brief Write data to a file at a given offset
- */
-size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
-{
- tVFS_Handle *h;
- size_t ret;
-
- h = VFS_GetHandle(FD);
- if(!h) return -1;
-
- if( !(h->Mode & VFS_OPENFLAG_WRITE) ) return -1;
- if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1;
-
- 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->Type->TypeName,
- h->Node->Type->Write);
- return -1;
+ // Bounds checks
+ if( h->Node->Size != (Uint64)-1 && Offset > h->Node->Size ) {
+ Log_Notice("VFS", "Write starting past EOF of FD%x (%lli > %lli)",
+ FD, Offset, h->Node->Size);
+ //errno = ESPIPE;
+ return 0;
+ }
+ if( Offset + Length > h->Node->Size )
+ {
+ // Going OOB
+ if( !nodetype->Truncate )
+ {
+ LOG("No .Truncate method, emiting write past EOF");
+ }
+ else if( nodetype->Flags & VFS_NODETYPEFLAG_NOAUTOEXPAND )
+ {
+ LOG("NOAUTOEXPAND set, truncating length from %i to %i",
+ Length, h->Node->Size - Offset);
+ Length = h->Node->Size - Offset;
+ }
+ else if( nodetype->Truncate(h->Node, Offset + Length) != Offset + Length )
+ {
+ // oh... fail? Truncate to current size
+ LOG(".Truncate failed, truncating length from %i to %i",
+ Length, h->Node->Size - Offset);
+ Length = h->Node->Size - Offset;
+ }
+ else
+ {
+ // Expansion, node size should now fit
+ LOG("Expanded file");
+ }
}
+
+ // Create flag set
Uint flags = 0;
flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
- ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer, flags);
+
+ // Dispatch the read!
+ size_t ret = nodetype->Write(h->Node, Offset, Length, Buffer, flags);
if(ret == (size_t)-1) return -1;
+ if(ret != Length) LOG("%i/%i written", ret, Length);
+
return ret;
}
*/
int VFS_Seek(int FD, Sint64 Offset, int Whence)
{
- tVFS_Handle *h;
-
- h = VFS_GetHandle(FD);
+ tVFS_Handle *h = VFS_GetHandle(FD);
if(!h) return -1;
+ if( (h->Node->Type->Flags & VFS_NODETYPEFLAG_STREAM) ) {
+ LOG("Seeking in stream");
+ return -1;
+ }
+
// Set relative to current position
if(Whence == 0) {
LOG("(FD%x)->Position += %lli", FD, Offset);
return 0;
}
+/*
+ * Truncate/Expand a file's allocation
+ */
+off_t VFS_Truncate(int FD, off_t Size)
+{
+ tVFS_Handle *h = VFS_GetHandle(FD);
+ if(!h) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if( !h->Node->Type->Truncate)
+ {
+ errno = ENOTIMPL;
+ return -1;
+ }
+
+ return h->Node->Type->Truncate(h->Node, Size);
+}
+
/**
* \fn int VFS_IOCtl(int FD, int ID, void *Buffer)
* \brief Call an IO Control on a file
*/
int VFS_IOCtl(int FD, int ID, void *Buffer)
{
- tVFS_Handle *h;
-
- h = VFS_GetHandle(FD);
+ tVFS_Handle *h = VFS_GetHandle(FD);
if(!h) {
LOG("FD%i is invalid", FD);
errno = EINVAL;
// === PROTOTYPES ===
//void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset);
void *VFS_MMap_Anon(void *Destination, size_t Length, Uint FlagsSet, Uint FlagsMask);
+int VFS_MMap_MapPage(tVFS_Node *Node, unsigned int PageNum, tVFS_MMapPageBlock *pb, void *mapping_dest, unsigned int Protection);
//int VFS_MUnmap(void *Addr, size_t Length);
// === CODE ===
void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset)
{
- tVAddr mapping_base;
- int npages, pagenum;
- tVFS_MMapPageBlock *pb, *prev;
-
ENTER("pDestHint iLength xProtection xFlags xFD XOffset", DestHint, Length, Protection, Flags, FD, Offset);
if( Flags & MMAP_MAP_ANONYMOUS )
Offset = (tVAddr)DestHint & 0xFFF;
- npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
- pagenum = Offset / PAGE_SIZE;
+ unsigned int npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
+ unsigned int pagenum = Offset / PAGE_SIZE;
- mapping_base = (tVAddr)DestHint;
- tPage *mapping_dest = (void*)(mapping_base & ~(PAGE_SIZE-1));
+ tVAddr mapping_base = (tVAddr)DestHint;
- if( DestHint == NULL )
+ if( Flags & MMAP_MAP_FIXED )
+ {
+ ASSERT( (Flags & MMAP_MAP_FIXED) && DestHint != NULL );
+ // Keep and use the hint
+ // - TODO: Validate that the region pointed to by the hint is correct
+ }
+ else
{
- // TODO: Locate space for the allocation
- LEAVE('n');
- return NULL;
+ Log_Warning("VFS", "MMap: TODO Handle non-fixed mappings");
+ if( DestHint == NULL )
+ {
+ // TODO: Locate space for the allocation
+ Log_Warning("VFS", "Mmap: Handle NULL destination hint");
+ LEAVE('n');
+ return NULL;
+ }
}
+ tPage *mapping_dest = (void*)(mapping_base & ~(PAGE_SIZE-1));
// Handle anonymous mappings
if( Flags & MMAP_MAP_ANONYMOUS )
Mutex_Acquire( &h->Node->Lock );
+ tVFS_MMapPageBlock *pb, **pb_pnp = (tVFS_MMapPageBlock**)&h->Node->MMapInfo;
// Search for existing mapping for each page
// - Sorted list of 16 page blocks
- for(
- pb = h->Node->MMapInfo, prev = NULL;
- pb && pb->BaseOffset + MMAP_PAGES_PER_BLOCK <= pagenum;
- prev = pb, pb = pb->Next
- )
- ;
+ for( pb = h->Node->MMapInfo; pb; pb_pnp = &pb->Next, pb = pb->Next )
+ {
+ if( pb->BaseOffset + MMAP_PAGES_PER_BLOCK <= pagenum )
+ break;
+ }
LOG("pb = %p, pb->BaseOffset = %X", pb, pb ? pb->BaseOffset : 0);
}
pb->Next = old_pb;
pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK;
- if(prev)
- prev->Next = pb;
- else
- h->Node->MMapInfo = pb;
+ *pb_pnp = pb;
}
// - Map (and allocate) pages
while( npages -- )
{
- assert( pagenum >= pb->BaseOffset );
- assert( pagenum - pb->BaseOffset < MMAP_PAGES_PER_BLOCK );
+ ASSERTC( pagenum, >=, pb->BaseOffset );
+ ASSERTC( pagenum - pb->BaseOffset, <, MMAP_PAGES_PER_BLOCK );
if( MM_GetPhysAddr( mapping_dest ) == 0 )
{
- if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 )
- {
- tVFS_NodeType *nt = h->Node->Type;
- if( !nt )
- {
- // TODO: error
- }
- else if( nt->MMap )
- nt->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest);
- else
- {
- int read_len;
- // Allocate pages and read data
- if( MM_Allocate(mapping_dest) == 0 ) {
- // TODO: Unwrap
- Mutex_Release( &h->Node->Lock );
- LEAVE('n');
- return NULL;
- }
- // TODO: Clip read length
- read_len = nt->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE,
- mapping_dest, 0);
- // TODO: This was commented out, why?
- if( read_len != PAGE_SIZE ) {
- memset( (char*)mapping_dest + read_len, 0, PAGE_SIZE-read_len );
- }
- }
- pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
- MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], h->Node );
- MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
- LOG("Read and map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
- pb->PhysAddrs[pagenum - pb->BaseOffset]);
- }
- else
+ LOG("Map page to %p", mapping_dest);
+ if( VFS_MMap_MapPage(h->Node, pagenum, pb, mapping_dest, Protection) )
{
- MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
- MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
- LOG("Cached map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
- pb->PhysAddrs[pagenum - pb->BaseOffset]);
- }
- h->Node->ReferenceCount ++;
-
- // Set flags
- if( !(Protection & MMAP_PROT_WRITE) ) {
- MM_SetFlags(mapping_dest, MM_PFLAG_RO, MM_PFLAG_RO);
- }
- else {
- MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
- }
-
- if( Protection & MMAP_PROT_EXEC ) {
- MM_SetFlags(mapping_dest, MM_PFLAG_EXEC, MM_PFLAG_EXEC);
- }
- else {
- MM_SetFlags(mapping_dest, 0, MM_PFLAG_EXEC);
+ Mutex_Release( &h->Node->Lock );
+ LEAVE('n');
+ return NULL;
}
}
else
MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
}
}
- if( Flags & MMAP_MAP_PRIVATE )
+ if( Flags & MMAP_MAP_PRIVATE ) {
+ // TODO: Don't allow the page to change underneath either
MM_SetFlags(mapping_dest, MM_PFLAG_COW, MM_PFLAG_COW);
+ }
pagenum ++;
mapping_dest ++;
// Roll on to next block if needed
if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK)
{
- if( pb->Next && pb->Next->BaseOffset == pagenum )
- pb = pb->Next;
- else
+ if( !pb->Next || pb->Next->BaseOffset != pagenum )
{
- tVFS_MMapPageBlock *oldpb = pb;
- pb = malloc( sizeof(tVFS_MMapPageBlock) );
- pb->Next = oldpb->Next;
- pb->BaseOffset = pagenum;
- memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
- oldpb->Next = pb;
+ if( pb->Next ) ASSERTC(pb->Next->BaseOffset % MMAP_PAGES_PER_BLOCK, ==, 0);
+ tVFS_MMapPageBlock *newpb = malloc( sizeof(tVFS_MMapPageBlock) );
+ newpb->Next = pb->Next;
+ newpb->BaseOffset = pagenum;
+ memset(newpb->PhysAddrs, 0, sizeof(newpb->PhysAddrs));
+ pb->Next = newpb;
}
+
+ pb = pb->Next;
}
}
return Destination;
}
+int VFS_MMap_MapPage(tVFS_Node *Node, unsigned int pagenum, tVFS_MMapPageBlock *pb, void *mapping_dest, unsigned int Protection)
+{
+ if( pb->PhysAddrs[pagenum - pb->BaseOffset] != 0 )
+ {
+ MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
+ MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
+ LOG("Cached map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
+ pb->PhysAddrs[pagenum - pb->BaseOffset]);
+ }
+ else
+ {
+ tVFS_NodeType *nt = Node->Type;
+ if( !nt )
+ {
+ // TODO: error
+ }
+ else if( nt->MMap )
+ nt->MMap(Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest);
+ else
+ {
+ int read_len;
+ // Allocate pages and read data
+ if( MM_Allocate(mapping_dest) == 0 ) {
+ // TODO: Unwrap
+ return 1;
+ }
+ // TODO: Clip read length
+ read_len = nt->Read(Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest, 0);
+ // TODO: This was commented out, why?
+ if( read_len != PAGE_SIZE ) {
+ memset( (char*)mapping_dest + read_len, 0, PAGE_SIZE-read_len );
+ }
+ }
+ pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
+ MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], Node );
+ MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
+ LOG("Read and map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
+ pb->PhysAddrs[pagenum - pb->BaseOffset]);
+ }
+ // TODO: Huh?
+ Node->ReferenceCount ++;
+
+ // Set flags
+ if( !(Protection & MMAP_PROT_WRITE) ) {
+ MM_SetFlags(mapping_dest, MM_PFLAG_RO, MM_PFLAG_RO);
+ }
+ else {
+ MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
+ }
+
+ if( Protection & MMAP_PROT_EXEC ) {
+ MM_SetFlags(mapping_dest, MM_PFLAG_EXEC, MM_PFLAG_EXEC);
+ }
+ else {
+ MM_SetFlags(mapping_dest, 0, MM_PFLAG_EXEC);
+ }
+
+ return 0;
+}
+
int VFS_MUnmap(void *Addr, size_t Length)
{
return 0;
\r
Mutex_Release( &glVesa_Lock );\r
\r
- // TODO: Disableable backbuffer\r
- gVesa_BufInfo.BackBuffer = realloc(gVesa_BufInfo.BackBuffer,\r
- modeptr->height * modeptr->pitch);\r
+ // TODO: Allow disabling of back-buffer\r
+ gVesa_DriverStruct.RootNode.Size = modeptr->height * modeptr->pitch;\r
+ gVesa_BufInfo.BackBuffer = realloc(gVesa_BufInfo.BackBuffer, modeptr->height * modeptr->pitch);\r
gVesa_BufInfo.Framebuffer = gpVesa_Framebuffer;\r
gVesa_BufInfo.Pitch = modeptr->pitch;\r
gVesa_BufInfo.Width = modeptr->width;\r
};
tVFS_NodeType gTCP_ClientNodeType = {
.TypeName = "TCP Client/Connection",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = TCP_Client_Read,
.Write = TCP_Client_Write,
.IOCtl = TCP_Client_IOCtl,
// === GLOBALS ===
tVFS_NodeType gUDP_NodeType = {
+ .TypeName = "UDP",
+ .Flags = VFS_NODETYPEFLAG_STREAM,
.Read = UDP_Channel_Read,
.Write = UDP_Channel_Write,
.IOCtl = UDP_Channel_IOCtl,
tUDPChannel *new;
new = calloc( sizeof(tUDPChannel), 1 );
new->Interface = Interface;
+ new->Node.Size = -1;
new->Node.ImplPtr = new;
new->Node.NumACLs = 1;
new->Node.ACLs = &gVFS_ACL_EveryoneRW;
SYSCALL5(_SysReadAt, SYS_READAT) // int, uint, uint64, void*
SYSCALL3(_SysWrite, SYS_WRITE) // int, uint, void*
SYSCALL5(_SysWriteAt, SYS_WRITEAT) // int, uint, uint64, void*
+SYSCALL3(_SysTruncate, SYS_TRUNCATE) // int, uint64
SYSCALL4(_SysSeek, SYS_SEEK) // int, uint64_t, int
SYSCALL1(_SysTell, SYS_TELL) // int
SYSCALL3(_SysFInfo, SYS_FINFO) // int, void*, int
SYSCALL1(_SysMkDir, SYS_MKDIR) // const char*
SYSCALL1(_SysUnlink, SYS_UNLINK) // const char*
+SYSCALL6(_SysMMap, SYS_MMAP)
+SYSCALL2(_SysMUnMap, SYS_MUNMAP)
+
+SYSCALL1(_SysMarshalFD, SYS_MARSHALFD)
+SYSCALL2(_SysUnMarshalFD, SYS_UNMARSHALFD)
+
#define FILEFLAG_SYMLINK 0x20
#define CLONE_VM 0x10
+#define MMAP_PROT_READ 0x001 //!< Readable memory
+#define MMAP_PROT_WRITE 0x002 //!< Writable memory
+#define MMAP_PROT_EXEC 0x004 //!< Executable memory
+#define MMAP_MAP_SHARED 0x001 //!< Shared with all other users of the FD
+#define MMAP_MAP_PRIVATE 0x002 //!< Local (COW) copy
+#define MMAP_MAP_FIXED 0x004 //!< Load to a fixed address
+#define MMAP_MAP_ANONYMOUS 0x008 //!< Not associated with a FD
+
#ifdef ARCHDIR_is_native
# include "_native_syscallmod.h"
#endif
extern int _SysFDFlags(int fd, int mask, int newflags);
extern size_t _SysRead(int fd, void *buffer, size_t length);
extern size_t _SysReadAt(int fd, uint64_t offset, size_t length, void *buffer);
+extern uint64_t _SysTruncate(int fd, uint64_t size);
extern int _SysClose(int fd);
extern int _SysFDCtl(int fd, int option, ...);
extern size_t _SysWrite(int fd, const void *buffer, size_t length);
//#define select(nfs, rdfds, wrfds, erfds, timeout) _SysSelect(nfs, rdfds, wrfds, erfds, timeout, 0)
extern int _SysMkDir(const char *dirname);
extern int _SysUnlink(const char *pathname);
+extern void* _SysMMap(void *addr, size_t length, unsigned int _flags, int fd, uint64_t offset);
+#define _SysMMap(addr,length,flags,prot,fd,offset) _SysMMap(addr,length,(flags|(prot<<16)), fd, offset)
+extern int _SysMUnMap(void *addr, size_t length);
+extern uint64_t _SysMarshalFD(int FD);
+extern int _SysUnMarshalFD(uint64_t Handle);
// --- IPC ---
extern int _SysSendMessage(int dest, size_t length, const void *Data);