void VFS_RestoreHandles(int NumFDs, void *Handles) { tVFS_Handle *handles = Handles; int i; // NULL = nothing to do if( !Handles ) return ; // Check if there is already a set of handles if( MM_GetPhysAddr( gaUserHandles ) != 0 ) return ; // Allocate user handle area { Uint addr, size; int max_handles = *Threads_GetMaxFD(); size = max_handles * sizeof(tVFS_Handle); for(addr = 0; addr < size; addr += 0x1000) { if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) ) { Warning("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate user } } memset( gaUserHandles, 0, size ); } // Restore handles memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) ); // Reference when copied for( i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h = &handles[i]; if( !h->Node ) continue ; _ReferenceNode(h->Node); h->Mount->OpenHandleCount ++; } }
int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) { // Check for a user open if(bIsUser) { int max_handles = *Threads_GetMaxFD(NULL); // Allocate Buffer if( MM_GetPhysAddr( gaUserHandles ) == 0 ) { tPage *pageptr = (void*)gaUserHandles; size_t size = max_handles * sizeof(tVFS_Handle); for( size_t ofs = 0; ofs < size; ofs ++) { if( !MM_Allocate( pageptr ) ) { Warning("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate user } pageptr ++; } memset( gaUserHandles, 0, size ); } // Get a handle for( int i = 0; i < max_handles; i ++ ) { if(gaUserHandles[i].Node) continue; gaUserHandles[i].Node = Node; gaUserHandles[i].Position = 0; gaUserHandles[i].Mode = Mode; return i; } } else { // Allocate space if not already if( MM_GetPhysAddr( gaKernelHandles ) == 0 ) { tPage *pageptr = (void*)gaKernelHandles; size_t size = MAX_KERNEL_FILES * sizeof(tVFS_Handle); for(size_t ofs = 0; ofs < size; ofs += size) { if( !MM_Allocate( pageptr ) ) { Panic("OOM - VFS_AllocHandle"); } pageptr ++; } memset( gaKernelHandles, 0, size ); } // Get a handle for(int i=0;i<MAX_KERNEL_FILES;i++) { if(gaKernelHandles[i].Node) continue; gaKernelHandles[i].Node = Node; gaKernelHandles[i].Position = 0; gaKernelHandles[i].Mode = Mode; return i|VFS_KERNEL_FLAG; } } return -1; }
void VFS_RestoreHandles(int NumFDs, void *Handles) { tVFS_Handle *handles = Handles; const int max_handles = *Threads_GetMaxFD(NULL); // NULL = nothing to do if( !Handles ) return ; if( NumFDs > max_handles ) { Log_Notice("VFS", "RestoreHandles: Capping from %i FDs to %i", NumFDs, max_handles); NumFDs = max_handles; } // Allocate user handle area (and dereference existing handles) for( int i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h = &gaUserHandles[i]; if( !MM_GetPhysAddr(h) ) { void *pg = (void*)( (tVAddr)h & ~(PAGE_SIZE-1) ); if( !MM_Allocate( pg ) ) { // OOM? return ; } memset(pg, 0, PAGE_SIZE); } // Safe to dereference, as Threads_CloneTCB references handles #if 1 else { if(h->Node) { _CloseNode(h->Node); h->Mount->OpenHandleCount --; } } #endif } // Clean up existing // Restore handles memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) ); // Reference when copied for( int i = 0; i < NumFDs; i ++ ) { tVFS_Handle *h = &gaUserHandles[i]; if( !h->Node ) continue ; // Debug("VFS_RestoreHandles: %i %p", i, h->Node); _ReferenceNode(h->Node); h->Mount->OpenHandleCount ++; } for( int i = NumFDs; i < max_handles; i ++ ) { gaUserHandles[i].Node = NULL; } }
int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) { // Check for a user open if(bIsUser) { int max_handles = *Threads_GetMaxFD(); // Allocate Buffer if( MM_GetPhysAddr( gaUserHandles ) == 0 ) { Uint addr, size; size = max_handles * sizeof(tVFS_Handle); for(addr = 0; addr < size; addr += 0x1000) { if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) ) { Warning("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate user } } memset( gaUserHandles, 0, size ); } // Get a handle for( int i = 0; i < max_handles; i ++ ) { if(gaUserHandles[i].Node) continue; gaUserHandles[i].Node = Node; gaUserHandles[i].Position = 0; gaUserHandles[i].Mode = Mode; return i; } } else { // Allocate space if not already if( MM_GetPhysAddr( gaKernelHandles ) == 0 ) { Uint addr, size; size = MAX_KERNEL_FILES * sizeof(tVFS_Handle); for(addr = 0; addr < size; addr += 0x1000) { if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) ) { Panic("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate application (get some space back) } } memset( gaKernelHandles, 0, size ); } // Get a handle for(int i=0;i<MAX_KERNEL_FILES;i++) { if(gaKernelHandles[i].Node) continue; gaKernelHandles[i].Node = Node; gaKernelHandles[i].Position = 0; gaKernelHandles[i].Mode = Mode; return i|VFS_KERNEL_FLAG; } } return -1; }