/*-------------------------------------------
| Name:fputc
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int __fputc(int ch, FILE *fp){
   register int v;

   __thr_safe_lock(fp);

   Inline_init;

   v = fp->mode;
   /* If last op was a read ... */
   if ((v & __MODE_READING) && __fflush(fp)) {
      __thr_safe_unlock(fp);
      return EOF;
   }

   /* Can't write or there's been an EOF or error then return EOF */
   if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) {
      __thr_safe_unlock(fp);
      return EOF;
   }

   /* In MSDOS translation mode */
#if __MODE_IOTRAN
   if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF) {
      __thr_safe_unlock(fp);
      return EOF;
   }
#endif

   /* Buffer is full */
   if (fp->bufpos >= fp->bufend && __fflush(fp)) {
      __thr_safe_unlock(fp);
      return EOF;
   }

   /* Right! Do it! */
   *(fp->bufpos++) = ch;
   fp->mode |= __MODE_WRITING;

   /* Unbuffered or Line buffered and end of line */
   if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF))
       && __fflush(fp)) {
      __thr_safe_unlock(fp);
      return EOF;
   }

   /* Can the macro handle this by itself ? */
   if (v & (__MODE_IOTRAN | _IOLBF | _IONBF))
      fp->bufwrite = fp->bufstart;      /* Nope */
   else
      fp->bufwrite = fp->bufend;        /* Yup */

   __thr_safe_unlock(fp);

   /* Correct return val */
   return (unsigned char) ch;
}
/*-------------------------------------------
| Name:__stdio_close_all
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
void __stdio_close_all(pid_t pid){
   FILE *fp;
   __fflush(stdout);
   __fflush(stderr);
   for (fp = __IO_list; fp; fp = fp->next)
   {
      __fflush(fp);
      close(fp->fd);
      /* Note we're not de-allocating the memory */
      /* There doesn't seem to be much point :-) */
      fp->fd = -1;
   }
}
Example #3
0
int __srget(FILE *stream) /* Get next input block */
{
  if(stream->flags&(__SERR|__SEOF)) /* Error on stream / EOF */
  {
    stream->incount=0;
    errno=EPERM;
    return EOF;
  }
  if(stream->flags&__SWR)
  {
    if(__fflush(stream))
      return EOF;
  }else if(stream->tmpp!=NULL) /* File is in ungetc mode */
  {
    stream->p=stream->tmpp;
    stream->incount=stream->tmpinc;
    stream->tmpp=NULL;
    if(--stream->incount>=0)
      return *stream->p++;
  }
  if(stream->flags&__SSTR) /* it's a sscanf buffer */
    return EOF;
  if(stream->flags&(__SNBF|__SLBF)) /* Before reading from line- or unbuffered input file */
  {                   /* fflush all line buffered output files (ANSI) */
    struct filenode *fp=(struct filenode *)__filelist.mlh_Head;
    while(fp->node.mln_Succ)
    {
      if((fp->FILE.flags&(__SWR|__SLBF))==(__SWR|__SLBF))
        __fflush(&fp->FILE); /* Don't return EOF if this fails */
      fp=(struct filenode *)fp->node.mln_Succ;
    }
  }
  stream->flags|=__SRD;
  stream->incount=read(stream->file,stream->buffer,stream->bufsize);
  if(!stream->incount) /* EOF found */
  {
    stream->flags|=__SEOF;
    return EOF;
  }else if(stream->incount<0) /* Error */
  {
    stream->incount=0;
    stream->flags|=__SERR;
    return EOF;
  }
  stream->incount--;
  stream->p=stream->buffer;
  return *stream->p++;
}
Example #4
0
/*
 * Helper function for `fprintf to unbuffered unix file': creates a
 * temporary buffer.  We only work on write-only files; this avoids
 * worries about ungetc buffers and so forth.
 */
static int
__sbprintf(FILE *fp, const char *fmt, va_list ap)
{
	int ret;
	FILE fake = FAKE_FILE;
	unsigned char buf[BUFSIZ];

	/* XXX This is probably not needed. */
	if (prepwrite(fp) != 0)
		return (EOF);

	/* copy the important variables */
	fake._flags = fp->_flags & ~__SNBF;
	fake._file = fp->_file;
	fake._cookie = fp->_cookie;
	fake._write = fp->_write;
	fake._orientation = fp->_orientation;
	fake._mbstate = fp->_mbstate;

	/* set up the buffer */
	fake._bf._base = fake._p = buf;
	fake._bf._size = fake._w = sizeof(buf);
	fake._lbfsize = 0;	/* not actually used, but Just In Case */

	/* do the work, then copy any error status */
	ret = __vfprintf(&fake, fmt, ap);
	if (ret >= 0 && __fflush(&fake))
		ret = EOF;
	if (fake._flags & __SERR)
		fp->_flags |= __SERR;
	return (ret);
}
Example #5
0
int __swbuf(int c,FILE *stream) /* Get next output block */
{ int out,lbs;

  if(stream->flags&(__SSTR|__SERR)) /* sprintf buffer | error on stream */
  { stream->outcount=0;
    errno=EPERM;
    return EOF;
  }else if(stream->flags&__SRD)
  {
    stream->incount=0; /* throw away input buffer */
    stream->tmpp=NULL;
    stream->flags&=~__SRD;
  }
  lbs=stream->flags&__SLBF?-stream->bufsize:0;
  out=(stream->flags&__SNBF?0:stream->bufsize-1)+lbs;
  if(!(stream->flags&__SWR)) /* File wasn't in write mode */
  { stream->p=stream->buffer; /* set buffer */
    stream->outcount=--out;   /* and buffercount */
    stream->flags|=__SWR; }   /* and write mode */
  *stream->p++=c; /* put this character */
  if(stream->outcount<0&&(stream->outcount<lbs||(char)c=='\n'))
  { if(__fflush(stream)) /* Buffer full */
      return EOF;
    stream->p=stream->buffer; /* Set new buffer */
  }
  stream->linebufsize=lbs;
  stream->outcount=out;
  stream->flags|=__SWR;
  return c;
}
/*-------------------------------------------
| Name:setvbuf
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int __setvbuf(FILE * fp,char * buf,int mode,size_t size){
   __thr_safe_lock(fp);
   __fflush(fp);
   if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart);
   fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
   fp->bufstart = fp->unbuf;
   fp->bufend = fp->unbuf + sizeof(fp->unbuf);
   fp->mode |= _IONBF;

   if( mode == _IOFBF || mode == _IOLBF )
   {
      if( size <= 0  ) size = BUFSIZ;
      if( buf == 0 ) buf = malloc(size);
      if( buf == 0 ) {
         __thr_safe_unlock(fp);
         return EOF;
      }

      fp->bufstart = buf;
      fp->bufend = buf+size;
      fp->mode |= mode;
   }
   fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;

   __thr_safe_unlock(fp);
   return 0;
}
Example #7
0
/*
 * Write the given character into the (probably full) buffer for
 * the given file.  Flush the buffer out if it is or becomes full,
 * or if c=='\n' and the file is line buffered.
 *
 * Non-MT-safe
 */
int
__swbuf(int c, FILE *fp)
{
	int n;

	/*
	 * In case we cannot write, or longjmp takes us out early,
	 * make sure _w is 0 (if fully- or un-buffered) or -_bf._size
	 * (if line buffered) so that we will get called again.
	 * If we did not do this, a sufficient number of putc()
	 * calls might wrap _w from negative to positive.
	 */
	fp->_w = fp->_lbfsize;
	if (prepwrite(fp) != 0)
		return (EOF);
	c = (unsigned char)c;

	ORIENT(fp, -1);

	/*
	 * If it is completely full, flush it out.  Then, in any case,
	 * stuff c into the buffer.  If this causes the buffer to fill
	 * completely, or if c is '\n' and the file is line buffered,
	 * flush it (perhaps a second time).  The second flush will always
	 * happen on unbuffered streams, where _bf._size==1; fflush()
	 * guarantees that putc() will always call wbuf() by setting _w
	 * to 0, so we need not do anything else.
	 */
	n = fp->_p - fp->_bf._base;
	if (n >= fp->_bf._size) {
		if (__fflush(fp))
			return (EOF);
		n = 0;
	}
	fp->_w--;
	*fp->_p++ = c;
	if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n'))
		if (__fflush(fp))
			return (EOF);
	return (c);
}
/*-------------------------------------------
| Name:fread
| Description:
| Parameters:
| Return Type:
| Comments:fread will often be used to read in
|          large chunks of data calling read()
|          directly can be a big win in this case.
|          Beware also fgetc calls this function to fill the buffer.
|          This ignores __MODE__IOTRAN;
|          probably exactly what you want. (It _is_ whatfgetc wants)
| See:
---------------------------------------------*/
int __fread(char *buf,int size,int nelm,FILE *fp){
   int len, v;
   unsigned bytes, got = 0;

   __thr_safe_lock(fp);

   Inline_init;

   v = fp->mode;

   /* Want to do this to bring the file pointer up to date */
   if (v & __MODE_WRITING)
      __fflush(fp);

   /* Can't read or there's been an EOF or error then return zero */
   if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) {
      __thr_safe_unlock(fp);
      return 0;
   }

   /* This could be long, doesn't seem much point tho */
   bytes = size * nelm;

   len = fp->bufread - fp->bufpos;
   if ( (unsigned)len >= bytes)         /* Enough buffered */
   {
      memcpy(buf, fp->bufpos, (unsigned) bytes);
      fp->bufpos += bytes;
      __thr_safe_unlock(fp);
      return bytes;
   }
   else if (len > 0)            /* Some buffered */
   {
      memcpy(buf, fp->bufpos, len);
      fp->bufpos += len;
      got = len;
   }

   /* Need more; do it with a direct read */
   len = read(fp->fd, buf + got, (unsigned) (bytes - got));

   /* Possibly for now _or_ later */
   if (len < 0)
   {
      fp->mode |= __MODE_ERR;
      len = 0;
   }
   else if (len == 0)
      fp->mode |= __MODE_EOF;

   __thr_safe_unlock(fp);
   return (got + len) / size;
}
Example #9
0
/*@
	requires file == \null || file == &(stdio_pvt(file)->pub);
	requires valid_IO_file_pvt(stdio_pvt(file));
	assigns stdio_pvt(file)->ibytes, stdio_pvt(file)->pub._IO_eof, stdio_pvt(file)->pub._IO_error, stdio_pvt(file)->obytes, errno;
@*/
int fflush(FILE *file)
{
	struct _IO_file_pvt *f;

	if (__likely(file)) {
		f = stdio_pvt(file);
		return __fflush(f);
	} else {
		int err = 0;

		/*@
			loop invariant valid_IO_file_pvt(f);
			loop invariant f != &__stdio_headnode;
			loop assigns f, err;
		*/
		for (f = __stdio_headnode.next;
		     f != &__stdio_headnode;
		     f = f->next) {
			if (f->obytes)
				err |= __fflush(f);
		}
		return err;
	}
}
Example #10
0
static size_t fwrite_noflush(const void *buf, size_t count,
			     struct _IO_file_pvt *f)
{
	size_t bytes = 0;
	size_t nb;
	const char *p = buf;
	ssize_t rv;

	while (count) {
		if (f->ibytes || f->obytes >= f->bufsiz ||
		    (f->obytes && count >= f->bufsiz))
			if (__fflush(f))
				break;

		if (count >= f->bufsiz) {
			/*
			 * The write is large, so bypass
			 * buffering entirely.
			 */
			rv = write(f->pub._IO_fileno, p, count);
			if (rv == -1) {
				if (errno == EINTR || errno == EAGAIN)
					continue;
				f->pub._IO_error = true;
				break;
			} else if (rv == 0) {
				/* EOF on output? */
				f->pub._IO_eof = true;
				break;
			}

			p += rv;
			bytes += rv;
			count -= rv;
		} else {
			nb = f->bufsiz - f->obytes;
			nb = (count < nb) ? count : nb;
			if (nb) {
				memcpy(f->buf+f->obytes, p, nb);
				p += nb;
				f->obytes += nb;
				count -= nb;
				bytes += nb;
			}
		}
	}
	return bytes;
}
/*-------------------------------------------
| Name:ftell
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
long __ftell(FILE * fp){
   int pos;

   __thr_safe_lock(fp);

   if (__fflush(fp) == EOF) {
      __thr_safe_unlock(fp);
      return EOF;
   }

   pos=lseek(fp->fd, 0L, SEEK_CUR);

   __thr_safe_unlock(fp);

   return pos;
}
Example #12
0
static int __vfprintf(FILE *stream,const char *format,va_list args)
{ unsigned char buf[((BUFSIZ/4)+3)&~3];
  FILE fp;
  int ret;

  fp.outcount    = 0;
  fp.flags       = stream->flags&~(__SWO|__SWR|__SNBF);
  fp.file        = stream->file;
  fp.buffer      = buf;
  fp.bufsize     = sizeof(buf);
  fp.linebufsize = 0;
  if(((ret=vfprintf(&fp,format,args))>=0) && __fflush(&fp))
    ret = -1;
  if(fp.flags&__SERR)
    stream->flags|=__SERR;
  return ret;
}
Example #13
0
int fseek(FILE *stream,long int offset,int whence)
{
  if(stream->flags&__SERR) /* Error on stream */
  { errno=EPERM;
    return EOF; }
  if(stream->flags&__SWR)
    if(__fflush(stream))
      return EOF;
  if(whence==SEEK_CUR)
    offset-=stream->incount+(stream->tmpp!=NULL?stream->tmpinc:0);
  stream->incount=0;
  stream->tmpp=NULL;
  stream->flags&=~(__SEOF|__SRD);
  if(lseek(stream->file,offset,whence)==EOF)
  { stream->flags|=__SERR;
    return EOF; }
  return 0;
}
/*-------------------------------------------
| Name:fclose
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int __fclose(FILE *fp){
   int rv = 0;
   //int errno;

   if (fp == 0)
   {
      errno = EINVAL;
      return EOF;
   }
   if (__fflush(fp))
      return EOF;

   if (close(fp->fd))
      rv = EOF;
   fp->fd = -1;

   if (fp->mode & __MODE_FREEBUF)
   {
      free(fp->bufstart);
      fp->mode &= ~__MODE_FREEBUF;
      fp->bufstart = fp->bufend = 0;
   }

   if (fp->mode & __MODE_FREEFIL)
   {
      FILE *prev = 0, *ptr;
      fp->mode = 0;

      for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next)
         ;
      if (ptr == fp)
      {
         if (prev == 0)
            __IO_list = fp->next;
         else
            prev->next = fp->next;
      }
      free(fp);
   }
   else
      fp->mode = 0;

   return rv;
}
/*-------------------------------------------
| Name:fseek
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int __fseek(FILE *fp,long offset,int ref)
{
   __thr_safe_lock(fp);
#if 1
   /* if __MODE_READING and no ungetc ever done can just move pointer */
   /* This needs testing! */

   if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING &&
        ( ref == SEEK_SET || ref == SEEK_CUR )) {

      long fpos = lseek(fp->fd, 0L, SEEK_CUR);
      if( fpos == -1 ) {
         __thr_safe_unlock(fp);
         return EOF;
      }

      if( ref == SEEK_CUR ) {
         ref = SEEK_SET;
         offset = fpos + offset + fp->bufpos - fp->bufread;
      }
      if( ref == SEEK_SET ) {
         if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread ) {
            fp->bufpos = offset - fpos + fp->bufread;
            __thr_safe_unlock(fp);
            return 0;
         }
      }
   }
#endif
   /* Use fflush to sync the pointers */
   if (__fflush(fp) == EOF) {
      __thr_safe_unlock(fp);
      return EOF;
   }
   if (lseek(fp->fd, (off_t)offset, ref) < 0) {
      __thr_safe_unlock(fp);
      return EOF;
   }

   __thr_safe_unlock(fp);
   return 0;
}
Example #16
0
size_t _fwrite(const void *buf, size_t count, FILE *file)
{
	struct _IO_file_pvt *f = stdio_pvt(file);
	size_t bytes = 0;
	size_t pf_len, pu_len;
	const char *p = buf;
	const char *q;

	/* We divide the data into two chunks, flushed (pf)
	   and unflushed (pu) depending on buffering mode
	   and contents. */

	switch (f->bufmode) {
	case _IOFBF:
		pf_len = 0;
		break;

	case _IOLBF:
		q = memrchr(p, '\n', count);
		pf_len = q ? q - p + 1 : 0;
		break;

	case _IONBF:
	default:
		pf_len = count;
		break;
	}

	if (pf_len) {
		bytes = fwrite_noflush(p, pf_len, f);
		p += bytes;
		if (__fflush(f) || bytes != pf_len)
			return bytes;
	}

	pu_len = count - pf_len;
	if (pu_len)
		bytes += fwrite_noflush(p, pu_len, f);

	return bytes;
}
/*-------------------------------------------
| Name:fgetc
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int __fgetc(FILE *fp){
   int ch;

   __thr_safe_lock(fp);

   if (fp->mode & __MODE_WRITING)
      __fflush(fp);
#if __MODE_IOTRAN
try_again:
#endif
   /* Can't read or there's been an EOF or error then return EOF */
   if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) {
      __thr_safe_unlock(fp);
      return EOF;
   }

   /* Nothing in the buffer - fill it up */
   if (fp->bufpos >= fp->bufread)
   {
      fp->bufpos = fp->bufread = fp->bufstart;
      ch = __fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp);
      if (ch == 0) {
         __thr_safe_unlock(fp);
         return EOF;
      }

      fp->bufread += ch;
      fp->mode |= __MODE_READING;
      fp->mode &= ~__MODE_UNGOT;
   }
   ch = *(fp->bufpos++);

#if __MODE_IOTRAN
   /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */
   if (ch == '\r' && (fp->mode & __MODE_IOTRAN))
      goto try_again;
#endif

   __thr_safe_unlock(fp);
   return ch;
}
/*-------------------------------------------
| Name:setbuffer
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
void __setbuffer(FILE * fp,char * buf,int size){
   __thr_safe_lock(fp);
   __fflush(fp);
   if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart);
   fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);

   if( buf == 0 )
   {
      fp->bufstart = fp->unbuf;
      fp->bufend = fp->unbuf + sizeof(fp->unbuf);
      fp->mode |= _IONBF;
   }
   else
   {
      fp->bufstart = buf;
      fp->bufend = buf+size;
      fp->mode |= _IOFBF;
   }
   fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
   __thr_safe_unlock(fp);
}
Example #19
0
/*@
	requires 0 <= count;
	requires \separated(((char*)buf)+(0..count-1), stdio_pvt(file)->next, stdio_pvt(file)->prev, stdio_pvt(file)->buf+(0..(stdio_pvt(file)->bufsiz+32-1)));
	requires file == &(stdio_pvt(file)->pub);
	requires valid_IO_file_pvt(stdio_pvt(file));
	requires \valid(((char*)buf)+(0..count-1));
@*/
size_t _fread(void *buf, size_t count, FILE *file)
{
	struct _IO_file_pvt *f = stdio_pvt(file);
	size_t bytes = 0;
	size_t nb;
	char *p = buf;
	char *rdptr;
	ssize_t rv;
	bool bypass;

	if (!count)
		return 0;

	if (f->obytes)		/* User error! */
		__fflush(f);

	/*@
		loop invariant \base_addr(p) == \base_addr(buf);
		loop invariant 0 <= bytes;
		loop invariant \base_addr(rdptr) == \base_addr(f->data);
		loop invariant f->data <= rdptr <= f->data + f->bufsiz + 32; 
		loop invariant (char*)buf <= p <= (char*)buf + \at(count, Pre);
		loop invariant 0 <= count;
		loop assigns rv, bypass, rdptr, nb, f->pub._IO_error, f->pub._IO_eof, p, bytes, count, f->ibytes, f->data;
		loop variant count;
	@*/
	while (count) {
		while (f->ibytes == 0) {
			/*
			 * The buffer is empty, we have to read
			 */
			bypass = (count >= f->bufsiz);
			if (bypass) {
				/* Large read, bypass buffer */
				rdptr = p;
				nb = count;
			} else {
				rdptr = f->buf + _IO_UNGET_SLOP;
				nb = f->bufsiz;
			}

			rv = read(f->pub._IO_fileno, rdptr, nb);
			if (rv == -1) {
				if (errno == EINTR || errno == EAGAIN)
					continue;
				f->pub._IO_error = true;
				return bytes;
			} else if (rv == 0) {
				f->pub._IO_eof = true;
				return bytes;


			}

			if (bypass) {
				p += rv;
				bytes += rv;
				count -= rv;
			} else {
				f->ibytes = rv;
				f->data = rdptr;
			}

			if (!count)
				return bytes;
		}

		/* If we get here, the buffer is non-empty */
		nb = f->ibytes;
		nb = (count < nb) ? count : nb;
		if (nb) {
			memcpy(p, f->data, nb);
			p += nb;
			bytes += nb;
			count -= nb;
			f->data += nb;
			f->ibytes -= nb;
		}
	}
	return bytes;
}
/*-------------------------------------------
| Name:fwrite
| Description:
| Parameters:
| Return Type:
| Comments: Like fread, fwrite will often be used
|           to write out large chunks of data;
|           calling write() directly can be a big
|           win in this case.
|           But first we check to see if there's
|           space in the buffer.
|           Again this ignores __MODE__IOTRAN.
| See:
---------------------------------------------*/
int __fwrite(char *buf,int size,int nelm,FILE *fp){
   register int v;
   int len;
   unsigned bytes, put;
   //int errno;

   __thr_safe_lock(fp);

   v = fp->mode;
   /* If last op was a read ... */
   if ((v & __MODE_READING) && __fflush(fp)) {
      __thr_safe_unlock(fp);
      return 0;
   }

   /* Can't write or there's been an EOF or error then return 0 */
   if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) {
      __thr_safe_unlock(fp);
      return 0;
   }

   /* This could be long, doesn't seem much point tho */
   bytes = size * nelm;

   len = fp->bufend - fp->bufpos;

   /* Flush the buffer if not enough room */
   if (bytes > (unsigned)len)
      if (__fflush(fp)) {
         __thr_safe_unlock(fp);
         return 0;
      }

   len = fp->bufend - fp->bufpos;
   if (bytes <= (unsigned)len)          /* It'll fit in the buffer ? */
   {
      fp->mode |= __MODE_WRITING;
      memcpy(fp->bufpos, buf, bytes);
      fp->bufpos += bytes;

      /* If we're not fully buffered */
      if (v & (_IOLBF | _IONBF))
         __fflush(fp);

      __thr_safe_unlock(fp);
      return nelm;
   }
   else /* Too big for the buffer */
   {
      put = bytes;
      do
      {
         len = write(fp->fd, buf, bytes);
         if( len > 0 ) {
            buf+=len; bytes-=len;
         }
      } while (len > 0 || (len != -1 /*&& errno == EINTR*/)); //to do: (len==-1 && errno == EINTR) test.

      if (len < 0)
         fp->mode |= __MODE_ERR;

      put -= bytes;
   }

   __thr_safe_unlock(fp);
   return put / size;
}
/*-------------------------------------------
| Name:fflush
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int __fflush(FILE *fp){
   int len, cc, rv=0;
   char * bstart;
   //int errno;

   __thr_safe_lock(fp);

   if (fp == NULL)              /* On NULL flush the lot. */
   {
      if (__fflush(stdin)) {
         __thr_safe_unlock(fp);
         return EOF;
      }
      if (__fflush(stdout)) {
         __thr_safe_unlock(fp);
         return EOF;
      }
      if (__fflush(stderr)) {
         __thr_safe_unlock(fp);
         return EOF;
      }

      for (fp = __IO_list; fp; fp = fp->next)
         if (__fflush(fp)) {
            __thr_safe_unlock(fp);
            return EOF;
         }

      __thr_safe_unlock(fp);
      return 0;
   }

   /* If there's output data pending */
   if (fp->mode & __MODE_WRITING)
   {
      len = fp->bufpos - fp->bufstart;

      if (len)
      {
         bstart = fp->bufstart;
         /*
          * The loop is so we don't get upset by signals or partial writes.
          */
         do
         {
            cc = write(fp->fd, bstart, len);
            if( cc > 0 )
            {
               bstart+=cc; len-=cc;
            }
         }
         while ( cc>0 || (cc != -1 /*&& errno == EINTR*/)); //to do: (cc == -1 && errno == EINTR) test.
         /*
          * If we get here with len!=0 there was an error, exactly what to
          * do about it is another matter ...
          *
          * I'll just clear the buffer.
          */
         if (len)
         {
            fp->mode |= __MODE_ERR;
            rv = EOF;
         }
      }
   }
   /* If there's data in the buffer sychronise the file positions */
   else if (fp->mode & __MODE_READING)
   {
      /* Humm, I think this means sync the file like fpurge() ... */
      /* Anyway the user isn't supposed to call this function when reading */

      len = fp->bufread - fp->bufpos;   /* Bytes buffered but unread */
      /* If it's a file, make it good */
      if (len > 0 && (lseek(fp->fd, (off_t)-len, 1) < 0))
      {
         /* Hummm - Not certain here, I don't think this is reported */
         /*
          * fp->mode |= __MODE_ERR; return EOF;
          */
      }
   }

   /* All done, no problem */
   fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT));
   fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart;
   __thr_safe_unlock(fp);
   return rv;
}