]>
Commit | Line | Data |
---|---|---|
28f540f4 | 1 | /* File descriptors. |
c84142e8 UD |
2 | Copyright (C) 1993, 1994, 1995, 1996, 1997 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 not, | |
17 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
18 | Boston, MA 02111-1307, USA. */ | |
28f540f4 RM |
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. If FD is invalid or unused, return | |
57 | NULL. The cell is unlocked; when ready to use it, lock it and check for | |
58 | it being unused. */ | |
59 | ||
60 | _EXTERN_INLINE struct hurd_fd * | |
61 | _hurd_fd_get (int fd) | |
62 | { | |
63 | struct hurd_fd *descriptor; | |
64 | ||
65 | __mutex_lock (&_hurd_dtable_lock); | |
66 | if (fd < 0 || fd >= _hurd_dtablesize) | |
67 | descriptor = NULL; | |
68 | else | |
69 | { | |
70 | struct hurd_fd *cell = _hurd_dtable[fd]; | |
71 | if (cell == NULL) | |
72 | /* No descriptor allocated at this index. */ | |
73 | descriptor = NULL; | |
74 | else | |
75 | { | |
76 | __spin_lock (&cell->port.lock); | |
77 | if (cell->port.port == MACH_PORT_NULL) | |
78 | /* The descriptor at this index has no port in it. | |
79 | This happens if it existed before but was closed. */ | |
80 | descriptor = NULL; | |
81 | else | |
82 | descriptor = cell; | |
83 | __spin_unlock (&cell->port.lock); | |
84 | } | |
85 | } | |
86 | __mutex_unlock (&_hurd_dtable_lock); | |
87 | ||
88 | return descriptor; | |
89 | } | |
90 | ||
91 | ||
92 | /* Evaluate EXPR with the variable `descriptor' bound to a pointer to the | |
93 | file descriptor structure for FD. */ | |
94 | ||
95 | #define HURD_FD_USE(fd, expr) \ | |
96 | ({ struct hurd_fd *descriptor = _hurd_fd_get (fd); \ | |
97 | descriptor == NULL ? EBADF : (expr); }) | |
98 | ||
99 | /* Evaluate EXPR with the variable `port' bound to the port to FD, and | |
100 | `ctty' bound to the ctty port. */ | |
101 | ||
102 | #define HURD_DPORT_USE(fd, expr) \ | |
103 | HURD_FD_USE ((fd), HURD_FD_PORT_USE (descriptor, (expr))) | |
104 | ||
105 | /* Likewise, but FD is a pointer to the file descriptor structure. */ | |
106 | ||
107 | #define HURD_FD_PORT_USE(fd, expr) \ | |
108 | ({ error_t __result; \ | |
109 | struct hurd_fd *const __d = (fd); \ | |
110 | struct hurd_userlink __ulink, __ctty_ulink; \ | |
111 | io_t port, ctty; \ | |
112 | void *crit = _hurd_critical_section_lock (); \ | |
113 | __spin_lock (&__d->port.lock); \ | |
114 | if (__d->port.port == MACH_PORT_NULL) \ | |
115 | { \ | |
116 | __spin_unlock (&__d->port.lock); \ | |
117 | _hurd_critical_section_unlock (crit); \ | |
118 | __result = EBADF; \ | |
119 | } \ | |
120 | else \ | |
121 | { \ | |
122 | ctty = _hurd_port_get (&__d->ctty, &__ctty_ulink); \ | |
123 | port = _hurd_port_locked_get (&__d->port, &__ulink); \ | |
124 | _hurd_critical_section_unlock (crit); \ | |
125 | __result = (expr); \ | |
126 | _hurd_port_free (&__d->port, &__ulink, port); \ | |
127 | if (ctty != MACH_PORT_NULL) \ | |
128 | _hurd_port_free (&__d->ctty, &__ctty_ulink, ctty); \ | |
129 | } \ | |
130 | __result; }) | |
131 | \f | |
132 | #include <errno.h> | |
133 | ||
134 | /* Check if ERR should generate a signal. | |
135 | Returns the signal to take, or zero if none. */ | |
136 | ||
137 | _EXTERN_INLINE error_t | |
138 | _hurd_fd_error_signal (error_t err) | |
139 | { | |
140 | switch (err) | |
141 | { | |
142 | case EMACH_SEND_INVALID_DEST: | |
143 | case EMIG_SERVER_DIED: | |
144 | /* The server has disappeared! */ | |
145 | return SIGLOST; | |
146 | case EPIPE: | |
147 | return SIGPIPE; | |
148 | default: | |
149 | /* Having a default case avoids -Wenum-switch warnings. */ | |
150 | return 0; | |
151 | } | |
152 | } | |
153 | ||
154 | /* Handle an error from an RPC on a file descriptor's port. You should | |
155 | always use this function to handle errors from RPCs made on file | |
93a470c7 | 156 | descriptor ports. Some errors are translated into signals. */ |
28f540f4 RM |
157 | |
158 | _EXTERN_INLINE error_t | |
159 | _hurd_fd_error (int fd, error_t err) | |
160 | { | |
161 | int signo = _hurd_fd_error_signal (err); | |
162 | if (signo) | |
93a470c7 RM |
163 | { |
164 | const struct hurd_signal_detail detail | |
165 | = { code: fd, error: err, exc: 0 }; | |
166 | _hurd_raise_signal (NULL, signo, &detail); | |
167 | } | |
28f540f4 RM |
168 | return err; |
169 | } | |
170 | ||
171 | /* Handle error code ERR from an RPC on file descriptor FD's port. | |
172 | Set `errno' to the appropriate error code, and always return -1. */ | |
173 | ||
174 | _EXTERN_INLINE int | |
175 | __hurd_dfail (int fd, error_t err) | |
176 | { | |
177 | errno = _hurd_fd_error (fd, err); | |
178 | return -1; | |
179 | } | |
180 | \f | |
181 | /* Set up *FD to have PORT its server port, doing appropriate ctty magic. | |
182 | Does no locking or unlocking. */ | |
183 | ||
184 | extern void _hurd_port2fd (struct hurd_fd *fd, io_t port, int flags); | |
185 | ||
186 | /* Allocate a new file descriptor and install PORT in it (doing any | |
187 | appropriate ctty magic); consumes a user reference on PORT. FLAGS are | |
188 | as for `open'; only O_IGNORE_CTTY is meaningful, but all are saved. | |
189 | ||
190 | If the descriptor table is full, set errno, and return -1. | |
191 | If DEALLOC is nonzero, deallocate PORT first. */ | |
192 | ||
193 | extern int _hurd_intern_fd (io_t port, int flags, int dealloc); | |
194 | ||
195 | /* Allocate a new file descriptor in the table and return it, locked. The | |
196 | new descriptor number will be no less than FIRST_FD. If the table is | |
197 | full, set errno to EMFILE and return NULL. If FIRST_FD is negative or | |
198 | bigger than the size of the table, set errno to EINVAL and return NULL. */ | |
199 | ||
200 | extern struct hurd_fd *_hurd_alloc_fd (int *fd_ptr, int first_fd); | |
201 | ||
202 | /* Allocate a new file descriptor structure and initialize its port cells | |
203 | with PORT and CTTY. (This does not affect the descriptor table.) */ | |
204 | ||
205 | extern struct hurd_fd *_hurd_new_fd (io_t port, io_t ctty); | |
206 | ||
207 | /* Close a file descriptor, making it available for future reallocation. */ | |
208 | ||
209 | extern error_t _hurd_fd_close (struct hurd_fd *fd); | |
210 | ||
211 | /* Read and write data from a file descriptor; just like `read' and `write'. | |
212 | If successful, stores the amount actually read or written in *NBYTES. */ | |
213 | ||
214 | extern error_t _hurd_fd_read (struct hurd_fd *fd, void *buf, size_t *nbytes); | |
215 | extern error_t _hurd_fd_write (struct hurd_fd *fd, | |
216 | const void *buf, size_t *nbytes); | |
217 | ||
218 | ||
219 | /* Call *RPC on PORT and/or CTTY; if a call on CTTY returns EBACKGROUND, | |
220 | generate SIGTTIN/SIGTTOU or EIO as appropriate. */ | |
221 | ||
222 | extern error_t _hurd_ctty_input (io_t port, io_t ctty, error_t (*rpc) (io_t)); | |
223 | extern error_t _hurd_ctty_output (io_t port, io_t ctty, error_t (*rpc) (io_t)); | |
224 | ||
225 | ||
226 | #endif /* hurd/fd.h */ |