diff options
Diffstat (limited to 'REORG.TODO/hurd/hurd/fd.h')
-rw-r--r-- | REORG.TODO/hurd/hurd/fd.h | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/REORG.TODO/hurd/hurd/fd.h b/REORG.TODO/hurd/hurd/fd.h new file mode 100644 index 0000000000..8954be0d50 --- /dev/null +++ b/REORG.TODO/hurd/hurd/fd.h @@ -0,0 +1,275 @@ +/* File descriptors. + Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_FD_H + +#define _HURD_FD_H 1 +#include <features.h> + +#include <cthreads.h> + +#include <hurd/hurd_types.h> +#include <hurd/port.h> +#include <sys/socket.h> + + +/* Structure representing a file descriptor. */ + +struct hurd_fd + { + struct hurd_port port; /* io server port. */ + int flags; /* fcntl flags; locked by port.lock. */ + + /* Normal port to the ctty. When `port' is our ctty, this is a port to + the same io object but which never returns EBACKGROUND; when not, + this is nil. */ + struct hurd_port ctty; + }; + + +/* Current file descriptor table. */ + +extern int _hurd_dtablesize; +extern struct hurd_fd **_hurd_dtable; +extern struct mutex _hurd_dtable_lock; /* Locks those two variables. */ + +#include <hurd/signal.h> + +#ifndef _HURD_FD_H_EXTERN_INLINE +#define _HURD_FD_H_EXTERN_INLINE __extern_inline +#endif + +/* Returns the descriptor cell for FD. If FD is invalid or unused, return + NULL. The cell is unlocked; when ready to use it, lock it and check for + it being unused. */ + +_HURD_FD_H_EXTERN_INLINE struct hurd_fd * +_hurd_fd_get (int fd) +{ + struct hurd_fd *descriptor; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_dtable_lock); + if (fd < 0 || fd >= _hurd_dtablesize) + descriptor = NULL; + else + { + struct hurd_fd *cell = _hurd_dtable[fd]; + if (cell == NULL) + /* No descriptor allocated at this index. */ + descriptor = NULL; + else + { + __spin_lock (&cell->port.lock); + if (cell->port.port == MACH_PORT_NULL) + /* The descriptor at this index has no port in it. + This happens if it existed before but was closed. */ + descriptor = NULL; + else + descriptor = cell; + __spin_unlock (&cell->port.lock); + } + } + __mutex_unlock (&_hurd_dtable_lock); + HURD_CRITICAL_END; + + return descriptor; +} + + +/* Evaluate EXPR with the variable `descriptor' bound to a pointer to the + file descriptor structure for FD. */ + +#define HURD_FD_USE(fd, expr) \ + ({ struct hurd_fd *descriptor = _hurd_fd_get (fd); \ + descriptor == NULL ? EBADF : (expr); }) + +/* Evaluate EXPR with the variable `port' bound to the port to FD, and + `ctty' bound to the ctty port. */ + +#define HURD_DPORT_USE(fd, expr) \ + HURD_FD_USE ((fd), HURD_FD_PORT_USE (descriptor, (expr))) + +/* Likewise, but FD is a pointer to the file descriptor structure. */ + +#define HURD_FD_PORT_USE(fd, expr) \ + ({ error_t __result; \ + struct hurd_fd *const __d = (fd); \ + struct hurd_userlink __ulink, __ctty_ulink; \ + io_t port, ctty; \ + void *crit = _hurd_critical_section_lock (); \ + __spin_lock (&__d->port.lock); \ + if (__d->port.port == MACH_PORT_NULL) \ + { \ + __spin_unlock (&__d->port.lock); \ + _hurd_critical_section_unlock (crit); \ + __result = EBADF; \ + } \ + else \ + { \ + ctty = _hurd_port_get (&__d->ctty, &__ctty_ulink); \ + port = _hurd_port_locked_get (&__d->port, &__ulink); \ + _hurd_critical_section_unlock (crit); \ + __result = (expr); \ + _hurd_port_free (&__d->port, &__ulink, port); \ + if (ctty != MACH_PORT_NULL) \ + _hurd_port_free (&__d->ctty, &__ctty_ulink, ctty); \ + } \ + __result; }) + +#include <errno.h> + +/* Check if ERR should generate a signal. + Returns the signal to take, or zero if none. */ + +_HURD_FD_H_EXTERN_INLINE int +_hurd_fd_error_signal (error_t err) +{ + switch (err) + { + case EMACH_SEND_INVALID_DEST: + case EMIG_SERVER_DIED: + /* The server has disappeared! */ + return SIGLOST; + case EPIPE: + return SIGPIPE; + default: + /* Having a default case avoids -Wenum-switch warnings. */ + return 0; + } +} + +/* Handle an error from an RPC on a file descriptor's port. You should + always use this function to handle errors from RPCs made on file + descriptor ports. Some errors are translated into signals. */ + +_HURD_FD_H_EXTERN_INLINE error_t +_hurd_fd_error (int fd, error_t err) +{ + int signo = _hurd_fd_error_signal (err); + if (signo) + { + const struct hurd_signal_detail detail + = { code: fd, error: err, exc: 0 }; + _hurd_raise_signal (NULL, signo, &detail); + } + return err; +} + +/* Handle error code ERR from an RPC on file descriptor FD's port. + Set `errno' to the appropriate error code, and always return -1. */ + +_HURD_FD_H_EXTERN_INLINE int +__hurd_dfail (int fd, error_t err) +{ + errno = _hurd_fd_error (fd, err); + return -1; +} + +/* Likewise, but do not raise SIGPIPE on EPIPE if flags contain + MSG_NOSIGNAL. */ + +_HURD_FD_H_EXTERN_INLINE int +__hurd_sockfail (int fd, int flags, error_t err) +{ + if (!(flags & MSG_NOSIGNAL) || err != EPIPE) + err = _hurd_fd_error (fd, err); + errno = err; + return -1; +} + +/* Set up *FD to have PORT its server port, doing appropriate ctty magic. + Does no locking or unlocking. */ + +extern void _hurd_port2fd (struct hurd_fd *fd, io_t port, int flags); + +/* Allocate a new file descriptor and install PORT in it (doing any + appropriate ctty magic); consumes a user reference on PORT. FLAGS are + as for `open'; only O_IGNORE_CTTY and O_CLOEXEC are meaningful, but all are + saved. + + If the descriptor table is full, set errno, and return -1. + If DEALLOC is nonzero, deallocate PORT first. */ + +extern int _hurd_intern_fd (io_t port, int flags, int dealloc); + +/* Allocate a new file descriptor in the table and return it, locked. The + new descriptor number will be no less than FIRST_FD. If the table is + full, set errno to EMFILE and return NULL. If FIRST_FD is negative or + bigger than the size of the table, set errno to EINVAL and return NULL. */ + +extern struct hurd_fd *_hurd_alloc_fd (int *fd_ptr, int first_fd); + +/* Allocate a new file descriptor structure and initialize its port cells + with PORT and CTTY. (This does not affect the descriptor table.) */ + +extern struct hurd_fd *_hurd_new_fd (io_t port, io_t ctty); + +/* Close a file descriptor, making it available for future reallocation. */ + +extern error_t _hurd_fd_close (struct hurd_fd *fd); + +/* Read and write data from a file descriptor; just like `read' and `write' + if OFFSET is -1, or like `pread' and `pwrite' if OFFSET is not -1. + If successful, stores the amount actually read or written in *NBYTES. */ + +extern error_t _hurd_fd_read (struct hurd_fd *fd, + void *buf, size_t *nbytes, loff_t offset); +extern error_t _hurd_fd_write (struct hurd_fd *fd, + const void *buf, size_t *nbytes, loff_t offset); + + +/* Call *RPC on PORT and/or CTTY; if a call on CTTY returns EBACKGROUND, + generate SIGTTIN/SIGTTOU or EIO as appropriate. */ + +extern error_t _hurd_ctty_input (io_t port, io_t ctty, error_t (*rpc) (io_t)); +extern error_t _hurd_ctty_output (io_t port, io_t ctty, error_t (*rpc) (io_t)); + + +/* The guts of `select' and `poll'. Check the first NFDS descriptors + either in POLLFDS (if nonnull) or in each of READFDS, WRITEFDS, + EXCEPTFDS that is nonnull. If TIMEOUT is not NULL, time out after + waiting the interval specified therein. If SIGMASK is nonnull, + the set of blocked signals is temporarily set to that during this call. + Returns the number of ready descriptors, or -1 for errors. */ +struct pollfd; +struct timespec; +extern int _hurd_select (int nfds, struct pollfd *pollfds, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, + const sigset_t *sigmask); + +/* Variant of file_name_lookup used in *at function implementations. + AT_FLAGS may only contain AT_SYMLINK_FOLLOW or AT_SYMLINK_NOFOLLOW, + which will remove and add O_NOLINK from FLAGS respectively. + Other bits cause EINVAL. */ +extern file_t __file_name_lookup_at (int fd, int at_flags, + const char *file_name, + int flags, mode_t mode); + +/* Variant of file_name_split used in *at function implementations. */ +extern file_t __file_name_split_at (int fd, const char *file_name, + char **name); + +/* Variant of directory_name_split used in *at function implementations. */ +extern file_t __directory_name_split_at (int fd, const char *directory_name, + char **name); + + + +#endif /* hurd/fd.h */ |