_CODE_ACCESS int fflush(register FILE *_fp) { int result = 0; /*------------------------------------------------------------------------*/ /* The current thread in a multi-threaded application must protect access */ /* to __TI_LOCK_FILE_TBL shared resources (_ftable[], __TI_ft_end, init */ /* and __TI_cleanup_ptr. init is a static local in __TI_search_fp() in */ /* fopen.c). In this case, __TI_doflush will update the specified file */ /* streams, so we must also protect access to the streams. */ /* The below loop will cache a local copy of _ftable[] and __TI_ft_end. */ /* Ensure that the local copy of _ftable[] and each flushed file stream */ /* is flushed to shared memory and the local copy of __TI_ft_end is */ /* invalidated before leaving the critical section. */ /*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/ /* If _fp is not a NULL pointer, call __TI_doflush for that stream. */ /* Otherwise, call __TI_doflush for all file streams in the table that are*/ /* active. */ /*------------------------------------------------------------------------*/ if (_fp) { __TI_file_lock(_fp); result = __TI_doflush(_fp); __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); } else { int index; __TI_resource_lock(__TI_LOCK_FILE_TBL); for(index = 0; index < __TI_ft_end; index++) if(_ftable[index].fd != -1) { __TI_file_lock(&_ftable[index]); result |= __TI_doflush(&_ftable[index]); __TI_data_synch_WBINV(&_ftable[index], sizeof(_ftable[index])); __TI_file_unlock(&_ftable[index]); } __TI_data_synch_WBINV(&_ftable, sizeof(_ftable)); __TI_data_synch_INV(&__TI_ft_end, sizeof(__TI_ft_end)); __TI_resource_unlock(__TI_LOCK_FILE_TBL); } return (result); }
_CODE_ACCESS void __TI_buff_read(FILE *_fp) { /*------------------------------------------------------------------------*/ /* Local variables */ /*------------------------------------------------------------------------*/ int errchk, j, buffer_size = _fp->bufend - _fp->buf; /*------------------------------------------------------------------------*/ /* If this is a line buffered stream, flush all line buffered streams. */ /* The current thread in a multi-threaded application must protect access */ /* to __TI_LOCK_FILE_TBL shared resources (_ftable[] and __TI_ft_end) and */ /* each file stream that is flushed. Ensure that the local copy of */ /* _ftable[] is flushed to shared memory and the local copy of */ /* __TI_ft_end is invalidated before leaving the critical section. */ /*------------------------------------------------------------------------*/ if (_BUFFMODE(_fp) == _IOLBF) { __TI_resource_lock(__TI_LOCK_FILE_TBL); for (j=0; j < __TI_ft_end; j++) if (_BUFFMODE(&_ftable[j]) == _IOLBF) { __TI_file_lock(&_ftable[j]); __TI_doflush(&_ftable[j]); __TI_data_synch_WBINV(&_ftable[j], sizeof(FILE)); __TI_file_unlock(&_ftable[j]); } __TI_data_synch_WBINV(&_ftable, sizeof(_ftable)); __TI_data_synch_INV(&__TI_ft_end, sizeof(__TI_ft_end)); __TI_resource_unlock(__TI_LOCK_FILE_TBL); } /*------------------------------------------------------------------------*/ /* Read in the next characters from the file. */ /*------------------------------------------------------------------------*/ errchk = read(_fp->fd, (char *)_fp->buf, buffer_size); /*------------------------------------------------------------------------*/ /* Adjust the buffer pointers. */ /*------------------------------------------------------------------------*/ _fp->buff_stop = _fp->buf + errchk; _fp->pos = _fp->buf; /*------------------------------------------------------------------------*/ /* Set any error flags if necessary. */ /*------------------------------------------------------------------------*/ switch (errchk) { case -1 : _SET(_fp, _STATERR); break; case 0 : _SET(_fp, _STATEOF); break; } return; }
_CODE_ACCESS int fseek(register FILE *_fp, long _offset, int _ptrname) { /*------------------------------------------------------------------------*/ /* The current thread in a multi-threaded application must protect access */ /* to the file stream. In this case, _fp may be updated, so we must */ /* ensure that the local copy of _fp is flushed to shared memory before */ /* leaving the critical section (invalidated if it is not modified). */ /*------------------------------------------------------------------------*/ __TI_file_lock(_fp); /*------------------------------------------------------------------------*/ /* If the current stream is not associated with a file, return an error. */ /*------------------------------------------------------------------------*/ if (_fp->fd == -1) { __TI_data_synch_INV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } /*------------------------------------------------------------------------*/ /* When positioning to a location relative to the current location, */ /* adjust for the fact that there may be something in the buffer. */ /*------------------------------------------------------------------------*/ if(_ptrname == SEEK_CUR && _STCHK(_fp, _MODER) && _fp->pos) _offset -= (_fp->buff_stop - _fp->pos); __TI_doflush(_fp); _UNSET(_fp, (_STATEOF | _UNGETC)); if ((lseek(_fp->fd, _offset, _ptrname)) == -1) { __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (0); }
_CODE_ACCESS int fputs(const char *_ptr, register FILE *_fp) { /*------------------------------------------------------------------------*/ /* Local variables */ /*------------------------------------------------------------------------*/ size_t num_left, ptr_strlen; char *fpos = (char *)_ptr; int room_left, flush_flag = 0, num_to_write; /*------------------------------------------------------------------------*/ /* The current thread in a multi-threaded application must protect access */ /* to the file stream. In this case, _fp may be updated, so we must */ /* ensure that the local copy of _fp is flushed to shared memory before */ /* leaving the critical section (invalidated if it is not modified). */ /*------------------------------------------------------------------------*/ __TI_file_lock(_fp); /*------------------------------------------------------------------------*/ /* Make sure that the stream is writeable. */ /*------------------------------------------------------------------------*/ if (!__TI_wrt_ok(_fp)) { __TI_data_synch_INV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } room_left = (int)(_fp->bufend - _fp->pos); ptr_strlen = num_left = strlen(_ptr); /*------------------------------------------------------------------------*/ /* If the stream is non-buffered, call the lowlevel WRITE function. */ /*------------------------------------------------------------------------*/ if (_BUFFMODE(_fp) == _IONBF) { int num_written = 0; while (num_left > 0) { int write_return = write(_fp->fd, _ptr + num_written, num_left); if (write_return < 0) { _SET(_fp, _STATERR); __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } else { num_written += write_return; num_left -= write_return; } } __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return ptr_strlen; } /*------------------------------------------------------------------------*/ /* Write the string into the buffer, flushing it when full. */ /*------------------------------------------------------------------------*/ while (num_left > 0) { num_to_write = (num_left > room_left) ? room_left : num_left; if ((_BUFFMODE(_fp) == _IOLBF) && memchr(fpos, '\n', num_to_write)) { num_to_write = (char *)memchr(fpos, '\n', num_to_write) - fpos + 1; flush_flag = 1; } memcpy(_fp->pos, fpos, num_to_write); /*---------------------------------------------------------------------*/ /* Update pointers and counters. */ /*---------------------------------------------------------------------*/ _fp->pos += num_to_write; fpos += num_to_write; num_left -= num_to_write; room_left -= num_to_write; /*---------------------------------------------------------------------*/ /* If the buffer is full, flush it. Any I/O errors cause this */ /* function to exit, returning an EOF. */ /*---------------------------------------------------------------------*/ if (room_left == 0 || flush_flag) { if (__TI_doflush(_fp)) { _SET(_fp, _STATERR); __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } room_left = (int)(_fp->bufend - _fp->pos); _SET(_fp, _MODEW); flush_flag = 0; } } __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return ptr_strlen; }
_CODE_ACCESS int fputc(int _c, register FILE *_fp) { /*------------------------------------------------------------------------*/ /* The current thread in a multi-threaded application must protect access */ /* to the file stream. In this case, _fp may be updated, so we must */ /* ensure that the local copy of _fp is flushed to shared memory before */ /* leaving the critical section (invalidated if it is not modified). */ /*------------------------------------------------------------------------*/ __TI_file_lock(_fp); /*------------------------------------------------------------------------*/ /* Make sure that the stream is writeable. */ /*------------------------------------------------------------------------*/ if (!__TI_wrt_ok(_fp)) { __TI_data_synch_INV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return EOF; } /*------------------------------------------------------------------------*/ /* If the stream is non-buffered, call the lowlevel WRITE function. */ /*------------------------------------------------------------------------*/ if(_BUFFMODE(_fp) == _IONBF) { char cbuf = (char)_c; if ((write(_fp->fd, &cbuf, 1)) == -1) { _SET(_fp, _STATERR); __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } else { __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return ((unsigned char)_c); } } /*------------------------------------------------------------------------*/ /* Check for room in the buffer. If room, add the character. Must */ /* check before writing because C++ library fills the buffer to */ /* capacity, then calls fputc() from overflow() (CQXXXXX). */ /*------------------------------------------------------------------------*/ if ((_fp->pos >= _fp->bufend) && __TI_doflush(_fp)) { _SET(_fp, _STATERR); __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } *(_fp->pos++) = (unsigned char)_c; /*------------------------------------------------------------------------*/ /* If a line-buffered stream reached a newline character, flush it. */ /*------------------------------------------------------------------------*/ if ((_STCHK(_fp, _IOLBF) && _c == '\n') && __TI_doflush(_fp)) { _SET(_fp, _STATERR); __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (EOF); } __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return ((unsigned char)_c); }
_CODE_ACCESS size_t fwrite(const void *_ptr, size_t _size, size_t _count, register FILE *_fp) { /*------------------------------------------------------------------------*/ /* Local variables */ /*------------------------------------------------------------------------*/ unsigned char *fpos = (unsigned char *)_ptr; unsigned char *nl_pos; size_t buffer_size, next_nl, room_left; size_t num_left = _size * _count, num_to_write, num_written = 0; /*------------------------------------------------------------------------*/ /* The current thread in a multi-threaded application must protect access */ /* to the file stream. In this case, _fp may be updated, so we must */ /* ensure that the local copy of _fp is flushed to shared memory before */ /* leaving the critical section (invalidated if it is not modified). */ /*------------------------------------------------------------------------*/ __TI_file_lock(_fp); /*------------------------------------------------------------------------*/ /* Make sure that the stream is writeable. */ /*------------------------------------------------------------------------*/ buffer_size = (_fp->bufend - _fp->buf); if (!__TI_wrt_ok(_fp) || _size == 0 || _count == 0) { __TI_data_synch_INV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (0); } /*------------------------------------------------------------------------*/ /* If the stream is non-buffered, call the lowlevel WRITE function. */ /*------------------------------------------------------------------------*/ if(_BUFFMODE(_fp) == _IONBF) { int num_written = 0; while (num_left > 0) { int write_return = write(_fp->fd, (char *)fpos + num_written, num_left); if (write_return <= 0) { _SET(_fp, _STATERR); break; } else { num_written += write_return; num_left -= write_return; } } __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (num_written / _size); } room_left = (_fp->bufend - _fp->pos); if (_STCHK(_fp, _IOLBF)) next_nl = (char *)memchr(fpos, '\n', num_left) - (char *)fpos + 1; while (num_left > 0) { /*---------------------------------------------------------------------*/ /* Determine how many characters should be written based on buffering */ /* mode. For non-buffered streams, call the lowlevel WRITE function. */ /* For fully buffered streams, put as many characters in the buffer as */ /* possible. For line buffered streams, put characters into the */ /* util the buffer is full, the last character is reached, or a */ /* newline character is reached. */ /*---------------------------------------------------------------------*/ switch (_BUFFMODE(_fp)) { case _IOFBF : num_to_write = (room_left > num_left) ? num_left : room_left; break; case _IOLBF : num_to_write = (room_left > next_nl) ? next_nl : (room_left > num_left) ? num_left : room_left; break; /*------------------------------------------------------------------*/ /* The only other available _BUFFMODE for _fp is _IONBF which has */ /* already been accounted for above. We should never get here. */ /*------------------------------------------------------------------*/ default : return (0); } /*---------------------------------------------------------------------*/ /* Write the data to the buffer, and update the buffer pointer and the */ /* ROOM_LEFT coutner. */ /*---------------------------------------------------------------------*/ memcpy(_fp->pos, fpos, num_to_write); _fp->pos += num_to_write; room_left = (_fp->bufend - _fp->pos); /*---------------------------------------------------------------------*/ /* If the buffer is full, or a newline character has been encountered */ /* on a line-buffered stream, flush it. */ /*---------------------------------------------------------------------*/ if (room_left == 0 || (_STCHK(_fp, _IOLBF) && num_to_write == next_nl)) { if (__TI_doflush(_fp)) { _SET(_fp, _STATERR); __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (num_written / _size); } room_left = buffer_size; /*------------------------------------------------------------------*/ /* The _DOFLUSH function clears the write flag on streams opened in */ /* update mode. Make sure that the write flag is still set here. */ /*------------------------------------------------------------------*/ _SET(_fp, _MODEW); } /*---------------------------------------------------------------------*/ /* Update pointers and counters. */ /*---------------------------------------------------------------------*/ num_written += num_to_write; fpos += num_to_write; num_left -= num_to_write; /*---------------------------------------------------------------------*/ /* For line-buffered streams, find the next occurance of a newline */ /* character. If there are no more, and the remaining data will fit */ /* in the buffer, exit the loop where the remaining data will be moved */ /* there. Otherwise loop until this condition is true. */ /*---------------------------------------------------------------------*/ if (_STCHK(_fp, _IOLBF)) { nl_pos = (unsigned char *)memchr((fpos + 1), '\n', (num_left > 0) ? (num_left-1) : 0); if (! nl_pos) { if (num_left < room_left) break; else next_nl = buffer_size + 1; } else next_nl = (nl_pos - fpos) + 1; } } /*------------------------------------------------------------------------*/ /* Copy the rest of the characters into the buffer for line-buffered */ /* streams. */ /*------------------------------------------------------------------------*/ if (_STCHK(_fp, _IOLBF)) { memcpy(_fp->pos, fpos, num_left); num_written += num_left; _fp->pos += num_left; } __TI_data_synch_WBINV(_fp, sizeof(FILE)); __TI_file_unlock(_fp); return (num_written / _size); }