Formerly hurd/hurd/fd.h.~19~
[kopensolaris-gnu/glibc.git] / hurd / hurd / fd.h
1 /* File descriptors.
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #ifndef _HURD_FD_H
21
22 #define _HURD_FD_H      1
23 #include <features.h>
24
25 #include <hurd/hurd_types.h>
26 #include <hurd/port.h>
27
28
29 /* Structure representing a file descriptor.  */
30
31 struct hurd_fd
32   {
33     struct hurd_port port;      /* io server port.  */
34     int flags;                  /* fcntl flags; locked by port.lock.  */
35
36     /* Normal port to the ctty.  When `port' is our ctty, this is a port to
37        the same io object but which never returns EBACKGROUND; when not,
38        this is nil.  */
39     struct hurd_port ctty;
40   };
41
42
43 /* Current file descriptor table.  */
44
45 extern int _hurd_dtablesize;
46 extern struct hurd_fd **_hurd_dtable;
47 extern struct mutex _hurd_dtable_lock; /* Locks those two variables.  */
48 \f
49 #include <hurd/signal.h>
50 #include <lock-intern.h>
51
52 #ifndef _EXTERN_INLINE
53 #define _EXTERN_INLINE extern __inline
54 #endif
55
56 /* Returns the descriptor cell for FD, locked.
57    If FD is invalid or unused, return NULL.  */
58
59 _EXTERN_INLINE struct hurd_fd *
60 _hurd_fd_get (int fd)
61 {
62   struct hurd_fd *descriptor;
63   HURD_CRITICAL_BEGIN;
64   __mutex_lock (&_hurd_dtable_lock);
65   if (fd < 0 || fd >= _hurd_dtablesize)
66     descriptor = NULL;
67   else
68     {
69       struct hurd_fd *cell = _hurd_dtable[fd];
70       if (cell == NULL)
71         /* No descriptor allocated at this index.  */
72         descriptor = NULL;
73       else
74         {
75           __spin_lock (&cell->port.lock);
76           if (cell->port.port == MACH_PORT_NULL)
77             {
78               /* The descriptor at this index has no port in it.
79                  This happens if it existed before but was closed.  */
80               __spin_unlock (&cell->port.lock);
81               descriptor = NULL;
82             }
83           else
84             descriptor = cell;
85         }
86     }
87   __mutex_unlock (&_hurd_dtable_lock);
88   HURD_CRITICAL_END;
89   return descriptor;
90 }
91
92
93 /* Evaluate EXPR with the variable `descriptor' bound to a pointer to the
94    locked file descriptor structure for FD.  EXPR should unlock the
95    descriptor when it is finished.  */
96
97 #define HURD_FD_USE(fd, expr)                                                 \
98   ({ struct hurd_fd *const descriptor = _hurd_fd_get (fd);                    \
99      descriptor == NULL ? EBADF : (expr); })
100
101 /* Evaluate EXPR with the variable `port' bound to the port to FD,
102    and `ctty' bound to the ctty port.  */
103
104 #define HURD_DPORT_USE(fd, expr) \
105   HURD_FD_USE ((fd), HURD_FD_PORT_USE (descriptor, (expr)))
106
107 /* Likewise, but FD is a pointer to the locked file descriptor structure.
108    It is unlocked on return.  */
109
110 #define HURD_FD_PORT_USE(fd, expr)                                            \
111   ({ error_t __result;                                                        \
112      struct hurd_fd *const __d = (fd);                                        \
113      struct hurd_userlink __ulink, __ctty_ulink;                              \
114      io_t port = _hurd_port_locked_get (&__d->port, &__ulink);                \
115      io_t ctty = _hurd_port_locked_get (&__d->ctty, &__ctty_ulink);           \
116      __result = (expr);                                                       \
117      _hurd_port_free (&__d->port, &__ulink, port);                            \
118      if (ctty != MACH_PORT_NULL)                                              \
119        _hurd_port_free (&__d->ctty, &__ctty_ulink, ctty);                     \
120      __result; })
121 \f
122 #include <errno.h>
123
124 /* Check if ERR should generate a signal.
125    Returns the signal to take, or zero if none.  */
126
127 _EXTERN_INLINE error_t
128 _hurd_fd_error_signal (error_t err)
129 {
130   switch (err)
131     {
132     case MACH_SEND_INVALID_DEST: /* The server has disappeared!  */
133       return SIGLOST;
134     case EPIPE:
135       return SIGPIPE;
136     default:
137       /* Having a default case avoids -Wenum-switch warnings.  */
138       return 0;
139     }
140 }
141
142 /* Handle an error from an RPC on a file descriptor's port.  You should
143    always use this function to handle errors from RPCs made on file
144    descriptor ports.  Some errors are translated into signals.  */   
145
146 _EXTERN_INLINE error_t
147 _hurd_fd_error (int fd, error_t err)
148 {
149   int signo = _hurd_fd_error_signal (err);
150   if (signo)
151     _hurd_raise_signal (NULL, signo, fd);
152   return err;
153 }
154
155 /* Handle error code ERR from an RPC on file descriptor FD's port.
156    Set `errno' to the appropriate error code, and always return -1.  */
157
158 _EXTERN_INLINE int
159 __hurd_dfail (int fd, error_t err)
160 {
161   errno = _hurd_fd_error (fd, err);
162   return -1;
163 }
164 \f
165 /* Set up *FD to have PORT its server port, doing appropriate ctty magic.
166    Does no locking or unlocking.  */
167
168 extern void _hurd_port2fd (struct hurd_fd *fd, io_t port, int flags);
169
170 /* Allocate a new file descriptor and install PORT in it (doing any
171    appropriate ctty magic); consumes a user reference on PORT.  FLAGS are
172    as for `open'; only O_IGNORE_CTTY is meaningful, but all are saved.
173
174    If the descriptor table is full, set errno, and return -1.
175    If DEALLOC is nonzero, deallocate PORT first.  */
176
177 extern int _hurd_intern_fd (io_t port, int flags, int dealloc);
178
179 /* Allocate a new file descriptor in the table and return it, locked.  The
180    new descriptor number will be no less than FIRST_FD.  If the table is
181    full, set errno to EMFILE and return NULL.  If FIRST_FD is negative or
182    bigger than the size of the table, set errno to EINVAL and return NULL.  */
183
184 extern struct hurd_fd *_hurd_alloc_fd (int *fd_ptr, int first_fd);
185
186 /* Allocate a new file descriptor structure and initialize its port cells
187    with PORT and CTTY.  (This does not affect the descriptor table.)  */
188
189 extern struct hurd_fd *_hurd_new_fd (io_t port, io_t ctty);
190
191 /* Close a file descriptor, making it available for future reallocation.
192    FD should be locked, and is unlocked on return.  */
193
194 extern error_t _hurd_fd_close (struct hurd_fd *fd);
195
196 /* Read and write data from a file descriptor; just like `read' and `write'.
197    If successful, stores the amount actually read or written in *NBYTES.  */
198
199 extern error_t _hurd_fd_read (struct hurd_fd *fd, void *buf, size_t *nbytes);
200 extern error_t _hurd_fd_write (struct hurd_fd *fd,
201                                const void *buf, size_t *nbytes);
202
203 \f
204 /* User-registered handlers for specific `ioctl' requests.  */
205
206 #define __need___va_list
207 #include <stdarg.h>
208
209 /* Structure that records an ioctl handler.  */
210
211 struct ioctl_handler
212   {
213     int first_request, last_request; /* Range of handled request values.  */
214
215     /* Handler function, called like ioctl to do its entire job.  */
216     int (*handler) (int fd, int request, void *arg);
217
218     struct ioctl_handler *next; /* Next handler.  */
219   };
220
221
222 /* Register HANDLER to handle ioctls with REQUEST values between
223    FIRST_REQUEST and LAST_REQUEST inclusive.  Returns zero if successful.
224    Return nonzero and sets `errno' for an error.  */
225
226 extern int hurd_register_ioctl_handler (int first_request, int last_request,
227                                         int (*handler) (int fd, int request,
228                                                         __gnuc_va_list));
229
230
231 /* Define a library-internal handler for ioctl commands between FIRST and
232    LAST inclusive.  The last element gratuitously references HANDLER to
233    avoid `defined but not used' warnings.  */
234
235 #define _HURD_HANDLE_IOCTLS(handler, first, last)                             \
236   static const struct ioctl_handler handler##_ioctl_handler =                 \
237     { (first), (last), (int (*) (int, int, __gnuc_va_list)) (handler),        \
238         (&(handler), &(handler##_ioctl_handler), NULL) };                     \
239   text_set_element (_hurd_ioctl_handler_lists, ##handler##_ioctl_handler)
240
241 /* Define a library-internal handler for a single ioctl command.  */
242
243 #define _HURD_HANDLE_IOCTL(handler, ioctl) \
244   _HURD_HANDLE_IOCTLS (handler, (ioctl), (ioctl))
245
246
247 #endif  /* hurd/fd.h */