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