From: John Hodge Date: Wed, 15 May 2013 08:12:34 +0000 (+0800) Subject: Kernel - Working on SYS_COPYFD X-Git-Tag: rel0.15~479^2 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=b60e6b273c3ecb1614d937bf9448033e9d339e83;p=tpg%2Facess2.git Kernel - Working on SYS_COPYFD --- diff --git a/KernelLand/Kernel/include/vfs_ext.h b/KernelLand/Kernel/include/vfs_ext.h index 2cd41010..1bae964f 100644 --- a/KernelLand/Kernel/include/vfs_ext.h +++ b/KernelLand/Kernel/include/vfs_ext.h @@ -226,6 +226,13 @@ extern int VFS_OpenInode(Uint32 Mount, Uint64 Inode, int Mode); */ extern void VFS_Close(int FD); +/** + * \brief Copy one FD to another + * \param SrcFD Source file descriptor + * \param DstFD Destination file descriptor (-1 means allocate new) + */ +extern int VFS_DuplicateFD(int SrcFD, int DstFD); + /** * \brief Get file information from an open file * \param FD File handle returned by ::VFS_Open diff --git a/KernelLand/Kernel/include/vfs_int.h b/KernelLand/Kernel/include/vfs_int.h index 232c55e4..06ad8dab 100644 --- a/KernelLand/Kernel/include/vfs_int.h +++ b/KernelLand/Kernel/include/vfs_int.h @@ -62,6 +62,9 @@ extern int VFS_CheckACL(tVFS_Node *Node, Uint Permissions); extern tVFS_Mount *VFS_GetMountByIdent(Uint32 MountID); // --- dir.c --- extern int VFS_MkNod(const char *Path, Uint Flags); +// --- handle.c --- +extern int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode); +extern int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode); // --- VFS Helpers --- diff --git a/KernelLand/Kernel/syscalls.c b/KernelLand/Kernel/syscalls.c index 635f69ac..4416ec4f 100644 --- a/KernelLand/Kernel/syscalls.c +++ b/KernelLand/Kernel/syscalls.c @@ -214,6 +214,11 @@ void SyscallHandler(tSyscallRegs *Regs) VFS_Close( Regs->Arg1 ); break; + case SYS_COPYFD: + LOG("VFS_DuplicateFD(%i,%i)", Regs->Arg1, Regs->Arg2); + ret = VFS_DuplicateFD(Regs->Arg1, Regs->Arg2); + break; + case SYS_SEEK: #if BITS == 64 ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3 ); diff --git a/KernelLand/Kernel/vfs/handle.c b/KernelLand/Kernel/vfs/handle.c index cb4fae12..35aa00c8 100644 --- a/KernelLand/Kernel/vfs/handle.c +++ b/KernelLand/Kernel/vfs/handle.c @@ -16,11 +16,7 @@ #define MAX_KERNEL_FILES 128 // === PROTOTYPES === -#if 0 -tVFS_Handle *VFS_GetHandle(int FD); -#endif inline void _ReferenceNode(tVFS_Node *Node); - int VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode); // === GLOBALS === tVFS_Handle *gaUserHandles = (void*)MM_PPD_HANDLES; @@ -66,10 +62,27 @@ tVFS_Handle *VFS_GetHandle(int FD) return h; } -int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) +int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode) { - int i; + tVFS_Handle *h; + if(FD < 0) return -1; + if( FD & VFS_KERNEL_FLAG ) { + FD &= (VFS_KERNEL_FLAG -1); + if( FD >= MAX_KERNEL_FILES ) return -1; + h = &gaKernelHandles[FD]; + } + else { + if( FD >= *Threads_GetMaxFD()) return -1; + h = &gaUserHandles[FD]; + } + h->Node = Node; + h->Mode = Mode; + return FD; +} + +int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) +{ // Check for a user open if(bIsUser) { @@ -90,7 +103,7 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) memset( gaUserHandles, 0, size ); } // Get a handle - for( i = 0; i < max_handles; i ++ ) + for( int i = 0; i < max_handles; i ++ ) { if(gaUserHandles[i].Node) continue; gaUserHandles[i].Node = Node; @@ -117,7 +130,7 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) memset( gaKernelHandles, 0, size ); } // Get a handle - for(i=0;iNode = NULL; } +int VFS_DuplicateFD(int SrcFD, int DstFD) +{ + int isUser = !(SrcFD & VFS_KERNEL_FLAG); + tVFS_Handle *src = VFS_GetHandle(SrcFD); + if( !src ) return -1; + if( DstFD == -1 ) { + DstFD = VFS_AllocHandle(isUser, src->Node, src->Mode); + } + else { + // Can't overwrite + if( VFS_GetHandle(DstFD) ) + return -1; + VFS_SetHandle(DstFD, src->Node, src->Mode); + } + memcpy(VFS_GetHandle(DstFD), src, sizeof(tVFS_Handle)); + return DstFD; +} + /** * \brief Change current working directory */