Update.
[glibc.git] / sysdeps / mach / hurd / sysd-stdio.c
blobfea9b56a96170be8f52c88c897ad2236e0b6d095
1 /* Copyright (C) 1994, 95, 96, 97, 98 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #include <errno.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <hurd.h>
23 #include <fcntl.h>
24 #include <hurd/fd.h>
26 extern __io_read_fn __stdio_read;
27 extern __io_write_fn __stdio_write;
28 extern __io_seek_fn __stdio_seek;
29 extern __io_close_fn __stdio_close;
30 extern __io_fileno_fn __stdio_fileno;
33 /* Check ERR for wanting to generate a signal. */
35 static inline int
36 fd_fail (struct hurd_fd *fd, error_t err)
38 int signo = _hurd_fd_error_signal (err);
39 if (signo)
41 const struct hurd_signal_detail detail
42 = { code: __stdio_fileno (fd), error: err, exc: 0 };
43 _hurd_raise_signal (NULL, signo, &detail);
45 errno = err;
46 return -1;
50 /* Read up to N chars into BUF from COOKIE.
51 Return how many chars were read, 0 for EOF or -1 for error. */
52 ssize_t
53 __stdio_read (cookie, buf, n)
54 void *cookie;
55 char *buf;
56 size_t n;
58 error_t err;
59 struct hurd_fd *fd = cookie;
61 if (! fd)
62 return __hurd_fail (EBADF);
64 if (err = _hurd_fd_read (fd, buf, &n, -1))
65 return fd_fail (fd, err);
67 return n;
70 /* Write up to N chars from BUF to COOKIE.
71 Return how many chars were written or -1 for error. */
72 ssize_t
73 __stdio_write (cookie, buf, n)
74 void *cookie;
75 const char *buf;
76 size_t n;
78 error_t err;
79 size_t wrote, nleft;
80 struct hurd_fd *fd = cookie;
82 if (! fd)
83 return __hurd_fail (EBADF);
85 nleft = n;
88 wrote = nleft;
89 if (err = _hurd_fd_write (fd, buf, &wrote, -1))
90 return fd_fail (fd, err);
91 buf += wrote;
92 nleft -= wrote;
93 } while (nleft > 0);
95 return wrote;
98 /* Move COOKIE's file position *POS bytes, according to WHENCE.
99 The current file position is stored in *POS.
100 Returns zero if successful, nonzero if not. */
102 __stdio_seek (cookie, pos, whence)
103 void *cookie;
104 fpos_t *pos;
105 int whence;
107 error_t err;
108 struct hurd_fd *fd = cookie;
109 if (! fd)
110 return __hurd_fail (EBADF);
111 err = HURD_FD_PORT_USE (fd, __io_seek (port, *pos, whence, pos));
112 return err ? fd_fail (fd, err) : 0;
115 /* Close the file associated with COOKIE.
116 Return 0 for success or -1 for failure. */
118 __stdio_close (cookie)
119 void *cookie;
121 error_t error = cookie ? _hurd_fd_close (cookie) : EBADF;
122 return error ? fd_fail (cookie, error) : 0;
126 static inline int
127 modeflags (__io_mode m)
129 int flags = 0;
130 if (m.__read)
131 flags |= O_READ;
132 if (m.__write)
133 flags |= O_WRITE;
134 if (m.__append)
135 flags |= O_APPEND;
136 if (m.__create)
137 flags |= O_CREAT;
138 if (m.__truncate)
139 flags |= O_TRUNC;
140 if (m.__exclusive)
141 flags |= O_EXCL;
142 return flags;
145 /* Open FILENAME with the mode in M. */
147 __stdio_open (filename, m, cookieptr)
148 const char *filename;
149 __io_mode m;
150 void **cookieptr;
152 int flags;
153 file_t port;
154 struct hurd_fd *d;
156 flags = modeflags (m);
157 port = __file_name_lookup (filename, flags, 0666 & ~_hurd_umask);
158 if (port == MACH_PORT_NULL)
159 return -1;
161 HURD_CRITICAL_BEGIN;
162 d = _hurd_alloc_fd (NULL, 0);
163 if (d != NULL)
165 _hurd_port2fd (d, port, flags);
166 __spin_unlock (&d->port.lock);
168 HURD_CRITICAL_END;
170 *cookieptr = d;
171 return 0;
175 /* Open FILENAME with the mode in M. Use the same magic cookie
176 already in *COOKIEPTR if possible, closing the old cookie with CLOSEFN. */
178 __stdio_reopen (filename, m, cookieptr, closefn)
179 const char *filename;
180 __io_mode m;
181 void **cookieptr;
182 __io_close_fn closefn;
184 int flags;
185 file_t port;
186 struct hurd_fd *d;
188 if (closefn != __stdio_close)
190 /* The old cookie is Not Of The Body.
191 Just close it and do a normal open. */
192 (*closefn) (*cookieptr);
193 return __stdio_open (filename, m, cookieptr);
196 /* Open a new port on the file. */
197 flags = modeflags (m);
198 port = __file_name_lookup (filename, flags, 0666 & ~_hurd_umask);
200 /* Install the new port in the same file descriptor slot the old cookie
201 points to. If opening the file failed, PORT will be MACH_PORT_NULL
202 and installing it in the descriptor will have the effect of closing
203 the old descriptor. */
205 d = *cookieptr;
206 HURD_CRITICAL_BEGIN;
207 __spin_lock (&d->port.lock);
208 _hurd_port2fd (d, port, flags);
209 __spin_unlock (&d->port.lock);
210 HURD_CRITICAL_END;
212 return port == MACH_PORT_NULL ? -1 : 0;
216 /* Write a message to the error output.
217 Try hard to make it really get out. */
218 void
219 __stdio_errmsg (msg, len)
220 const char *msg;
221 size_t len;
223 io_t server;
224 mach_msg_type_number_t wrote;
226 server = __getdport (2);
227 __io_write (server, msg, len, -1, &wrote);
228 __mach_port_deallocate (__mach_task_self (), server);
232 /* Return the POSIX.1 file descriptor associated with COOKIE,
233 or -1 for errors. If COOKIE does not relate to any POSIX.1 file
234 descriptor, this should return -1 with errno set to EOPNOTSUPP. */
236 __stdio_fileno (cookie)
237 void *cookie;
239 int fd;
241 if (! cookie)
242 return __hurd_fail (EBADF);
244 __mutex_lock (&_hurd_dtable_lock);
245 for (fd = 0; fd < _hurd_dtablesize; ++fd)
246 if (_hurd_dtable[fd] == cookie)
248 __mutex_unlock (&_hurd_dtable_lock);
249 return fd;
251 __mutex_unlock (&_hurd_dtable_lock);
253 /* This should never happen, because this function should not be
254 installed as a stream's __fileno function unless that stream's cookie
255 points to a file descriptor. */
256 errno = EGRATUITOUS;
257 return -1;