|
|
1.1 ! root 1: /* ! 2: Copyright (C) 1993 Free Software Foundation ! 3: ! 4: This file is part of the GNU IO Library. This library is free ! 5: software; you can redistribute it and/or modify it under the ! 6: terms of the GNU General Public License as published by the ! 7: Free Software Foundation; either version 2, or (at your option) ! 8: any later version. ! 9: ! 10: This library is distributed in the hope that it will be useful, ! 11: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 13: GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with GNU CC; see the file COPYING. If not, write to ! 17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 18: ! 19: As a special exception, if you link this library with files ! 20: compiled with a GNU compiler to produce an executable, this does not cause ! 21: the resulting executable to be covered by the GNU General Public License. ! 22: This exception does not however invalidate any other reasons why ! 23: the executable file might be covered by the GNU General Public License. */ ! 24: ! 25: /* written by Per Bothner ([email protected]) */ ! 26: ! 27: #define _POSIX_SOURCE ! 28: #include "libioP.h" ! 29: #include <fcntl.h> ! 30: #include <sys/types.h> ! 31: #include <sys/stat.h> ! 32: #include <string.h> ! 33: #include <errno.h> ! 34: #ifndef errno ! 35: extern int errno; ! 36: #endif ! 37: ! 38: /* An fstream can be in at most one of put mode, get mode, or putback mode. ! 39: Putback mode is a variant of get mode. ! 40: ! 41: In a filebuf, there is only one current position, instead of two ! 42: separate get and put pointers. In get mode, the current posistion ! 43: is that of gptr(); in put mode that of pptr(). ! 44: ! 45: The position in the buffer that corresponds to the position ! 46: in external file system is file_ptr(). ! 47: This is normally egptr(), except in putback mode, when it is _save_egptr. ! 48: If the field _fb._offset is >= 0, it gives the offset in ! 49: the file as a whole corresponding to eGptr(). (???) ! 50: ! 51: PUT MODE: ! 52: If a filebuf is in put mode, pbase() is non-NULL and equal to base(). ! 53: Also, epptr() == ebuf(). ! 54: Also, eback() == gptr() && gptr() == egptr(). ! 55: The un-flushed character are those between pbase() and pptr(). ! 56: GET MODE: ! 57: If a filebuf is in get or putback mode, eback() != egptr(). ! 58: In get mode, the unread characters are between gptr() and egptr(). ! 59: The OS file position corresponds to that of egptr(). ! 60: PUTBACK MODE: ! 61: Putback mode is used to remember "excess" characters that have ! 62: been sputbackc'd in a separate putback buffer. ! 63: In putback mode, the get buffer points to the special putback buffer. ! 64: The unread characters are the characters between gptr() and egptr() ! 65: in the putback buffer, as well as the area between save_gptr() ! 66: and save_egptr(), which point into the original reserve buffer. ! 67: (The pointers save_gptr() and save_egptr() are the values ! 68: of gptr() and egptr() at the time putback mode was entered.) ! 69: The OS position corresponds to that of save_egptr(). ! 70: ! 71: LINE BUFFERED OUTPUT: ! 72: During line buffered output, pbase()==base() && epptr()==base(). ! 73: However, ptr() may be anywhere between base() and ebuf(). ! 74: This forces a call to filebuf::overflow(int C) on every put. ! 75: If there is more space in the buffer, and C is not a '\n', ! 76: then C is inserted, and pptr() incremented. ! 77: ! 78: UNBUFFERED STREAMS: ! 79: If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer. ! 80: */ ! 81: ! 82: #define CLOSED_FILEBUF_FLAGS \ ! 83: (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET) ! 84: ! 85: ! 86: void ! 87: _IO_file_init(fp) ! 88: register _IO_FILE *fp; ! 89: { ! 90: fp->_offset = _IO_pos_0; ! 91: ! 92: _IO_link_in(fp); ! 93: fp->_fileno = -1; ! 94: } ! 95: ! 96: int ! 97: _IO_file_close_it(fp) ! 98: register _IO_FILE* fp; ! 99: { ! 100: int status; ! 101: if (!_IO_file_is_open(fp)) ! 102: return EOF; ! 103: ! 104: /* This flushes as well as switching mode. */ ! 105: if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode(fp)) ! 106: if (_IO_switch_to_get_mode(fp)) ! 107: return EOF; ! 108: ! 109: _IO_unsave_markers(fp); ! 110: ! 111: status = fp->_jumps->__close(fp); ! 112: ! 113: /* Free buffer. */ ! 114: _IO_setb(fp, NULL, NULL, 0); ! 115: _IO_setg(fp, NULL, NULL, NULL); ! 116: _IO_setp(fp, NULL, NULL); ! 117: ! 118: _IO_un_link(fp); ! 119: fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS; ! 120: fp->_fileno = EOF; ! 121: fp->_offset = _IO_pos_0; ! 122: ! 123: return status; ! 124: } ! 125: ! 126: void ! 127: _IO_file_finish(fp) ! 128: register _IO_FILE* fp; ! 129: { ! 130: if (!(fp->_flags & _IO_DELETE_DONT_CLOSE)) ! 131: _IO_file_close_it(fp); ! 132: _IO_default_finish(fp); ! 133: } ! 134: ! 135: _IO_FILE * ! 136: _IO_file_fopen(fp, filename, mode) ! 137: register _IO_FILE *fp; ! 138: const char *filename; ! 139: const char *mode; ! 140: { ! 141: int oflags = 0, omode; ! 142: int read_write, fdesc; ! 143: int oprot = 0666; ! 144: if (_IO_file_is_open (fp)) ! 145: return 0; ! 146: switch (*mode++) { ! 147: case 'r': ! 148: omode = O_RDONLY; ! 149: read_write = _IO_NO_WRITES; ! 150: break; ! 151: case 'w': ! 152: omode = O_WRONLY; ! 153: oflags = O_CREAT|O_TRUNC; ! 154: read_write = _IO_NO_READS; ! 155: break; ! 156: case 'a': ! 157: omode = O_WRONLY; ! 158: oflags = O_CREAT|O_APPEND; ! 159: read_write = _IO_NO_READS|_IO_IS_APPENDING; ! 160: break; ! 161: default: ! 162: errno = EINVAL; ! 163: return NULL; ! 164: } ! 165: if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) { ! 166: omode = O_RDWR; ! 167: read_write &= _IO_IS_APPENDING; ! 168: } ! 169: fdesc = open(filename, omode|oflags, oprot); ! 170: if (fdesc < 0) ! 171: return NULL; ! 172: fp->_fileno = fdesc; ! 173: fp->_IO_file_flags = ! 174: _IO_mask_flags(fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); ! 175: if (read_write & _IO_IS_APPENDING) ! 176: if (fp->_jumps->__seekoff(fp, (_IO_off_t)0, _IO_seek_end) == _IO_pos_BAD) ! 177: return NULL; ! 178: _IO_link_in(fp); ! 179: return fp; ! 180: } ! 181: ! 182: _IO_FILE* ! 183: _IO_file_attach(fp, fd) ! 184: _IO_FILE *fp; ! 185: int fd; ! 186: { ! 187: if (_IO_file_is_open(fp)) ! 188: return NULL; ! 189: fp->_fileno = fd; ! 190: fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES); ! 191: fp->_offset = _IO_pos_BAD; ! 192: return fp; ! 193: } ! 194: ! 195: int ! 196: _IO_file_setbuf(fp, p, len) ! 197: register _IO_FILE *fp; ! 198: char* p; ! 199: _IO_ssize_t len; ! 200: { ! 201: if (_IO_default_setbuf(fp, p, len) == EOF) ! 202: return EOF; ! 203: ! 204: fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end ! 205: = fp->_IO_buf_base; ! 206: _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); ! 207: ! 208: return 0; ! 209: } ! 210: ! 211: int ! 212: _IO_do_write(fp, data, to_do) ! 213: register _IO_FILE *fp; ! 214: const char* data; ! 215: _IO_size_t to_do; ! 216: { ! 217: _IO_size_t count; ! 218: if (to_do == 0) ! 219: return 0; ! 220: if (fp->_flags & _IO_IS_APPENDING) ! 221: /* On a system without a proper O_APPEND implementation, ! 222: you would need to sys_seek(0, SEEK_END) here, but is ! 223: is not needed nor desirable for Unix- or Posix-like systems. ! 224: Instead, just indicate that offset (before and after) is ! 225: unpredictable. */ ! 226: fp->_offset = _IO_pos_BAD; ! 227: else if (fp->_IO_read_end != fp->_IO_write_base) ! 228: { ! 229: _IO_pos_t new_pos = fp->_jumps->__seek(fp, fp->_IO_write_base - fp->_IO_read_end, 1); ! 230: if (new_pos == _IO_pos_BAD) ! 231: return EOF; ! 232: fp->_offset = new_pos; ! 233: } ! 234: count = fp->_jumps->__write(fp, data, to_do); ! 235: if (fp->_cur_column) ! 236: fp->_cur_column = _IO_adjust_column(fp->_cur_column - 1, data, to_do) + 1; ! 237: _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); ! 238: fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base; ! 239: fp->_IO_write_end = (fp->_flags & _IO_LINE_BUF+_IO_UNBUFFERED) ? fp->_IO_buf_base ! 240: : fp->_IO_buf_end; ! 241: return count != to_do ? EOF : 0; ! 242: } ! 243: ! 244: int ! 245: _IO_file_underflow(fp) ! 246: register _IO_FILE *fp; ! 247: { ! 248: _IO_size_t count; ! 249: #if 0 ! 250: /* SysV does not make this test; take it out for compatibility */ ! 251: if (fp->_flags & _IO_EOF_SEEN) ! 252: return (EOF); ! 253: #endif ! 254: ! 255: if (fp->_flags & _IO_NO_READS) ! 256: return EOF; ! 257: if (fp->_IO_read_ptr < fp->_IO_read_end) ! 258: return *(unsigned char*)fp->_IO_read_ptr; ! 259: ! 260: if (fp->_IO_buf_base == NULL) ! 261: _IO_doallocbuf(fp); ! 262: ! 263: /* Flush all line buffered files before reading. */ ! 264: /* FIXME This can/should be moved to genops ?? */ ! 265: if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) ! 266: _IO_flush_all_linebuffered(); ! 267: ! 268: _IO_switch_to_get_mode(fp); ! 269: ! 270: count = fp->_jumps->__read(fp, fp->_IO_buf_base, ! 271: fp->_IO_buf_end - fp->_IO_buf_base); ! 272: if (count <= 0) ! 273: { ! 274: if (count == 0) ! 275: fp->_flags |= _IO_EOF_SEEN; ! 276: else ! 277: fp->_flags |= _IO_ERR_SEEN, count = 0; ! 278: } ! 279: fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; ! 280: fp->_IO_read_end = fp->_IO_buf_base + count; ! 281: fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end ! 282: = fp->_IO_buf_base; ! 283: if (count == 0) ! 284: return EOF; ! 285: if (fp->_offset != _IO_pos_BAD) ! 286: _IO_pos_adjust(fp->_offset, count); ! 287: return *(unsigned char*)fp->_IO_read_ptr; ! 288: } ! 289: ! 290: int _IO_file_overflow (f, ch) ! 291: register _IO_FILE* f; ! 292: int ch; ! 293: { ! 294: if (f->_flags & _IO_NO_WRITES) /* SET ERROR */ ! 295: return EOF; ! 296: /* If current reading or no buffer allocated. */ ! 297: if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0) ! 298: { ! 299: /* Allocate a buffer if needed. */ ! 300: if (f->_IO_buf_base == 0) ! 301: { ! 302: _IO_doallocbuf(f); ! 303: f->_IO_read_end = f->_IO_buf_base; ! 304: f->_IO_write_ptr = f->_IO_buf_base; ! 305: } ! 306: else /* Must be currently reading. */ ! 307: f->_IO_write_ptr = f->_IO_read_ptr; ! 308: f->_IO_write_base = f->_IO_write_ptr; ! 309: f->_IO_write_end = f->_IO_buf_end; ! 310: f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end; ! 311: ! 312: if (f->_flags & _IO_LINE_BUF+_IO_UNBUFFERED) ! 313: f->_IO_write_end = f->_IO_write_ptr; ! 314: f->_flags |= _IO_CURRENTLY_PUTTING; ! 315: } ! 316: if (ch == EOF) ! 317: return _IO_do_flush(f); ! 318: if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */ ! 319: if (_IO_do_flush(f) == EOF) ! 320: return EOF; ! 321: *f->_IO_write_ptr++ = ch; ! 322: if ((f->_flags & _IO_UNBUFFERED) ! 323: || ((f->_flags & _IO_LINE_BUF) && ch == '\n')) ! 324: if (_IO_do_flush(f) == EOF) ! 325: return EOF; ! 326: return (unsigned char)ch; ! 327: } ! 328: ! 329: int ! 330: _IO_file_sync(fp) ! 331: register _IO_FILE* fp; ! 332: { ! 333: _IO_size_t delta; ! 334: /* char* ptr = cur_ptr(); */ ! 335: if (fp->_IO_write_ptr > fp->_IO_write_base) ! 336: if (_IO_do_flush(fp)) return EOF; ! 337: delta = fp->_IO_read_ptr - fp->_IO_read_end; ! 338: if (delta != 0) ! 339: { ! 340: #ifdef TODO ! 341: if (_IO_in_backup(fp)) ! 342: delta -= eGptr() - Gbase(); ! 343: #endif ! 344: _IO_off_t new_pos = fp->_jumps->__seek(fp, delta, 1); ! 345: if (new_pos == (_IO_off_t)EOF) ! 346: return EOF; ! 347: fp->_offset = new_pos; ! 348: fp->_IO_read_end = fp->_IO_read_ptr; ! 349: } ! 350: /* FIXME: Cleanup - can this be shared? */ ! 351: /* setg(base(), ptr, ptr); */ ! 352: return 0; ! 353: } ! 354: ! 355: _IO_pos_t ! 356: _IO_file_seekoff(fp, offset, mode) ! 357: register _IO_FILE *fp; ! 358: _IO_off_t offset; ! 359: _IO_seekflags mode; ! 360: { ! 361: _IO_pos_t result; ! 362: _IO_off_t delta, new_offset; ! 363: long count; ! 364: int dir = mode & 3; ! 365: ! 366: if ((mode & _IO_seek_not_in) && (mode & _IO_seek_not_out)) ! 367: dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */ ! 368: ! 369: /* Flush unwritten characters. ! 370: (This may do an unneeded write if we seek within the buffer. ! 371: But to be able to switch to reading, we would need to set ! 372: egptr to ptr. That can't be done in the current design, ! 373: which assumes file_ptr() is eGptr. Anyway, since we probably ! 374: end up flushing when we close(), it doesn't make much difference.) ! 375: FIXME: simulate mem-papped files. */ ! 376: ! 377: if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode(fp)) ! 378: if (_IO_switch_to_get_mode(fp)) return EOF; ! 379: ! 380: if (fp->_IO_buf_base == NULL) ! 381: { ! 382: _IO_doallocbuf(fp); ! 383: _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base); ! 384: _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); ! 385: } ! 386: ! 387: switch (dir) ! 388: { ! 389: case _IO_seek_cur: ! 390: if (fp->_offset == _IO_pos_BAD) ! 391: goto dumb; ! 392: /* Adjust for read-ahead (bytes is buffer). */ ! 393: offset -= fp->_IO_read_end - fp->_IO_read_ptr; ! 394: /* Make offset absolute, assuming current pointer is file_ptr(). */ ! 395: offset += _IO_pos_as_off(fp->_offset); ! 396: ! 397: dir = _IO_seek_set; ! 398: break; ! 399: case _IO_seek_set: ! 400: break; ! 401: case _IO_seek_end: ! 402: { ! 403: struct stat st; ! 404: if (fp->_jumps->__stat(fp, &st) == 0 && S_ISREG(st.st_mode)) ! 405: { ! 406: offset += st.st_size; ! 407: dir = _IO_seek_set; ! 408: } ! 409: else ! 410: goto dumb; ! 411: } ! 412: } ! 413: /* At this point, dir==_IO_seek_set. */ ! 414: ! 415: #ifdef TODO ! 416: /* If destination is within current buffer, optimize: */ ! 417: if (fp->_offset != IO_pos_BAD && fp->_IO_read_base != NULL) ! 418: { ! 419: /* Offset relative to start of main get area. */ ! 420: _IO_pos_t rel_offset = offset - _fb._offset ! 421: + (eGptr()-Gbase()); ! 422: if (rel_offset >= 0) ! 423: { ! 424: if (_IO_in_backup(fp)) ! 425: _IO_switch_to_main_get_area(fp); ! 426: if (rel_offset <= _IO_read_end - _IO_read_base) ! 427: { ! 428: _IO_setg(fp->_IO_buf_base, fp->_IO_buf_base + rel_offset, ! 429: fp->_IO_read_end); ! 430: _IO_setp(fp->_IO_buf_base, fp->_IO_buf_base); ! 431: return offset; ! 432: } ! 433: /* If we have streammarkers, seek forward by reading ahead. */ ! 434: if (_IO_have_markers(fp)) ! 435: { ! 436: int to_skip = rel_offset ! 437: - (fp->_IO_read_ptr - fp->_IO_read_base); ! 438: if (ignore(to_skip) != to_skip) ! 439: goto dumb; ! 440: return offset; ! 441: } ! 442: } ! 443: if (rel_offset < 0 && rel_offset >= Bbase() - Bptr()) ! 444: { ! 445: if (!_IO_in_backup(fp)) ! 446: _IO_switch_to_backup_area(fp); ! 447: gbump(fp->_IO_read_end + rel_offset - fp->_IO_read_ptr); ! 448: return offset; ! 449: } ! 450: } ! 451: ! 452: _IO_unsave_markers(fp); ! 453: #endif ! 454: ! 455: /* Try to seek to a block boundary, to improve kernel page management. */ ! 456: new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1); ! 457: delta = offset - new_offset; ! 458: if (delta > fp->_IO_buf_end - fp->_IO_buf_base) ! 459: { ! 460: new_offset = offset; ! 461: delta = 0; ! 462: } ! 463: result = fp->_jumps->__seek(fp, new_offset, 0); ! 464: if (result < 0) ! 465: return EOF; ! 466: if (delta == 0) ! 467: count = 0; ! 468: else ! 469: { ! 470: count = fp->_jumps->__read(fp, fp->_IO_buf_base, ! 471: fp->_IO_buf_end - fp->_IO_buf_base); ! 472: if (count < delta) ! 473: { ! 474: /* We weren't allowed to read, but try to seek the remainder. */ ! 475: offset = count == EOF ? delta : delta-count; ! 476: dir = _IO_seek_cur; ! 477: goto dumb; ! 478: } ! 479: } ! 480: _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base+delta, fp->_IO_buf_base+count); ! 481: _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base); ! 482: fp->_offset = result + count; ! 483: _IO_mask_flags(fp, 0, _IO_EOF_SEEN); ! 484: return offset; ! 485: dumb: ! 486: ! 487: _IO_unsave_markers(fp); ! 488: result = fp->_jumps->__seek(fp, offset, dir); ! 489: if (result != EOF) ! 490: _IO_mask_flags(fp, 0, _IO_EOF_SEEN); ! 491: fp->_offset = result; ! 492: _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); ! 493: _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base); ! 494: return result; ! 495: } ! 496: ! 497: _IO_ssize_t ! 498: _IO_file_read(fp, buf, size) ! 499: register _IO_FILE* fp; ! 500: void* buf; ! 501: _IO_ssize_t size; ! 502: { ! 503: for (;;) ! 504: { ! 505: _IO_ssize_t count = _IO_read(fp->_fileno, buf, size); ! 506: #ifdef EINTR ! 507: if (errno == EINTR && count == -1) ! 508: continue; ! 509: #endif ! 510: return count; ! 511: } ! 512: } ! 513: ! 514: _IO_pos_t ! 515: _IO_file_seek(fp, offset, dir) ! 516: _IO_FILE *fp; ! 517: _IO_off_t offset; ! 518: int dir; ! 519: { ! 520: return _IO_lseek(fp->_fileno, offset, dir); ! 521: } ! 522: ! 523: int ! 524: _IO_file_stat(fp, st) ! 525: _IO_FILE *fp; ! 526: void* st; ! 527: { ! 528: return _IO_fstat(fp->_fileno, (struct stat*)st); ! 529: } ! 530: ! 531: int ! 532: _IO_file_close(fp) ! 533: _IO_FILE* fp; ! 534: { ! 535: return _IO_close(fp->_fileno); ! 536: } ! 537: ! 538: _IO_ssize_t ! 539: _IO_file_write(f, data, n) ! 540: register _IO_FILE* f; ! 541: const void* data; ! 542: _IO_ssize_t n; ! 543: { ! 544: _IO_ssize_t to_do = n; ! 545: while (to_do > 0) ! 546: { ! 547: _IO_ssize_t count = _IO_write(f->_fileno, data, to_do); ! 548: if (count == EOF) ! 549: { ! 550: #ifdef EINTR ! 551: if (errno == EINTR) ! 552: continue; ! 553: else ! 554: #endif ! 555: { ! 556: f->_flags |= _IO_ERR_SEEN; ! 557: break; ! 558: } ! 559: } ! 560: to_do -= count; ! 561: data = (void*)((char*)data + count); ! 562: } ! 563: n -= to_do; ! 564: if (f->_offset >= 0) ! 565: f->_offset += n; ! 566: return n; ! 567: } ! 568: ! 569: _IO_size_t ! 570: _IO_file_xsputn(f, data, n) ! 571: _IO_FILE *f; ! 572: const void *data; ! 573: _IO_size_t n; ! 574: { ! 575: register const char *s = data; ! 576: _IO_size_t to_do = n; ! 577: int must_flush = 0; ! 578: _IO_size_t count; ! 579: ! 580: if (n <= 0) ! 581: return 0; ! 582: /* This is an optimized implementation. ! 583: If the amount to be written straddles a block boundary ! 584: (or the filebuf is unbuffered), use sys_write directly. */ ! 585: ! 586: /* First figure out how much space is available in the buffer. */ ! 587: count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */ ! 588: if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) ! 589: { ! 590: count = f->_IO_buf_end - f->_IO_write_ptr; ! 591: if (count >= n) ! 592: { register const char *p; ! 593: for (p = s + n; p > s; ) ! 594: { ! 595: if (*--p == '\n') { ! 596: count = p - s + 1; ! 597: must_flush = 1; ! 598: break; ! 599: } ! 600: } ! 601: } ! 602: } ! 603: /* Then fill the buffer. */ ! 604: if (count > 0) ! 605: { ! 606: if (count > to_do) ! 607: count = to_do; ! 608: if (count > 20) { ! 609: memcpy(f->_IO_write_ptr, s, count); ! 610: s += count; ! 611: } ! 612: else ! 613: { ! 614: register char *p = f->_IO_write_ptr; ! 615: register int i = (int)count; ! 616: while (--i >= 0) *p++ = *s++; ! 617: } ! 618: f->_IO_write_ptr += count; ! 619: to_do -= count; ! 620: } ! 621: if (to_do + must_flush > 0) ! 622: { _IO_size_t block_size, dont_write; ! 623: /* Next flush the (full) buffer. */ ! 624: if (__overflow(f, EOF) == EOF) ! 625: return n - to_do; ! 626: ! 627: /* Try to maintain alignment: write a whole number of blocks. ! 628: dont_write is what gets left over. */ ! 629: block_size = f->_IO_buf_end - f->_IO_buf_base; ! 630: dont_write = block_size >= 128 ? to_do % block_size : 0; ! 631: ! 632: count = to_do - dont_write; ! 633: if (_IO_do_write(f, s, count) == EOF) ! 634: return n - to_do; ! 635: to_do = dont_write; ! 636: ! 637: /* Now write out the remainder. Normally, this will fit in the ! 638: buffer, but it's somewhat messier for line-buffered files, ! 639: so we let _IO_xsputn handle the general case. */ ! 640: if (dont_write) ! 641: to_do -= _IO_default_xsputn(f, s+count, dont_write); ! 642: } ! 643: return n - to_do; ! 644: } ! 645: ! 646: struct _IO_jump_t _IO_file_jumps = { ! 647: _IO_file_overflow, ! 648: _IO_file_underflow, ! 649: _IO_file_xsputn, ! 650: _IO_default_xsgetn, ! 651: _IO_file_read, ! 652: _IO_file_write, ! 653: _IO_file_doallocate, ! 654: _IO_default_pbackfail, ! 655: _IO_file_setbuf, ! 656: _IO_file_sync, ! 657: _IO_file_finish, ! 658: _IO_file_close, ! 659: _IO_file_stat, ! 660: _IO_file_seek, ! 661: _IO_file_seekoff, ! 662: _IO_default_seekpos, ! 663: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.