/* Create a new socket of type TYPE in domain DOMAIN, using protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. Returns a file descriptor for the new socket, or -1 for errors. */ int __socket (int domain, int type, int protocol) { error_t err; socket_t sock, server; /* Find the socket server for DOMAIN. */ server = _hurd_socket_server (domain, 0); if (server == MACH_PORT_NULL) return -1; err = __socket_create (server, type, protocol, &sock); if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED || err == MIG_BAD_ID || err == EOPNOTSUPP) { /* On the first use of the socket server during the operation, allow for the old server port dying. */ server = _hurd_socket_server (domain, 1); if (server == MACH_PORT_NULL) return -1; err = __socket_create (server, type, protocol, &sock); } /* These errors all mean that the server node doesn't support the socket.defs protocol, which we'll take to mean that the protocol isn't supported. */ if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED || err == MIG_BAD_ID || err == EOPNOTSUPP) err = EAFNOSUPPORT; if (err) return __hurd_fail (err); return _hurd_intern_fd (sock, O_IGNORE_CTTY, 1); }
/* This returns a new stream opened on a temporary file (generated by tmpnam). The file is opened with mode "w+b" (binary read/write). If we couldn't generate a unique filename or the file couldn't be opened, NULL is returned. */ FILE * __tmpfile (void) { error_t err; file_t file; int fd; FILE *f; /* Get a port to the directory that will contain the file. */ const char *dirname = __libc_secure_getenv ("TMPDIR") ?: P_tmpdir; file_t dir = __file_name_lookup (dirname, 0, 0); if (dir == MACH_PORT_NULL) return NULL; /* Create an unnamed file in the temporary directory. */ err = __dir_mkfile (dir, O_RDWR, S_IRUSR | S_IWUSR, &file); __mach_port_deallocate (__mach_task_self (), dir); if (err) return __hurd_fail (err), NULL; /* Get a file descriptor for that port. POSIX.1 requires that streams returned by tmpfile allocate file descriptors as fopen would. */ fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */ if (fd < 0) return NULL; /* Open a stream on the unnamed file. It will cease to exist when this stream is closed. */ if ((f = _IO_fdopen (fd, "w+b")) == NULL) __close (fd); return f; }
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG, a third argument is the file protection. */ int __libc_open (const char *file, int oflag, ...) { mode_t mode; io_t port; if (__OPEN_NEEDS_MODE (oflag)) { va_list arg; va_start (arg, oflag); mode = va_arg (arg, mode_t); va_end (arg); } else mode = 0; port = __file_name_lookup (file, oflag, mode); if (port == MACH_PORT_NULL) return -1; return _hurd_intern_fd (port, oflag, 1); }
/* Open the shared memory segment *R_KEY and return a file descriptor to it in R_FD. If KEY is IPC_PRIVATE, use a private key and return it in R_KEY. */ static error_t get_exclusive (int shmflags, size_t size, key_t *r_key, int *r_fd) { error_t err; file_t dir; file_t file; char filename[SHM_NAMEMAX]; key_t key = *r_key; bool is_private; /* Create the shared memory segment. */ err = create_shm_file (size, shmflags, &dir, &file); if (err) return err; if (key == IPC_PRIVATE) { is_private = true; key = SHM_PRIV_KEY_START; /* Try to link the shared memory segment into the filesystem (exclusively). Private segments have negative keys. */ do { sprintf (filename, SHM_NAMEPRI, key); err = __dir_link (dir, file, filename, 1); if (!err) { /* We are done. */ *r_key = key; break; } else if (err == EEXIST) { /* Check if we ran out of keys. If not, try again with new key. */ if (key == SHM_PRIV_KEY_END) err = ENOSPC; else err = 0; key--; } } while (!err); } else { /* Try to link the shared memory segment into the filesystem (exclusively) under the given key. */ sprintf (filename, SHM_NAMEPRI, key); err = __dir_link (dir, file, filename, 1); } __mach_port_deallocate (__mach_task_self (), dir); if (!err) { int fd; /* Get a file descriptor for that port. */ fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */ if (fd < 0) err = errno; else *r_fd = fd; } return err; }
int openport (io_t port, int flags) { return _hurd_intern_fd (port, flags, 0); }
/* Create two new sockets, of type TYPE in domain DOMAIN and using protocol PROTOCOL, which are connected to each other, and put file descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, one will be chosen automatically. Returns 0 on success, -1 for errors. */ int __socketpair (int domain, int type, int protocol, int fds[2]) { error_t err; socket_t server, sock1, sock2; int d1, d2; if (fds == NULL) return __hurd_fail (EINVAL); /* Find the domain's socket server. */ server = _hurd_socket_server (domain, 0); if (server == MACH_PORT_NULL) return -1; /* Create two sockets and connect them together. */ err = __socket_create (server, type, protocol, &sock1); if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED || err == MIG_BAD_ID || err == EOPNOTSUPP) { /* On the first use of the socket server during the operation, allow for the old server port dying. */ server = _hurd_socket_server (domain, 1); if (server == MACH_PORT_NULL) return -1; err = __socket_create (server, type, protocol, &sock1); } if (err) return __hurd_fail (err); if (err = __socket_create (server, type, protocol, &sock2)) { __mach_port_deallocate (__mach_task_self (), sock1); return __hurd_fail (err); } if (err = __socket_connect2 (sock1, sock2)) { __mach_port_deallocate (__mach_task_self (), sock1); __mach_port_deallocate (__mach_task_self (), sock2); return __hurd_fail (err); } /* Put the sockets into file descriptors. */ d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY, 1); if (d1 < 0) { __mach_port_deallocate (__mach_task_self (), sock2); return -1; } d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY, 1); if (d2 < 0) { err = errno; (void) close (d1); return __hurd_fail (err); } fds[0] = d1; fds[1] = d2; return 0; }