]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/fileops.c
Update.
[thirdparty/glibc.git] / libio / fileops.c
CommitLineData
f38931a9 1/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
40a55d20
UD
2 This file is part of the GNU IO Library.
3 Written by Per Bothner <bothner@cygnus.com>.
96aa2d94 4
40a55d20
UD
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2, or (at
8 your option) any later version.
96aa2d94 9
40a55d20
UD
10 This library is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
96aa2d94 14
40a55d20
UD
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
96aa2d94 19
40a55d20
UD
20 As a special exception, if you link this library with files
21 compiled with a GNU compiler to produce an executable, this does
22 not cause the resulting executable to be covered by the GNU General
23 Public License. This exception does not however invalidate any
24 other reasons why the executable file might be covered by the GNU
25 General Public License. */
96aa2d94 26
96aa2d94 27
fa0bc87c
RM
28#ifndef _POSIX_SOURCE
29# define _POSIX_SOURCE
30#endif
96aa2d94
RM
31#include "libioP.h"
32#include <fcntl.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <string.h>
36#include <errno.h>
37#ifndef errno
38extern int errno;
39#endif
4547c1a4
UD
40#ifndef __set_errno
41# define __set_errno(Val) errno = (Val)
42#endif
96aa2d94 43
68dbb3a6
UD
44
45#ifdef _LIBC
61eb22d3
UD
46# define open(Name, Flags, Prot) __open (Name, Flags, Prot)
47# define close(FD) __close (FD)
61eb22d3
UD
48# define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
49# define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
50# define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
68dbb3a6
UD
51#endif
52
96aa2d94
RM
53/* An fstream can be in at most one of put mode, get mode, or putback mode.
54 Putback mode is a variant of get mode.
55
56 In a filebuf, there is only one current position, instead of two
6d52618b 57 separate get and put pointers. In get mode, the current position
96aa2d94
RM
58 is that of gptr(); in put mode that of pptr().
59
60 The position in the buffer that corresponds to the position
a18f587d
UD
61 in external file system is normally _IO_read_end, except in putback
62 mode, when it is _IO_save_end.
96aa2d94
RM
63 If the field _fb._offset is >= 0, it gives the offset in
64 the file as a whole corresponding to eGptr(). (?)
65
66 PUT MODE:
a18f587d
UD
67 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
68 and _IO_read_base are equal to each other. These are usually equal
69 to _IO_buf_base, though not necessarily if we have switched from
70 get mode to put mode. (The reason is to maintain the invariant
71 that _IO_read_end corresponds to the external file position.)
72 _IO_write_base is non-NULL and usually equal to _IO_base_base.
73 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
74 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
75
96aa2d94
RM
76 GET MODE:
77 If a filebuf is in get or putback mode, eback() != egptr().
78 In get mode, the unread characters are between gptr() and egptr().
79 The OS file position corresponds to that of egptr().
a18f587d 80
96aa2d94
RM
81 PUTBACK MODE:
82 Putback mode is used to remember "excess" characters that have
83 been sputbackc'd in a separate putback buffer.
84 In putback mode, the get buffer points to the special putback buffer.
85 The unread characters are the characters between gptr() and egptr()
86 in the putback buffer, as well as the area between save_gptr()
87 and save_egptr(), which point into the original reserve buffer.
88 (The pointers save_gptr() and save_egptr() are the values
89 of gptr() and egptr() at the time putback mode was entered.)
90 The OS position corresponds to that of save_egptr().
23396375 91
96aa2d94 92 LINE BUFFERED OUTPUT:
a18f587d 93 During line buffered output, _IO_write_base==base() && epptr()==base().
96aa2d94
RM
94 However, ptr() may be anywhere between base() and ebuf().
95 This forces a call to filebuf::overflow(int C) on every put.
96 If there is more space in the buffer, and C is not a '\n',
97 then C is inserted, and pptr() incremented.
23396375 98
96aa2d94
RM
99 UNBUFFERED STREAMS:
100 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
101*/
102
103#define CLOSED_FILEBUF_FLAGS \
104 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
105
106
107void
40a55d20
UD
108_IO_file_init (fp)
109 _IO_FILE *fp;
96aa2d94
RM
110{
111 /* POSIX.1 allows another file handle to be used to change the position
112 of our file descriptor. Hence we actually don't know the actual
113 position before we do the first fseek (and until a following fflush). */
bd355af0 114 fp->_offset = _IO_pos_BAD;
96aa2d94
RM
115 fp->_IO_file_flags |= CLOSED_FILEBUF_FLAGS;
116
117 _IO_link_in(fp);
118 fp->_fileno = -1;
119}
120
121int
40a55d20
UD
122_IO_file_close_it (fp)
123 _IO_FILE *fp;
96aa2d94 124{
fa0bc87c 125 int write_status, close_status;
40a55d20 126 if (!_IO_file_is_open (fp))
96aa2d94
RM
127 return EOF;
128
fa0bc87c 129 write_status = _IO_do_flush (fp);
96aa2d94
RM
130
131 _IO_unsave_markers(fp);
132
133 close_status = _IO_SYSCLOSE (fp);
134
135 /* Free buffer. */
40a55d20
UD
136 _IO_setb (fp, NULL, NULL, 0);
137 _IO_setg (fp, NULL, NULL, NULL);
138 _IO_setp (fp, NULL, NULL);
96aa2d94 139
40a55d20 140 _IO_un_link (fp);
96aa2d94
RM
141 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
142 fp->_fileno = EOF;
bd355af0 143 fp->_offset = _IO_pos_BAD;
96aa2d94 144
fa0bc87c 145 return close_status ? close_status : write_status;
96aa2d94
RM
146}
147
148void
40a55d20
UD
149_IO_file_finish (fp, dummy)
150 _IO_FILE *fp;
151 int dummy;
96aa2d94 152{
40a55d20 153 if (_IO_file_is_open (fp))
96aa2d94
RM
154 {
155 _IO_do_flush (fp);
156 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
157 _IO_SYSCLOSE (fp);
158 }
40a55d20 159 _IO_default_finish (fp, 0);
96aa2d94
RM
160}
161
bd355af0
UD
162#if defined __GNUC__ && __GNUC__ >= 2
163__inline__
164#endif
165_IO_FILE *
166_IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
167 _IO_FILE *fp;
168 const char *filename;
169 int posix_mode;
170 int prot;
171 int read_write;
172 int is32not64;
173{
174 int fdesc;
175#ifdef _G_OPEN64
176 fdesc = (is32not64
177 ? open (filename, posix_mode, prot)
178 : _G_OPEN64 (filename, posix_mode, prot));
179#else
180 fdesc = open (filename, posix_mode, prot);
181#endif
182 if (fdesc < 0)
183 return NULL;
184 fp->_fileno = fdesc;
185 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
186 if (read_write & _IO_IS_APPENDING)
187 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
188 == _IO_pos_BAD && errno != ESPIPE)
189 return NULL;
190 _IO_link_in (fp);
191 return fp;
192}
193
96aa2d94 194_IO_FILE *
dfd2257a 195_IO_file_fopen (fp, filename, mode, is32not64)
40a55d20
UD
196 _IO_FILE *fp;
197 const char *filename;
198 const char *mode;
dfd2257a 199 int is32not64;
96aa2d94
RM
200{
201 int oflags = 0, omode;
bd355af0 202 int read_write;
96aa2d94 203 int oprot = 0666;
f38931a9 204 int i;
96aa2d94
RM
205 if (_IO_file_is_open (fp))
206 return 0;
f38931a9 207 switch (*mode)
40a55d20
UD
208 {
209 case 'r':
210 omode = O_RDONLY;
211 read_write = _IO_NO_WRITES;
212 break;
213 case 'w':
214 omode = O_WRONLY;
215 oflags = O_CREAT|O_TRUNC;
216 read_write = _IO_NO_READS;
217 break;
218 case 'a':
219 omode = O_WRONLY;
220 oflags = O_CREAT|O_APPEND;
221 read_write = _IO_NO_READS|_IO_IS_APPENDING;
222 break;
223 default:
224 __set_errno (EINVAL);
225 return NULL;
226 }
f38931a9 227 for (i = 1; i < 4; ++i)
40a55d20 228 {
f38931a9
UD
229 switch (*++mode)
230 {
231 case '\0':
232 break;
233 case '+':
234 omode = O_RDWR;
235 read_write &= _IO_IS_APPENDING;
236 continue;
237 case 'x':
238 oflags |= O_EXCL;
239 continue;
240 case 'b':
241 default:
242 /* Ignore. */
243 continue;
244 }
245 break;
40a55d20 246 }
f38931a9 247
bd355af0
UD
248 return _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
249 is32not64);
96aa2d94
RM
250}
251
40a55d20
UD
252_IO_FILE *
253_IO_file_attach (fp, fd)
254 _IO_FILE *fp;
255 int fd;
96aa2d94 256{
40a55d20 257 if (_IO_file_is_open (fp))
96aa2d94
RM
258 return NULL;
259 fp->_fileno = fd;
260 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
261 fp->_flags |= _IO_DELETE_DONT_CLOSE;
f65fd747
UD
262 /* Get the current position of the file. */
263 /* We have to do that since that may be junk. */
bd355af0 264 fp->_offset = _IO_pos_BAD;
dfd2257a 265 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
f65fd747
UD
266 == _IO_pos_BAD && errno != ESPIPE)
267 return NULL;
96aa2d94
RM
268 return fp;
269}
270
40a55d20
UD
271_IO_FILE *
272_IO_file_setbuf (fp, p, len)
273 _IO_FILE *fp;
274 char *p;
275 _IO_ssize_t len;
96aa2d94 276{
40a55d20
UD
277 if (_IO_default_setbuf (fp, p, len) == NULL)
278 return NULL;
96aa2d94
RM
279
280 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
281 = fp->_IO_buf_base;
40a55d20 282 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
283
284 return fp;
285}
286
287/* Write TO_DO bytes from DATA to FP.
68dbb3a6 288 Then mark FP as having empty buffers. */
96aa2d94
RM
289
290int
40a55d20
UD
291_IO_do_write (fp, data, to_do)
292 _IO_FILE *fp;
293 const char *data;
294 _IO_size_t to_do;
96aa2d94
RM
295{
296 _IO_size_t count;
297 if (to_do == 0)
298 return 0;
299 if (fp->_flags & _IO_IS_APPENDING)
300 /* On a system without a proper O_APPEND implementation,
301 you would need to sys_seek(0, SEEK_END) here, but is
302 is not needed nor desirable for Unix- or Posix-like systems.
303 Instead, just indicate that offset (before and after) is
304 unpredictable. */
bd355af0 305 fp->_offset = _IO_pos_BAD;
96aa2d94 306 else if (fp->_IO_read_end != fp->_IO_write_base)
23396375 307 {
dfd2257a 308 _IO_fpos64_t new_pos
40a55d20 309 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
96aa2d94
RM
310 if (new_pos == _IO_pos_BAD)
311 return EOF;
bd355af0 312 fp->_offset = new_pos;
96aa2d94
RM
313 }
314 count = _IO_SYSWRITE (fp, data, to_do);
315 if (fp->_cur_column)
40a55d20
UD
316 fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, to_do) + 1;
317 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94 318 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
bfcd44c3 319 fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
40a55d20 320 ? fp->_IO_buf_base : fp->_IO_buf_end);
96aa2d94
RM
321 return count != to_do ? EOF : 0;
322}
323
324int
40a55d20
UD
325_IO_file_underflow (fp)
326 _IO_FILE *fp;
96aa2d94
RM
327{
328 _IO_ssize_t count;
329#if 0
330 /* SysV does not make this test; take it out for compatibility */
331 if (fp->_flags & _IO_EOF_SEEN)
332 return (EOF);
333#endif
334
335 if (fp->_flags & _IO_NO_READS)
feb3c934
UD
336 {
337 __set_errno (EBADF);
338 return EOF;
339 }
96aa2d94 340 if (fp->_IO_read_ptr < fp->_IO_read_end)
40a55d20 341 return *(unsigned char *) fp->_IO_read_ptr;
96aa2d94
RM
342
343 if (fp->_IO_buf_base == NULL)
40a55d20 344 _IO_doallocbuf (fp);
96aa2d94
RM
345
346 /* Flush all line buffered files before reading. */
347 /* FIXME This can/should be moved to genops ?? */
348 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
40a55d20 349 _IO_flush_all_linebuffered ();
96aa2d94 350
40a55d20 351 _IO_switch_to_get_mode (fp);
96aa2d94 352
2d7da676
UD
353 /* This is very tricky. We have to adjust those
354 pointers before we call _IO_SYSREAD () since
355 we may longjump () out while waiting for
356 input. Those pointers may be screwed up. H.J. */
357 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
358 fp->_IO_read_end = fp->_IO_buf_base;
359 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
360 = fp->_IO_buf_base;
361
96aa2d94
RM
362 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
363 fp->_IO_buf_end - fp->_IO_buf_base);
364 if (count <= 0)
365 {
366 if (count == 0)
367 fp->_flags |= _IO_EOF_SEEN;
368 else
369 fp->_flags |= _IO_ERR_SEEN, count = 0;
370 }
2d7da676 371 fp->_IO_read_end += count;
96aa2d94
RM
372 if (count == 0)
373 return EOF;
bd355af0
UD
374 if (fp->_offset != _IO_pos_BAD)
375 _IO_pos_adjust (fp->_offset, count);
40a55d20 376 return *(unsigned char *) fp->_IO_read_ptr;
96aa2d94
RM
377}
378
379int
40a55d20
UD
380_IO_file_overflow (f, ch)
381 _IO_FILE *f;
382 int ch;
96aa2d94
RM
383{
384 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
feb3c934 385 {
c131718c 386 f->_flags |= _IO_ERR_SEEN;
feb3c934
UD
387 __set_errno (EBADF);
388 return EOF;
389 }
96aa2d94
RM
390 /* If currently reading or no buffer allocated. */
391 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
392 {
393 /* Allocate a buffer if needed. */
394 if (f->_IO_write_base == 0)
395 {
40a55d20 396 _IO_doallocbuf (f);
96aa2d94
RM
397 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
398 }
c6645251
UD
399 /* Otherwise must be currently reading.
400 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
401 logically slide the buffer forwards one block (by setting the
402 read pointers to all point at the beginning of the block). This
403 makes room for subsequent output.
404 Otherwise, set the read pointers to _IO_read_end (leaving that
405 alone, so it can continue to correspond to the external position). */
406 if (f->_IO_read_ptr == f->_IO_buf_end)
407 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
96aa2d94
RM
408 f->_IO_write_ptr = f->_IO_read_ptr;
409 f->_IO_write_base = f->_IO_write_ptr;
410 f->_IO_write_end = f->_IO_buf_end;
411 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
412
96aa2d94 413 f->_flags |= _IO_CURRENTLY_PUTTING;
bfcd44c3
UD
414 if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
415 f->_IO_write_end = f->_IO_write_ptr;
96aa2d94
RM
416 }
417 if (ch == EOF)
40a55d20 418 return _IO_do_flush (f);
96aa2d94 419 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
40a55d20 420 if (_IO_do_flush (f) == EOF)
96aa2d94
RM
421 return EOF;
422 *f->_IO_write_ptr++ = ch;
423 if ((f->_flags & _IO_UNBUFFERED)
424 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
40a55d20 425 if (_IO_do_flush (f) == EOF)
96aa2d94 426 return EOF;
40a55d20 427 return (unsigned char) ch;
96aa2d94
RM
428}
429
430int
40a55d20
UD
431_IO_file_sync (fp)
432 _IO_FILE *fp;
96aa2d94 433{
a2bde807 434 _IO_ssize_t delta;
61eb22d3
UD
435 int retval = 0;
436
96aa2d94
RM
437 /* char* ptr = cur_ptr(); */
438 if (fp->_IO_write_ptr > fp->_IO_write_base)
439 if (_IO_do_flush(fp)) return EOF;
23396375 440 delta = fp->_IO_read_ptr - fp->_IO_read_end;
96aa2d94
RM
441 if (delta != 0)
442 {
443#ifdef TODO
40a55d20
UD
444 if (_IO_in_backup (fp))
445 delta -= eGptr () - Gbase ();
96aa2d94 446#endif
dfd2257a
UD
447 _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
448 if (new_pos != (_IO_off64_t) EOF)
96aa2d94
RM
449 fp->_IO_read_end = fp->_IO_read_ptr;
450#ifdef ESPIPE
451 else if (errno == ESPIPE)
452 ; /* Ignore error from unseekable devices. */
453#endif
454 else
61eb22d3 455 retval = EOF;
96aa2d94 456 }
61eb22d3 457 if (retval != EOF)
bd355af0 458 fp->_offset = _IO_pos_BAD;
96aa2d94
RM
459 /* FIXME: Cleanup - can this be shared? */
460 /* setg(base(), ptr, ptr); */
61eb22d3 461 return retval;
96aa2d94
RM
462}
463
dfd2257a 464_IO_fpos64_t
40a55d20
UD
465_IO_file_seekoff (fp, offset, dir, mode)
466 _IO_FILE *fp;
dfd2257a 467 _IO_off64_t offset;
40a55d20
UD
468 int dir;
469 int mode;
96aa2d94 470{
dfd2257a
UD
471 _IO_fpos64_t result;
472 _IO_off64_t delta, new_offset;
96aa2d94 473 long count;
feb3c934
UD
474 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
475 offset of the underlying file must be exact. */
476 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
477 && fp->_IO_write_base == fp->_IO_write_ptr);
96aa2d94
RM
478
479 if (mode == 0)
480 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
481
482 /* Flush unwritten characters.
483 (This may do an unneeded write if we seek within the buffer.
484 But to be able to switch to reading, we would need to set
485 egptr to ptr. That can't be done in the current design,
486 which assumes file_ptr() is eGptr. Anyway, since we probably
487 end up flushing when we close(), it doesn't make much difference.)
488 FIXME: simulate mem-papped files. */
489
40a55d20
UD
490 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
491 if (_IO_switch_to_get_mode (fp))
492 return EOF;
96aa2d94
RM
493
494 if (fp->_IO_buf_base == NULL)
495 {
40a55d20
UD
496 _IO_doallocbuf (fp);
497 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
498 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
499 }
500
501 switch (dir)
502 {
503 case _IO_seek_cur:
504 /* Adjust for read-ahead (bytes is buffer). */
505 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
bd355af0 506 if (fp->_offset == _IO_pos_BAD)
96aa2d94
RM
507 goto dumb;
508 /* Make offset absolute, assuming current pointer is file_ptr(). */
bd355af0 509 offset += _IO_pos_as_off (fp->_offset);
96aa2d94
RM
510
511 dir = _IO_seek_set;
512 break;
513 case _IO_seek_set:
514 break;
515 case _IO_seek_end:
516 {
dfd2257a 517 struct _G_stat64 st;
40a55d20 518 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
96aa2d94
RM
519 {
520 offset += st.st_size;
521 dir = _IO_seek_set;
522 }
523 else
524 goto dumb;
525 }
526 }
527 /* At this point, dir==_IO_seek_set. */
528
529 /* If destination is within current buffer, optimize: */
bd355af0 530 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
96aa2d94
RM
531 && !_IO_in_backup (fp))
532 {
533 /* Offset relative to start of main get area. */
bd355af0 534 _IO_fpos64_t rel_offset = (offset - fp->_offset
dfd2257a 535 + (fp->_IO_read_end - fp->_IO_read_base));
96aa2d94
RM
536 if (rel_offset >= 0)
537 {
538#if 0
40a55d20
UD
539 if (_IO_in_backup (fp))
540 _IO_switch_to_main_get_area (fp);
96aa2d94
RM
541#endif
542 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
543 {
40a55d20
UD
544 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
545 fp->_IO_read_end);
546 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
547 return offset;
548 }
549#ifdef TODO
550 /* If we have streammarkers, seek forward by reading ahead. */
40a55d20 551 if (_IO_have_markers (fp))
96aa2d94
RM
552 {
553 int to_skip = rel_offset
554 - (fp->_IO_read_ptr - fp->_IO_read_base);
40a55d20 555 if (ignore (to_skip) != to_skip)
96aa2d94
RM
556 goto dumb;
557 return offset;
558 }
559#endif
560 }
561#ifdef TODO
40a55d20 562 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
96aa2d94 563 {
40a55d20
UD
564 if (!_IO_in_backup (fp))
565 _IO_switch_to_backup_area (fp);
566 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
96aa2d94
RM
567 return offset;
568 }
569#endif
570 }
571
572#ifdef TODO
40a55d20 573 _IO_unsave_markers (fp);
96aa2d94
RM
574#endif
575
576 if (fp->_flags & _IO_NO_READS)
577 goto dumb;
578
579 /* Try to seek to a block boundary, to improve kernel page management. */
580 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
581 delta = offset - new_offset;
582 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
583 {
584 new_offset = offset;
585 delta = 0;
586 }
587 result = _IO_SYSSEEK (fp, new_offset, 0);
588 if (result < 0)
589 return EOF;
590 if (delta == 0)
591 count = 0;
592 else
593 {
594 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
feb3c934
UD
595 (must_be_exact
596 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
96aa2d94
RM
597 if (count < delta)
598 {
599 /* We weren't allowed to read, but try to seek the remainder. */
600 offset = count == EOF ? delta : delta-count;
601 dir = _IO_seek_cur;
602 goto dumb;
603 }
604 }
40a55d20
UD
605 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
606 fp->_IO_buf_base + count);
607 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
bd355af0 608 fp->_offset = result + count;
40a55d20 609 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
96aa2d94
RM
610 return offset;
611 dumb:
612
40a55d20 613 _IO_unsave_markers (fp);
96aa2d94
RM
614 result = _IO_SYSSEEK (fp, offset, dir);
615 if (result != EOF)
40a55d20 616 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
bd355af0 617 fp->_offset = result;
40a55d20
UD
618 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
619 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
620 return result;
621}
622
623_IO_ssize_t
40a55d20
UD
624_IO_file_read (fp, buf, size)
625 _IO_FILE *fp;
626 void *buf;
627 _IO_ssize_t size;
96aa2d94 628{
61eb22d3 629 return read (fp->_fileno, buf, size);
96aa2d94
RM
630}
631
dfd2257a 632_IO_fpos64_t
40a55d20
UD
633_IO_file_seek (fp, offset, dir)
634 _IO_FILE *fp;
dfd2257a 635 _IO_off64_t offset;
40a55d20 636 int dir;
96aa2d94 637{
dfd2257a
UD
638#ifdef _G_LSEEK64
639 return _G_LSEEK64 (fp->_fileno, offset, dir);
640#else
61eb22d3 641 return lseek (fp->_fileno, offset, dir);
dfd2257a 642#endif
96aa2d94
RM
643}
644
645int
40a55d20
UD
646_IO_file_stat (fp, st)
647 _IO_FILE *fp;
648 void *st;
96aa2d94 649{
279eb600 650#ifdef _G_FSTAT64
dfd2257a
UD
651 return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
652#else
653 return fstat (fp->_fileno, (struct _G_stat64 *) st);
654#endif
96aa2d94
RM
655}
656
657int
40a55d20
UD
658_IO_file_close (fp)
659 _IO_FILE *fp;
96aa2d94 660{
61eb22d3 661 return close (fp->_fileno);
96aa2d94
RM
662}
663
664_IO_ssize_t
40a55d20
UD
665_IO_file_write (f, data, n)
666 _IO_FILE *f;
667 const void *data;
668 _IO_ssize_t n;
96aa2d94
RM
669{
670 _IO_ssize_t to_do = n;
671 while (to_do > 0)
672 {
61eb22d3 673 _IO_ssize_t count = write (f->_fileno, data, to_do);
96aa2d94
RM
674 if (count == EOF)
675 {
39e16978
UD
676 f->_flags |= _IO_ERR_SEEN;
677 break;
96aa2d94
RM
678 }
679 to_do -= count;
40a55d20 680 data = (void *) ((char *) data + count);
96aa2d94
RM
681 }
682 n -= to_do;
bd355af0
UD
683 if (f->_offset >= 0)
684 f->_offset += n;
96aa2d94
RM
685 return n;
686}
687
688_IO_size_t
40a55d20
UD
689_IO_file_xsputn (f, data, n)
690 _IO_FILE *f;
691 const void *data;
692 _IO_size_t n;
96aa2d94 693{
40a55d20 694 register const char *s = (char *) data;
96aa2d94
RM
695 _IO_size_t to_do = n;
696 int must_flush = 0;
697 _IO_size_t count;
698
699 if (n <= 0)
700 return 0;
701 /* This is an optimized implementation.
702 If the amount to be written straddles a block boundary
703 (or the filebuf is unbuffered), use sys_write directly. */
704
705 /* First figure out how much space is available in the buffer. */
706 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
707 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
708 {
709 count = f->_IO_buf_end - f->_IO_write_ptr;
710 if (count >= n)
40a55d20
UD
711 {
712 register const char *p;
96aa2d94
RM
713 for (p = s + n; p > s; )
714 {
40a55d20
UD
715 if (*--p == '\n')
716 {
717 count = p - s + 1;
718 must_flush = 1;
719 break;
720 }
96aa2d94
RM
721 }
722 }
723 }
724 /* Then fill the buffer. */
725 if (count > 0)
726 {
727 if (count > to_do)
728 count = to_do;
40a55d20
UD
729 if (count > 20)
730 {
86187531
UD
731#ifdef _LIBC
732 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
733#else
40a55d20 734 memcpy (f->_IO_write_ptr, s, count);
86187531
UD
735 f->_IO_write_ptr += count;
736#endif
40a55d20
UD
737 s += count;
738 }
96aa2d94
RM
739 else
740 {
741 register char *p = f->_IO_write_ptr;
40a55d20
UD
742 register int i = (int) count;
743 while (--i >= 0)
744 *p++ = *s++;
86187531 745 f->_IO_write_ptr = p;
96aa2d94 746 }
96aa2d94
RM
747 to_do -= count;
748 }
749 if (to_do + must_flush > 0)
40a55d20
UD
750 {
751 _IO_size_t block_size, dont_write;
96aa2d94 752 /* Next flush the (full) buffer. */
40a55d20 753 if (__overflow (f, EOF) == EOF)
96aa2d94
RM
754 return n - to_do;
755
756 /* Try to maintain alignment: write a whole number of blocks.
757 dont_write is what gets left over. */
758 block_size = f->_IO_buf_end - f->_IO_buf_base;
759 dont_write = block_size >= 128 ? to_do % block_size : 0;
760
761 count = to_do - dont_write;
40a55d20 762 if (_IO_do_write (f, s, count) == EOF)
96aa2d94
RM
763 return n - to_do;
764 to_do = dont_write;
23396375 765
96aa2d94
RM
766 /* Now write out the remainder. Normally, this will fit in the
767 buffer, but it's somewhat messier for line-buffered files,
768 so we let _IO_default_xsputn handle the general case. */
769 if (dont_write)
40a55d20 770 to_do -= _IO_default_xsputn (f, s+count, dont_write);
96aa2d94
RM
771 }
772 return n - to_do;
773}
774
96aa2d94 775_IO_size_t
40a55d20
UD
776_IO_file_xsgetn (fp, data, n)
777 _IO_FILE *fp;
778 void *data;
779 _IO_size_t n;
96aa2d94 780{
4bca4c17
UD
781 register _IO_size_t want, have;
782 register _IO_ssize_t count;
96aa2d94 783 register char *s = data;
8fe0fd03
UD
784
785 want = n;
786
787 while (want > 0)
96aa2d94 788 {
8fe0fd03
UD
789 have = fp->_IO_read_end - fp->_IO_read_ptr;
790 if (want <= have)
96aa2d94 791 {
8fe0fd03
UD
792 memcpy (s, fp->_IO_read_ptr, want);
793 fp->_IO_read_ptr += want;
794 want = 0;
795 }
796 else
797 {
798 if (have > 0)
96aa2d94 799 {
279eb600
UD
800#ifdef _LIBC
801 s = __mempcpy (s, fp->_IO_read_ptr, have);
802#else
8fe0fd03 803 memcpy (s, fp->_IO_read_ptr, have);
8fe0fd03 804 s += have;
279eb600
UD
805#endif
806 want -= have;
8fe0fd03 807 fp->_IO_read_ptr += have;
96aa2d94 808 }
8fe0fd03
UD
809
810 /* Check for backup and repeat */
811 if (_IO_in_backup (fp))
96aa2d94 812 {
8fe0fd03
UD
813 _IO_switch_to_main_get_area (fp);
814 continue;
815 }
816
817 /* If we now want less than a buffer, underflow and repeat
818 the copy. Otherwise, _IO_SYSREAD directly to
819 the user buffer. */
3c720987 820 if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
8fe0fd03
UD
821 {
822 if (__underflow (fp) == EOF)
823 break;
824
825 continue;
826 }
827
4bca4c17
UD
828 /* These must be set before the sysread as we might longjmp out
829 waiting for input. */
830 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
831 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
832
279eb600
UD
833 /* Try to maintain alignment: read a whole number of blocks. */
834 count = want;
835 if (fp->_IO_buf_base)
836 {
837 _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
838 if (block_size >= 128)
839 count -= want % block_size;
840 }
841
842 count = _IO_SYSREAD (fp, s, count);
96aa2d94 843 if (count <= 0)
8fe0fd03
UD
844 {
845 if (count == 0)
846 fp->_flags |= _IO_EOF_SEEN;
847 else
848 fp->_flags |= _IO_ERR_SEEN;
849
850 break;
851 }
23396375 852
96aa2d94 853 s += count;
8fe0fd03 854 want -= count;
4bca4c17
UD
855 if (fp->_offset != _IO_pos_BAD)
856 _IO_pos_adjust (fp->_offset, count);
96aa2d94 857 }
96aa2d94 858 }
8fe0fd03
UD
859
860 return n - want;
96aa2d94 861}
96aa2d94 862
40a55d20
UD
863struct _IO_jump_t _IO_file_jumps =
864{
96aa2d94
RM
865 JUMP_INIT_DUMMY,
866 JUMP_INIT(finish, _IO_file_finish),
867 JUMP_INIT(overflow, _IO_file_overflow),
868 JUMP_INIT(underflow, _IO_file_underflow),
869 JUMP_INIT(uflow, _IO_default_uflow),
870 JUMP_INIT(pbackfail, _IO_default_pbackfail),
871 JUMP_INIT(xsputn, _IO_file_xsputn),
8fe0fd03 872 JUMP_INIT(xsgetn, _IO_file_xsgetn),
96aa2d94
RM
873 JUMP_INIT(seekoff, _IO_file_seekoff),
874 JUMP_INIT(seekpos, _IO_default_seekpos),
875 JUMP_INIT(setbuf, _IO_file_setbuf),
876 JUMP_INIT(sync, _IO_file_sync),
877 JUMP_INIT(doallocate, _IO_file_doallocate),
878 JUMP_INIT(read, _IO_file_read),
879 JUMP_INIT(write, _IO_file_write),
880 JUMP_INIT(seek, _IO_file_seek),
881 JUMP_INIT(close, _IO_file_close),
dfd2257a
UD
882 JUMP_INIT(stat, _IO_file_stat),
883 JUMP_INIT(showmanyc, _IO_default_showmanyc),
884 JUMP_INIT(imbue, _IO_default_imbue)
96aa2d94 885};