int attribute_compat_text_section _IO_old_file_sync (_IO_FILE *fp) { _IO_ssize_t delta; int retval = 0; /* char* ptr = cur_ptr(); */ if (fp->_IO_write_ptr > fp->_IO_write_base) if (_IO_old_do_flush(fp)) return EOF; delta = fp->_IO_read_ptr - fp->_IO_read_end; if (delta != 0) { #ifdef TODO if (_IO_in_backup (fp)) delta -= eGptr () - Gbase (); #endif _IO_off_t new_pos = _IO_SYSSEEK (fp, delta, 1); if (new_pos != (_IO_off_t) EOF) fp->_IO_read_end = fp->_IO_read_ptr; #ifdef ESPIPE else if (errno == ESPIPE) ; /* Ignore error from unseekable devices. */ #endif else retval = EOF; } if (retval != EOF) fp->_old_offset = _IO_pos_BAD; /* FIXME: Cleanup - can this be shared? */ /* setg(base(), ptr, ptr); */ return retval; }
void _IO_unsave_markers (_IO_FILE *fp) { struct _IO_marker *mark = fp->_markers; if (mark) { #ifdef TODO streampos offset = seekoff (0, ios::cur, ios::in); if (offset != EOF) { offset += eGptr () - Gbase (); for ( ; mark != NULL; mark = mark->_next) mark->set_streampos (mark->_pos + offset); } else { for ( ; mark != NULL; mark = mark->_next) mark->set_streampos (EOF); } #endif fp->_markers = 0; } if (_IO_have_backup (fp)) _IO_free_backup_area (fp); }
int filebuf::sync() { // char* ptr = cur_ptr(); if (pptr() > pbase()) if (do_flush()) return EOF; if (gptr() != egptr()) { streampos delta = gptr() - egptr(); if (in_backup()) delta -= eGptr() - Gbase(); if (sys_seek(delta, ios::cur) == EOF) return EOF; } // FIXME: Cleanup - can this be shared? // setg(base(), ptr, ptr); return 0; }
static int _IO_file_sync_mmap (_IO_FILE *fp) { if (fp->_IO_read_ptr != fp->_IO_read_end) { #ifdef TODO if (_IO_in_backup (fp)) delta -= eGptr () - Gbase (); #endif if (__lseek64 (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base, SEEK_SET) != fp->_IO_read_ptr - fp->_IO_buf_base) { fp->_flags |= _IO_ERR_SEEN; return EOF; } } fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base; fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base; return 0; }
streampos filebuf::seekoff(streamoff offset, _seek_dir dir, int mode) { streampos result, new_offset, delta; _G_ssize_t count; if (mode == 0) // Don't move any pointers. dir = ios::cur, offset = 0; // Flush unwritten characters. // (This may do an unneeded write if we seek within the buffer. // But to be able to switch to reading, we would need to set // egptr to ptr. That can't be done in the current design, // which assumes file_ptr() is eGptr. Anyway, since we probably // end up flushing when we close(), it doesn't make much difference.) if (pptr() > pbase() || put_mode()) if (switch_to_get_mode()) return EOF; if (base() == NULL) { doallocbuf(); setp(base(), base()); setg(base(), base(), base()); } switch (dir) { case ios::cur: if (_fb._offset < 0) { _fb._offset = sys_seek(0, ios::cur); if (_fb._offset < 0) return EOF; } // Make offset absolute, assuming current pointer is file_ptr(). offset += _fb._offset; offset -= _egptr - _gptr; if (in_backup()) offset -= _other_egptr - _other_gbase; dir = ios::beg; break; case ios::beg: break; case ios::end: struct stat st; if (sys_stat(&st) == 0 && S_ISREG(st.st_mode)) { offset += st.st_size; dir = ios::beg; } else goto dumb; } // At this point, dir==ios::beg. // If destination is within current buffer, optimize: if (_fb._offset >= 0 && _eback != NULL) { // Offset relative to start of main get area. fpos_t rel_offset = offset - _fb._offset + (eGptr()-Gbase()); if (rel_offset >= 0) { if (in_backup()) switch_to_main_get_area(); if (rel_offset <= _egptr - _eback) { setg(base(), base() + rel_offset, egptr()); setp(base(), base()); return offset; } // If we have streammarkers, seek forward by reading ahead. if (have_markers()) { int to_skip = rel_offset - (_gptr - _eback); if (ignore(to_skip) != to_skip) goto dumb; return offset; } } if (rel_offset < 0 && rel_offset >= Bbase() - Bptr()) { if (!in_backup()) switch_to_backup_area(); gbump(_egptr + rel_offset - gptr()); return offset; } } unsave_markers(); // Try to seek to a block boundary, to improve kernel page management. new_offset = offset & ~(ebuf() - base() - 1); delta = offset - new_offset; if (delta > ebuf() - base()) { new_offset = offset; delta = 0; } result = sys_seek(new_offset, ios::beg); if (result < 0) return EOF; if (delta == 0) count = 0; else { count = sys_read(base(), ebuf()-base()); if (count < delta) { // We weren't allowed to read, but try to seek the remainder. offset = count == EOF ? delta : delta-count; dir = ios::cur; goto dumb; } } setg(base(), base()+delta, base()+count); setp(base(), base()); _fb._offset = result + count; xflags(xflags() & ~ _S_EOF_SEEN); return offset; dumb: unsave_markers(); result = sys_seek(offset, dir); if (result != EOF) { xflags(xflags() & ~_S_EOF_SEEN); } _fb._offset = result; setg(base(), base(), base()); setp(base(), base()); return result; }
streammarker::~streammarker() { if (saving()) { // Unlink from sb's chain. register streammarker **ptr = &((backupbuf*)_sbuf)->_markers; for (; ; ptr = &(*ptr)->_next) if (*ptr == NULL) break; else if (*ptr == this) { *ptr = _next; return; } } #if 0 if _sbuf has a backup area that is no longer needed, should we delete it now, or wait until underflow()? #endif } #define BAD_DELTA EOF int streammarker::delta(streammarker& other_mark) { if (_sbuf != other_mark._sbuf) return BAD_DELTA; if (saving() && other_mark.saving()) return _pos - other_mark._pos; else if (!saving() && !other_mark.saving()) return _spos - other_mark._spos; else return BAD_DELTA; } int streammarker::delta() { if (_sbuf == NULL) return BAD_DELTA; if (saving()) { int cur_pos; if (_sbuf->in_backup()) cur_pos = _sbuf->_gptr - _sbuf->_egptr; else cur_pos = _sbuf->_gptr - _sbuf->_eback; return _pos - cur_pos; } else { if (_spos == EOF) return BAD_DELTA; int cur_pos = _sbuf->seekoff(0, ios::cur); if (cur_pos == EOF) return BAD_DELTA; return _pos - cur_pos; } } int streambuf::seekmark(streammarker& mark, int delta /* = 0 */) { if (mark._sbuf != this) return EOF; if (!mark.saving()) { return seekpos(mark._spos, ios::in); } else if (mark._pos >= 0) { if (in_backup()) switch_to_main_get_area(); _gptr = _eback + mark._pos; } else { if (!in_backup()) switch_to_backup_area(); _gptr = _egptr + mark._pos; } return 0; } void streambuf::unsave_markers() { register streammarker *mark =_markers; if (_markers) { streampos offset = seekoff(0, ios::cur, ios::in); if (offset != EOF) { offset += eGptr() - Gbase(); for ( ; mark != NULL; mark = mark->_next) mark->set_streampos(mark->_pos + offset); } else { for ( ; mark != NULL; mark = mark->_next) mark->set_streampos(EOF); } _markers = 0; } free_backup_area(); } int backupbuf::pbackfail(int c) { if (_gptr <= _eback) { // Need to handle a filebuf in write mode (switch to read mode). FIXME! if (have_backup() && !in_backup()) { switch_to_backup_area(); } if (!have_backup()) { // No backup buffer: allocate one. // Use short buffer, if unused? (probably not) FIXME int backup_size = 128; _other_gbase = new char [backup_size]; _other_egptr = _other_gbase + backup_size; _aux_limit = _other_egptr; switch_to_backup_area(); } else if (gptr() <= eback()) { // Increase size of existing backup buffer. size_t new_size; size_t old_size = egptr() - eback(); new_size = 2 * old_size; char* new_buf = new char [new_size]; memcpy(new_buf+(new_size-old_size), eback(), old_size); delete [] eback(); setg(new_buf, new_buf+(new_size-old_size), new_buf+new_size); _aux_limit = _gptr; } } _gptr--; if (c != EOF && *_gptr != c) *_gptr = c; return (unsigned char)*_gptr; } unsigned __adjust_column(unsigned start, const char *line, int count) { register const char *ptr = line + count; while (ptr > line) if (*--ptr == '\n') return line + count - ptr - 1; return start + count; } int ios::readable() { return !(rdbuf()->_flags & _S_NO_READS); } int ios::writable() { return !(rdbuf()->_flags & _S_NO_WRITES); } int ios::is_open() { return rdbuf() && (rdbuf()->_flags & _S_NO_READS+_S_NO_WRITES) != _S_NO_READS+_S_NO_WRITES; } #if defined(linux) #define IO_CLEANUP ; #endif #ifdef IO_CLEANUP IO_CLEANUP #else struct __io_defs { __io_defs() { } ~__io_defs() { streambuf::flush_all(); } }; __io_defs io_defs__;