*/
extern int VFS_OpenInode(Uint32 Mount, Uint64 Inode, int Mode);
+/**
+ * \brief Open a file reusing an old FD
+ */
+extern int VFS_Reopen(int FD, const char *Path, int Flags);
+
/**
* \brief Close a currently open file
* \param FD Handle returned by ::VFS_Open
if(Node && Node->Type && Node->Type->Close)
Node->Type->Close( Node );
}
+static inline void _ReferenceNode(tVFS_Node *Node)
+{
+ if( !MM_GetPhysAddr(Node->Type) ) {
+ Log_Error("VFS", "Node %p's type is invalid (%p bad pointer) - %P corrupted",
+ Node, Node->Type, MM_GetPhysAddr(&Node->Type));
+ return ;
+ }
+ if( Node->Type && Node->Type->Reference )
+ Node->Type->Reference( Node );
+ else
+ Node->ReferenceCount ++;
+}
#endif
LOG("VFS_Open(\"%s\", 0x%x)", (char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER);
ret = VFS_Open((char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER);
break;
+ case SYS_REOPEN:
+ CHECK_STR_NONULL( (char*)Regs->Arg2 );
+ LOG("VFS_Reopen(%i, \"%s\", 0x%x)", Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3 | VFS_OPENFLAG_USER);
+ ret = VFS_Reopen(Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3 | VFS_OPENFLAG_USER);
+ break;
case SYS_CLOSE:
LOG("VFS_Close(%i)", Regs->Arg1);
#define MAX_KERNEL_FILES 128
// === PROTOTYPES ===
-inline void _ReferenceNode(tVFS_Node *Node);
// === GLOBALS ===
tVFS_Handle *gaUserHandles = (void*)MM_PPD_HANDLES;
tVFS_Handle *gaKernelHandles = (void*)MM_KERNEL_VFS;
// === CODE ===
-inline void _ReferenceNode(tVFS_Node *Node)
-{
- if( !MM_GetPhysAddr(Node->Type) ) {
- Log_Error("VFS", "Node %p's type is invalid (%p bad pointer) - %P corrupted",
- Node, Node->Type, MM_GetPhysAddr(&Node->Type));
- return ;
- }
- if( Node->Type && Node->Type->Reference )
- Node->Type->Reference( Node );
- else
- Node->ReferenceCount ++;
-}
-
/**
* \fn tVFS_Handle *VFS_GetHandle(int FD)
* \brief Gets a pointer to the handle information structure
LEAVE_RET('x', VFS_int_CreateHandle(node, mnt, Mode));
}
+int VFS_Reopen(int FD, const char *Path, int Flags)
+{
+ tVFS_Handle *h = VFS_GetHandle(FD);
+ if(!h) {
+ errno = EBADF;
+ return -1;
+ }
+
+ int newf = VFS_Open(Path, Flags);
+ if( newf == -1 ) {
+ return -1;
+ }
+
+ _CloseNode(h->Node);
+ _DereferenceMount(h->Mount, "Reopen");
+ memcpy(h, VFS_GetHandle(newf), sizeof(*h));
+ _ReferenceNode(h->Node);
+ _ReferenceMount(h->Mount, "Reopen");
+
+ VFS_Close(newf);
+
+ return FD;
+}
+
/**
* \fn void VFS_Close(int FD)
* \brief Closes an open file handle
return -1;
VFS_SetHandle(DstFD, src->Node, src->Mode);
}
+ _ReferenceMount(src->Mount, "DuplicateFD");
+ _ReferenceNode(src->Node);
memcpy(VFS_GetHandle(DstFD), src, sizeof(tVFS_Handle));
return DstFD;
}