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