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