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