int dup(int oldfdnum, int newfdnum) { int i, r; u_int ova, nva, pte; struct Fd *oldfd, *newfd; if ((r = fd_lookup(oldfdnum, &oldfd)) < 0) { return r; } close(newfdnum); newfd = (struct Fd *)INDEX2FD(newfdnum); ova = fd2data(oldfd); nva = fd2data(newfd); if ((r = syscall_mem_map(0, (u_int)oldfd, 0, (u_int)newfd, ((*vpt)[VPN(oldfd)]) & (PTE_V | PTE_R | PTE_LIBRARY))) < 0) { goto err; } if ((* vpd)[PDX(ova)]) { for (i = 0; i < PDMAP; i += BY2PG) { pte = (* vpt)[VPN(ova + i)]; if (pte & PTE_V) { // should be no error here -- pd is already allocated if ((r = syscall_mem_map(0, ova + i, 0, nva + i, pte & (PTE_V | PTE_R | PTE_LIBRARY))) < 0) { goto err; } } } } return newfdnum; err: syscall_mem_unmap(0, (u_int)newfd); for (i = 0; i < PDMAP; i += BY2PG) { syscall_mem_unmap(0, nva + i); } return r; }
void serve(void) { u_int req, whom, perm; for (;;) { perm = 0; req = ipc_recv(&whom, REQVA, &perm); // All requests must contain an argument page if (!(perm & PTE_V)) { writef("Invalid request from %08x: no argument page\n", whom); continue; // just leave it hanging... } switch (req) { case FSREQ_OPEN: serve_open(whom, (struct Fsreq_open *)REQVA); break; case FSREQ_MAP: serve_map(whom, (struct Fsreq_map *)REQVA); break; case FSREQ_SET_SIZE: serve_set_size(whom, (struct Fsreq_set_size *)REQVA); break; case FSREQ_CLOSE: serve_close(whom, (struct Fsreq_close *)REQVA); break; case FSREQ_DIRTY: serve_dirty(whom, (struct Fsreq_dirty *)REQVA); break; case FSREQ_REMOVE: serve_remove(whom, (struct Fsreq_remove *)REQVA); break; case FSREQ_SYNC: serve_sync(whom); break; default: writef("Invalid request code %d from %08x\n", whom, req); break; } syscall_mem_unmap(0, REQVA); } }
void fd_close(struct Fd *fd) { syscall_mem_unmap(0, (u_int)fd); }