]> sourceware.org Git - glibc.git/blame - libio/fileops.c
Update.
[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;
40a55d20
UD
319 fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
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
413 if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
414 f->_IO_write_end = f->_IO_write_ptr;
415 f->_flags |= _IO_CURRENTLY_PUTTING;
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
RM
433{
434 _IO_size_t delta;
61eb22d3
UD
435 int retval = 0;
436
437 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
438 _IO_flockfile (fp);
96aa2d94
RM
439 /* char* ptr = cur_ptr(); */
440 if (fp->_IO_write_ptr > fp->_IO_write_base)
441 if (_IO_do_flush(fp)) return EOF;
23396375 442 delta = fp->_IO_read_ptr - fp->_IO_read_end;
96aa2d94
RM
443 if (delta != 0)
444 {
445#ifdef TODO
40a55d20
UD
446 if (_IO_in_backup (fp))
447 delta -= eGptr () - Gbase ();
96aa2d94 448#endif
dfd2257a
UD
449 _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
450 if (new_pos != (_IO_off64_t) EOF)
96aa2d94
RM
451 fp->_IO_read_end = fp->_IO_read_ptr;
452#ifdef ESPIPE
453 else if (errno == ESPIPE)
454 ; /* Ignore error from unseekable devices. */
455#endif
456 else
61eb22d3 457 retval = EOF;
96aa2d94 458 }
61eb22d3 459 if (retval != EOF)
bd355af0 460 fp->_offset = _IO_pos_BAD;
96aa2d94
RM
461 /* FIXME: Cleanup - can this be shared? */
462 /* setg(base(), ptr, ptr); */
61eb22d3
UD
463 _IO_cleanup_region_end (1);
464 return retval;
96aa2d94
RM
465}
466
dfd2257a 467_IO_fpos64_t
40a55d20
UD
468_IO_file_seekoff (fp, offset, dir, mode)
469 _IO_FILE *fp;
dfd2257a 470 _IO_off64_t offset;
40a55d20
UD
471 int dir;
472 int mode;
96aa2d94 473{
dfd2257a
UD
474 _IO_fpos64_t result;
475 _IO_off64_t delta, new_offset;
96aa2d94 476 long count;
feb3c934
UD
477 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
478 offset of the underlying file must be exact. */
479 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
480 && fp->_IO_write_base == fp->_IO_write_ptr);
96aa2d94
RM
481
482 if (mode == 0)
483 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
484
485 /* Flush unwritten characters.
486 (This may do an unneeded write if we seek within the buffer.
487 But to be able to switch to reading, we would need to set
488 egptr to ptr. That can't be done in the current design,
489 which assumes file_ptr() is eGptr. Anyway, since we probably
490 end up flushing when we close(), it doesn't make much difference.)
491 FIXME: simulate mem-papped files. */
492
40a55d20
UD
493 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
494 if (_IO_switch_to_get_mode (fp))
495 return EOF;
96aa2d94
RM
496
497 if (fp->_IO_buf_base == NULL)
498 {
40a55d20
UD
499 _IO_doallocbuf (fp);
500 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
501 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
502 }
503
504 switch (dir)
505 {
506 case _IO_seek_cur:
507 /* Adjust for read-ahead (bytes is buffer). */
508 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
bd355af0 509 if (fp->_offset == _IO_pos_BAD)
96aa2d94
RM
510 goto dumb;
511 /* Make offset absolute, assuming current pointer is file_ptr(). */
bd355af0 512 offset += _IO_pos_as_off (fp->_offset);
96aa2d94
RM
513
514 dir = _IO_seek_set;
515 break;
516 case _IO_seek_set:
517 break;
518 case _IO_seek_end:
519 {
dfd2257a 520 struct _G_stat64 st;
40a55d20 521 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
96aa2d94
RM
522 {
523 offset += st.st_size;
524 dir = _IO_seek_set;
525 }
526 else
527 goto dumb;
528 }
529 }
530 /* At this point, dir==_IO_seek_set. */
531
532 /* If destination is within current buffer, optimize: */
bd355af0 533 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
96aa2d94
RM
534 && !_IO_in_backup (fp))
535 {
536 /* Offset relative to start of main get area. */
bd355af0 537 _IO_fpos64_t rel_offset = (offset - fp->_offset
dfd2257a 538 + (fp->_IO_read_end - fp->_IO_read_base));
96aa2d94
RM
539 if (rel_offset >= 0)
540 {
541#if 0
40a55d20
UD
542 if (_IO_in_backup (fp))
543 _IO_switch_to_main_get_area (fp);
96aa2d94
RM
544#endif
545 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
546 {
40a55d20
UD
547 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
548 fp->_IO_read_end);
549 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
550 return offset;
551 }
552#ifdef TODO
553 /* If we have streammarkers, seek forward by reading ahead. */
40a55d20 554 if (_IO_have_markers (fp))
96aa2d94
RM
555 {
556 int to_skip = rel_offset
557 - (fp->_IO_read_ptr - fp->_IO_read_base);
40a55d20 558 if (ignore (to_skip) != to_skip)
96aa2d94
RM
559 goto dumb;
560 return offset;
561 }
562#endif
563 }
564#ifdef TODO
40a55d20 565 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
96aa2d94 566 {
40a55d20
UD
567 if (!_IO_in_backup (fp))
568 _IO_switch_to_backup_area (fp);
569 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
96aa2d94
RM
570 return offset;
571 }
572#endif
573 }
574
575#ifdef TODO
40a55d20 576 _IO_unsave_markers (fp);
96aa2d94
RM
577#endif
578
579 if (fp->_flags & _IO_NO_READS)
580 goto dumb;
581
582 /* Try to seek to a block boundary, to improve kernel page management. */
583 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
584 delta = offset - new_offset;
585 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
586 {
587 new_offset = offset;
588 delta = 0;
589 }
590 result = _IO_SYSSEEK (fp, new_offset, 0);
591 if (result < 0)
592 return EOF;
593 if (delta == 0)
594 count = 0;
595 else
596 {
597 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
feb3c934
UD
598 (must_be_exact
599 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
96aa2d94
RM
600 if (count < delta)
601 {
602 /* We weren't allowed to read, but try to seek the remainder. */
603 offset = count == EOF ? delta : delta-count;
604 dir = _IO_seek_cur;
605 goto dumb;
606 }
607 }
40a55d20
UD
608 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
609 fp->_IO_buf_base + count);
610 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
bd355af0 611 fp->_offset = result + count;
40a55d20 612 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
96aa2d94
RM
613 return offset;
614 dumb:
615
40a55d20 616 _IO_unsave_markers (fp);
96aa2d94
RM
617 result = _IO_SYSSEEK (fp, offset, dir);
618 if (result != EOF)
40a55d20 619 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
bd355af0 620 fp->_offset = result;
40a55d20
UD
621 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
622 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
623 return result;
624}
625
626_IO_ssize_t
40a55d20
UD
627_IO_file_read (fp, buf, size)
628 _IO_FILE *fp;
629 void *buf;
630 _IO_ssize_t size;
96aa2d94 631{
61eb22d3 632 return read (fp->_fileno, buf, size);
96aa2d94
RM
633}
634
dfd2257a 635_IO_fpos64_t
40a55d20
UD
636_IO_file_seek (fp, offset, dir)
637 _IO_FILE *fp;
dfd2257a 638 _IO_off64_t offset;
40a55d20 639 int dir;
96aa2d94 640{
dfd2257a
UD
641#ifdef _G_LSEEK64
642 return _G_LSEEK64 (fp->_fileno, offset, dir);
643#else
61eb22d3 644 return lseek (fp->_fileno, offset, dir);
dfd2257a 645#endif
96aa2d94
RM
646}
647
648int
40a55d20
UD
649_IO_file_stat (fp, st)
650 _IO_FILE *fp;
651 void *st;
96aa2d94 652{
279eb600 653#ifdef _G_FSTAT64
dfd2257a
UD
654 return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
655#else
656 return fstat (fp->_fileno, (struct _G_stat64 *) st);
657#endif
96aa2d94
RM
658}
659
660int
40a55d20
UD
661_IO_file_close (fp)
662 _IO_FILE *fp;
96aa2d94 663{
61eb22d3 664 return close (fp->_fileno);
96aa2d94
RM
665}
666
667_IO_ssize_t
40a55d20
UD
668_IO_file_write (f, data, n)
669 _IO_FILE *f;
670 const void *data;
671 _IO_ssize_t n;
96aa2d94
RM
672{
673 _IO_ssize_t to_do = n;
674 while (to_do > 0)
675 {
61eb22d3 676 _IO_ssize_t count = write (f->_fileno, data, to_do);
96aa2d94
RM
677 if (count == EOF)
678 {
39e16978
UD
679 f->_flags |= _IO_ERR_SEEN;
680 break;
96aa2d94
RM
681 }
682 to_do -= count;
40a55d20 683 data = (void *) ((char *) data + count);
96aa2d94
RM
684 }
685 n -= to_do;
bd355af0
UD
686 if (f->_offset >= 0)
687 f->_offset += n;
96aa2d94
RM
688 return n;
689}
690
691_IO_size_t
40a55d20
UD
692_IO_file_xsputn (f, data, n)
693 _IO_FILE *f;
694 const void *data;
695 _IO_size_t n;
96aa2d94 696{
40a55d20 697 register const char *s = (char *) data;
96aa2d94
RM
698 _IO_size_t to_do = n;
699 int must_flush = 0;
700 _IO_size_t count;
701
702 if (n <= 0)
703 return 0;
704 /* This is an optimized implementation.
705 If the amount to be written straddles a block boundary
706 (or the filebuf is unbuffered), use sys_write directly. */
707
708 /* First figure out how much space is available in the buffer. */
709 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
710 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
711 {
712 count = f->_IO_buf_end - f->_IO_write_ptr;
713 if (count >= n)
40a55d20
UD
714 {
715 register const char *p;
96aa2d94
RM
716 for (p = s + n; p > s; )
717 {
40a55d20
UD
718 if (*--p == '\n')
719 {
720 count = p - s + 1;
721 must_flush = 1;
722 break;
723 }
96aa2d94
RM
724 }
725 }
726 }
727 /* Then fill the buffer. */
728 if (count > 0)
729 {
730 if (count > to_do)
731 count = to_do;
40a55d20
UD
732 if (count > 20)
733 {
86187531
UD
734#ifdef _LIBC
735 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
736#else
40a55d20 737 memcpy (f->_IO_write_ptr, s, count);
86187531
UD
738 f->_IO_write_ptr += count;
739#endif
40a55d20
UD
740 s += count;
741 }
96aa2d94
RM
742 else
743 {
744 register char *p = f->_IO_write_ptr;
40a55d20
UD
745 register int i = (int) count;
746 while (--i >= 0)
747 *p++ = *s++;
86187531 748 f->_IO_write_ptr = p;
96aa2d94 749 }
96aa2d94
RM
750 to_do -= count;
751 }
752 if (to_do + must_flush > 0)
40a55d20
UD
753 {
754 _IO_size_t block_size, dont_write;
96aa2d94 755 /* Next flush the (full) buffer. */
40a55d20 756 if (__overflow (f, EOF) == EOF)
96aa2d94
RM
757 return n - to_do;
758
759 /* Try to maintain alignment: write a whole number of blocks.
760 dont_write is what gets left over. */
761 block_size = f->_IO_buf_end - f->_IO_buf_base;
762 dont_write = block_size >= 128 ? to_do % block_size : 0;
763
764 count = to_do - dont_write;
40a55d20 765 if (_IO_do_write (f, s, count) == EOF)
96aa2d94
RM
766 return n - to_do;
767 to_do = dont_write;
23396375 768
96aa2d94
RM
769 /* Now write out the remainder. Normally, this will fit in the
770 buffer, but it's somewhat messier for line-buffered files,
771 so we let _IO_default_xsputn handle the general case. */
772 if (dont_write)
40a55d20 773 to_do -= _IO_default_xsputn (f, s+count, dont_write);
96aa2d94
RM
774 }
775 return n - to_do;
776}
777
96aa2d94 778_IO_size_t
40a55d20
UD
779_IO_file_xsgetn (fp, data, n)
780 _IO_FILE *fp;
781 void *data;
782 _IO_size_t n;
96aa2d94 783{
4bca4c17
UD
784 register _IO_size_t want, have;
785 register _IO_ssize_t count;
96aa2d94 786 register char *s = data;
8fe0fd03
UD
787
788 want = n;
789
790 while (want > 0)
96aa2d94 791 {
8fe0fd03
UD
792 have = fp->_IO_read_end - fp->_IO_read_ptr;
793 if (want <= have)
96aa2d94 794 {
8fe0fd03
UD
795 memcpy (s, fp->_IO_read_ptr, want);
796 fp->_IO_read_ptr += want;
797 want = 0;
798 }
799 else
800 {
801 if (have > 0)
96aa2d94 802 {
279eb600
UD
803#ifdef _LIBC
804 s = __mempcpy (s, fp->_IO_read_ptr, have);
805#else
8fe0fd03 806 memcpy (s, fp->_IO_read_ptr, have);
8fe0fd03 807 s += have;
279eb600
UD
808#endif
809 want -= have;
8fe0fd03 810 fp->_IO_read_ptr += have;
96aa2d94 811 }
8fe0fd03
UD
812
813 /* Check for backup and repeat */
814 if (_IO_in_backup (fp))
96aa2d94 815 {
8fe0fd03
UD
816 _IO_switch_to_main_get_area (fp);
817 continue;
818 }
819
820 /* If we now want less than a buffer, underflow and repeat
821 the copy. Otherwise, _IO_SYSREAD directly to
822 the user buffer. */
3c720987 823 if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
8fe0fd03
UD
824 {
825 if (__underflow (fp) == EOF)
826 break;
827
828 continue;
829 }
830
4bca4c17
UD
831 /* These must be set before the sysread as we might longjmp out
832 waiting for input. */
833 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
834 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
835
279eb600
UD
836 /* Try to maintain alignment: read a whole number of blocks. */
837 count = want;
838 if (fp->_IO_buf_base)
839 {
840 _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
841 if (block_size >= 128)
842 count -= want % block_size;
843 }
844
845 count = _IO_SYSREAD (fp, s, count);
96aa2d94 846 if (count <= 0)
8fe0fd03
UD
847 {
848 if (count == 0)
849 fp->_flags |= _IO_EOF_SEEN;
850 else
851 fp->_flags |= _IO_ERR_SEEN;
852
853 break;
854 }
23396375 855
96aa2d94 856 s += count;
8fe0fd03 857 want -= count;
4bca4c17
UD
858 if (fp->_offset != _IO_pos_BAD)
859 _IO_pos_adjust (fp->_offset, count);
96aa2d94 860 }
96aa2d94 861 }
8fe0fd03
UD
862
863 return n - want;
96aa2d94 864}
96aa2d94 865
40a55d20
UD
866struct _IO_jump_t _IO_file_jumps =
867{
96aa2d94
RM
868 JUMP_INIT_DUMMY,
869 JUMP_INIT(finish, _IO_file_finish),
870 JUMP_INIT(overflow, _IO_file_overflow),
871 JUMP_INIT(underflow, _IO_file_underflow),
872 JUMP_INIT(uflow, _IO_default_uflow),
873 JUMP_INIT(pbackfail, _IO_default_pbackfail),
874 JUMP_INIT(xsputn, _IO_file_xsputn),
8fe0fd03 875 JUMP_INIT(xsgetn, _IO_file_xsgetn),
96aa2d94
RM
876 JUMP_INIT(seekoff, _IO_file_seekoff),
877 JUMP_INIT(seekpos, _IO_default_seekpos),
878 JUMP_INIT(setbuf, _IO_file_setbuf),
879 JUMP_INIT(sync, _IO_file_sync),
880 JUMP_INIT(doallocate, _IO_file_doallocate),
881 JUMP_INIT(read, _IO_file_read),
882 JUMP_INIT(write, _IO_file_write),
883 JUMP_INIT(seek, _IO_file_seek),
884 JUMP_INIT(close, _IO_file_close),
dfd2257a
UD
885 JUMP_INIT(stat, _IO_file_stat),
886 JUMP_INIT(showmanyc, _IO_default_showmanyc),
887 JUMP_INIT(imbue, _IO_default_imbue)
96aa2d94 888};
This page took 0.165743 seconds and 5 git commands to generate.