file_t __getdport (int fd) { if (_hurd_getdport_fn) /* dtable.c has defined the function to fetch a port from the real file descriptor table. */ return (*_hurd_getdport_fn) (fd); /* getdport is the only use of file descriptors, so we don't bother allocating a real table. */ if (_hurd_init_dtable == NULL) { /* Never had a descriptor table. */ errno = EBADF; return MACH_PORT_NULL; } if (fd < 0 || (unsigned int) fd > _hurd_init_dtablesize || _hurd_init_dtable[fd] == MACH_PORT_NULL) { errno = EBADF; return MACH_PORT_NULL; } else { __mach_port_mod_refs (__mach_task_self (), _hurd_init_dtable[fd], MACH_PORT_RIGHT_SEND, 1); return _hurd_init_dtable[fd]; } }
/* Called by MiG to deallocate the reply port. */ void __mig_dealloc_reply_port (void) { mach_port_t port = reply_port; reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */ __mach_port_mod_refs (__mach_task_self (), port, MACH_PORT_RIGHT_RECEIVE, -1); }
kern_return_t __get_privileged_ports (mach_port_t *host_priv_ptr, device_t *device_master_ptr) { if ((host_priv_ptr && _hurd_host_priv == MACH_PORT_NULL) || (device_master_ptr && _hurd_device_master == MACH_PORT_NULL)) { error_t err; if (_hurd_ports) /* We have gotten some initial ports, so perhaps we have a proc server to talk to. */ err = __USEPORT (PROC, __proc_getprivports (port, &_hurd_host_priv, &_hurd_device_master)); else return MACH_SEND_INVALID_DEST; if (err) return err; } if (host_priv_ptr) { error_t err = _hurd_host_priv == MACH_PORT_NULL ? 0 : __mach_port_mod_refs (mach_task_self (), _hurd_host_priv, MACH_PORT_RIGHT_SEND, +1); if (err) return err; *host_priv_ptr = _hurd_host_priv; } if (device_master_ptr) { error_t err = _hurd_device_master == MACH_PORT_NULL ? 0 : __mach_port_mod_refs (mach_task_self (), _hurd_device_master, MACH_PORT_RIGHT_SEND, +1); if (err) return err; *device_master_ptr = _hurd_device_master; } return KERN_SUCCESS; }
error_t _hurd_ports_get (unsigned int which, mach_port_t *result) { if (which >= _hurd_nports) return EINVAL; if (which >= INIT_PORT_MAX || _hurd_ports_getters[which] == NULL) return HURD_PORT_USE (&_hurd_ports[which], (*result = port) == MACH_PORT_NULL ? 0 : __mach_port_mod_refs (__mach_task_self (), port, MACH_PORT_RIGHT_SEND, +1)); return (*_hurd_ports_getters[which]) (result); }
/* Called by MiG to deallocate the reply port. */ void __mig_dealloc_reply_port (mach_port_t arg) { mach_port_t port; GETPORT; port = reply_port; reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */ if (MACH_PORT_VALID (port)) __mach_port_mod_refs (__mach_task_self (), port, MACH_PORT_RIGHT_RECEIVE, -1); }
error_t _hurd_ports_set (unsigned int which, mach_port_t newport) { error_t err; if (which >= _hurd_nports) return EINVAL; if (err = __mach_port_mod_refs (__mach_task_self (), newport, MACH_PORT_RIGHT_SEND, 1)) return err; if (which >= INIT_PORT_MAX || _hurd_ports_setters[which] == NULL) { _hurd_port_set (&_hurd_ports[which], newport); return 0; } return (*_hurd_ports_setters[which]) (newport); }
error_t addref (file_t crdir) { *dir = crdir; return __mach_port_mod_refs (__mach_task_self (), crdir, MACH_PORT_RIGHT_SEND, +1); }
/* Duplicate FD to FD2, closing the old FD2 and making FD2 be open on the same file as FD is, and setting FD2's flags according to FLAGS. Return FD2 or -1. */ int __dup3 (int fd, int fd2, int flags) { struct hurd_fd *d; /* Both passing flags different from O_CLOEXEC and FD2 being the same as FD are invalid. */ if ((flags & ~O_CLOEXEC || fd2 == fd) /* ... with the exception in case that dup2 behavior is requested: if FD is valid and FD2 is already the same then just return it. */ && ! (flags == -1 && fd2 == fd)) return __hurd_fail (EINVAL); /* Extract the ports and flags from FD. */ d = _hurd_fd_get (fd); if (d == NULL) return __hurd_fail (EBADF); HURD_CRITICAL_BEGIN; __spin_lock (&d->port.lock); if (d->port.port == MACH_PORT_NULL) { __spin_unlock (&d->port.lock); fd2 = __hurd_fail (EBADF); } else if (fd2 == fd) __spin_unlock (&d->port.lock); else { struct hurd_userlink ulink, ctty_ulink; int d_flags = d->flags; io_t ctty = _hurd_port_get (&d->ctty, &ctty_ulink); io_t port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */ if (fd2 < 0) fd2 = __hurd_fail (EBADF); else { /* Get a hold of the destination descriptor. */ struct hurd_fd *d2; __mutex_lock (&_hurd_dtable_lock); if (fd2 >= _hurd_dtablesize) { /* The table is not large enough to hold the destination descriptor. Enlarge it as necessary to allocate this descriptor. */ __mutex_unlock (&_hurd_dtable_lock); d2 = _hurd_alloc_fd (NULL, fd2); if (d2) __spin_unlock (&d2->port.lock); __mutex_lock (&_hurd_dtable_lock); } else { d2 = _hurd_dtable[fd2]; if (d2 == NULL) { /* Must allocate a new one. We don't initialize the port cells with this call so that if it fails (out of memory), we will not have already added user references for the ports, which we would then have to deallocate. */ d2 = _hurd_dtable[fd2] = _hurd_new_fd (MACH_PORT_NULL, MACH_PORT_NULL); } } __mutex_unlock (&_hurd_dtable_lock); if (d2 == NULL) { fd2 = -1; if (errno == EINVAL) errno = EBADF; /* POSIX.1-1990 6.2.1.2 ll 54-55. */ } else { /* Give the ports each a user ref for the new descriptor. */ __mach_port_mod_refs (__mach_task_self (), port, MACH_PORT_RIGHT_SEND, 1); if (ctty != MACH_PORT_NULL) __mach_port_mod_refs (__mach_task_self (), ctty, MACH_PORT_RIGHT_SEND, 1); /* Install the ports and flags in the new descriptor slot. */ __spin_lock (&d2->port.lock); if (flags & O_CLOEXEC) d2->flags = d_flags | FD_CLOEXEC; else /* dup clears FD_CLOEXEC. */ d2->flags = d_flags & ~FD_CLOEXEC; _hurd_port_set (&d2->ctty, ctty); _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ } } _hurd_port_free (&d->port, &ulink, port); if (ctty != MACH_PORT_NULL) _hurd_port_free (&d->ctty, &ctty_ulink, port); } HURD_CRITICAL_END; return fd2; }