Subversion Repositories Kolibri OS

Rev

Rev 4921 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19. FUNCTION
  20. <<fflush>>, <<fflush_unlocked>>---flush buffered file output
  21.  
  22. INDEX
  23.         fflush
  24. INDEX
  25.         fflush_unlocked
  26. INDEX
  27.         _fflush_r
  28. INDEX
  29.         _fflush_unlocked_r
  30.  
  31. ANSI_SYNOPSIS
  32.         #include <stdio.h>
  33.         int fflush(FILE *<[fp]>);
  34.  
  35.         #define _BSD_SOURCE
  36.         #include <stdio.h>
  37.         int fflush_unlocked(FILE *<[fp]>);
  38.  
  39.         #include <stdio.h>
  40.         int _fflush_r(struct _reent *<[reent]>, FILE *<[fp]>);
  41.  
  42.         #define _BSD_SOURCE
  43.         #include <stdio.h>
  44.         int _fflush_unlocked_r(struct _reent *<[reent]>, FILE *<[fp]>);
  45.  
  46. DESCRIPTION
  47. The <<stdio>> output functions can buffer output before delivering it
  48. to the host system, in order to minimize the overhead of system calls.
  49.  
  50. Use <<fflush>> to deliver any such pending output (for the file
  51. or stream identified by <[fp]>) to the host system.
  52.  
  53. If <[fp]> is <<NULL>>, <<fflush>> delivers pending output from all
  54. open files.
  55.  
  56. Additionally, if <[fp]> is a seekable input stream visiting a file
  57. descriptor, set the position of the file descriptor to match next
  58. unread byte, useful for obeying POSIX semantics when ending a process
  59. without consuming all input from the stream.
  60.  
  61. <<fflush_unlocked>> is a non-thread-safe version of <<fflush>>.
  62. <<fflush_unlocked>> may only safely be used within a scope
  63. protected by flockfile() (or ftrylockfile()) and funlockfile().  This
  64. function may safely be used in a multi-threaded program if and only
  65. if they are called while the invoking thread owns the (FILE *)
  66. object, as is the case after a successful call to the flockfile() or
  67. ftrylockfile() functions.  If threads are disabled, then
  68. <<fflush_unlocked>> is equivalent to <<fflush>>.
  69.  
  70. The alternate functions <<_fflush_r>> and <<_fflush_unlocked_r>> are
  71. reentrant versions, where the extra argument <[reent]> is a pointer to
  72. a reentrancy structure, and <[fp]> must not be NULL.
  73.  
  74. RETURNS
  75. <<fflush>> returns <<0>> unless it encounters a write error; in that
  76. situation, it returns <<EOF>>.
  77.  
  78. PORTABILITY
  79. ANSI C requires <<fflush>>.  The behavior on input streams is only
  80. specified by POSIX, and not all implementations follow POSIX rules.
  81.  
  82. <<fflush_unlocked>> is a BSD extension also provided by GNU libc.
  83.  
  84. No supporting OS subroutines are required.
  85. */
  86.  
  87. #include <_ansi.h>
  88. #include <stdio.h>
  89. #include <errno.h>
  90. #include "local.h"
  91.  
  92. #ifdef __IMPL_UNLOCKED__
  93. #define _fflush_r _fflush_unlocked_r
  94. #define fflush fflush_unlocked
  95. #endif
  96.  
  97. #ifndef __IMPL_UNLOCKED__
  98. /* Flush a single file, or (if fp is NULL) all files.  */
  99.  
  100. /* Core function which does not lock file pointer.  This gets called
  101.    directly from __srefill. */
  102. int
  103. _DEFUN(__sflush_r, (ptr, fp),
  104.        struct _reent *ptr _AND
  105.        register FILE * fp)
  106. {
  107.   register unsigned char *p;
  108.   register _READ_WRITE_BUFSIZE_TYPE n;
  109.   register _READ_WRITE_RETURN_TYPE t;
  110.   short flags;
  111.  
  112.   flags = fp->_flags;
  113.   if ((flags & __SWR) == 0)
  114.     {
  115. #ifdef _FSEEK_OPTIMIZATION
  116.       /* For a read stream, an fflush causes the next seek to be
  117.          unoptimized (i.e. forces a system-level seek).  This conforms
  118.          to the POSIX and SUSv3 standards.  */
  119.       fp->_flags |= __SNPT;
  120. #endif
  121.  
  122.       /* For a seekable stream with buffered read characters, we will attempt
  123.          a seek to the current position now.  A subsequent read will then get
  124.          the next byte from the file rather than the buffer.  This conforms
  125.          to the POSIX and SUSv3 standards.  Note that the standards allow
  126.          this seek to be deferred until necessary, but we choose to do it here
  127.          to make the change simpler, more contained, and less likely
  128.          to miss a code scenario.  */
  129.       if ((fp->_r > 0 || fp->_ur > 0) && fp->_seek != NULL)
  130.         {
  131.           int tmp_errno;
  132. #ifdef __LARGE64_FILES
  133.           _fpos64_t curoff;
  134. #else
  135.           _fpos_t curoff;
  136. #endif
  137.  
  138.           /* Save last errno and set errno to 0, so we can check if a device
  139.              returns with a valid position -1.  We restore the last errno if
  140.              no other error condition has been encountered. */
  141.           tmp_errno = ptr->_errno;
  142.           ptr->_errno = 0;
  143.           /* Get the physical position we are at in the file.  */
  144.           if (fp->_flags & __SOFF)
  145.             curoff = fp->_offset;
  146.           else
  147.             {
  148.               /* We don't know current physical offset, so ask for it.
  149.                  Only ESPIPE and EINVAL are ignorable.  */
  150. #ifdef __LARGE64_FILES
  151.               if (fp->_flags & __SL64)
  152.                 curoff = fp->_seek64 (ptr, fp->_cookie, 0, SEEK_CUR);
  153.               else
  154. #endif
  155.                 curoff = fp->_seek (ptr, fp->_cookie, 0, SEEK_CUR);
  156.               if (curoff == -1L && ptr->_errno != 0)
  157.                 {
  158.                   int result = EOF;
  159.                   if (ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
  160.                     {
  161.                       result = 0;
  162.                       ptr->_errno = tmp_errno;
  163.                     }
  164.                   else
  165.                     fp->_flags |= __SERR;
  166.                   return result;
  167.                 }
  168.             }
  169.           if (fp->_flags & __SRD)
  170.             {
  171.               /* Current offset is at end of buffer.  Compensate for
  172.                  characters not yet read.  */
  173.               curoff -= fp->_r;
  174.               if (HASUB (fp))
  175.                 curoff -= fp->_ur;
  176.             }
  177.           /* Now physically seek to after byte last read.  */
  178. #ifdef __LARGE64_FILES
  179.           if (fp->_flags & __SL64)
  180.             curoff = fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET);
  181.           else
  182. #endif
  183.             curoff = fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET);
  184.           if (curoff != -1 || ptr->_errno == 0
  185.               || ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
  186.             {
  187.               /* Seek successful or ignorable error condition.
  188.                  We can clear read buffer now.  */
  189. #ifdef _FSEEK_OPTIMIZATION
  190.               fp->_flags &= ~__SNPT;
  191. #endif
  192.               fp->_r = 0;
  193.               fp->_p = fp->_bf._base;
  194.               if ((fp->_flags & __SOFF) && (curoff != -1 || ptr->_errno == 0))
  195.                 fp->_offset = curoff;
  196.               ptr->_errno = tmp_errno;
  197.               if (HASUB (fp))
  198.                 FREEUB (ptr, fp);
  199.             }
  200.           else
  201.             {
  202.               fp->_flags |= __SERR;
  203.               return EOF;
  204.             }
  205.         }
  206.       return 0;
  207.     }
  208.   if ((p = fp->_bf._base) == NULL)
  209.     {
  210.       /* Nothing to flush.  */
  211.       return 0;
  212.     }
  213.   n = fp->_p - p;               /* write this much */
  214.  
  215.   /*
  216.    * Set these immediately to avoid problems with longjmp
  217.    * and to allow exchange buffering (via setvbuf) in user
  218.    * write function.
  219.    */
  220.   fp->_p = p;
  221.   fp->_w = flags & (__SLBF | __SNBF) ? 0 : fp->_bf._size;
  222.  
  223.   while (n > 0)
  224.     {
  225.       t = fp->_write (ptr, fp->_cookie, (char *) p, n);
  226.       if (t <= 0)
  227.         {
  228.           fp->_flags |= __SERR;
  229.           return EOF;
  230.         }
  231.       p += t;
  232.       n -= t;
  233.     }
  234.   return 0;
  235. }
  236.  
  237. #ifdef _STDIO_BSD_SEMANTICS
  238. /* Called from _cleanup_r.  At exit time, we don't need file locking,
  239.    and we don't want to move the underlying file pointer unless we're
  240.    writing. */
  241. int
  242. _DEFUN(__sflushw_r, (ptr, fp),
  243.        struct _reent *ptr _AND
  244.        register FILE *fp)
  245. {
  246.   return (fp->_flags & __SWR) ?  __sflush_r (ptr, fp) : 0;
  247. }
  248. #endif
  249.  
  250. #endif /* __IMPL_UNLOCKED__ */
  251.  
  252. int
  253. _DEFUN(_fflush_r, (ptr, fp),
  254.        struct _reent *ptr _AND
  255.        register FILE * fp)
  256. {
  257.   int ret;
  258.  
  259. #ifdef _REENT_SMALL
  260.   /* For REENT_SMALL platforms, it is possible we are being
  261.      called for the first time on a std stream.  This std
  262.      stream can belong to a reentrant struct that is not
  263.      _REENT.  If CHECK_INIT gets called below based on _REENT,
  264.      we will end up changing said file pointers to the equivalent
  265.      std stream off of _REENT.  This causes unexpected behavior if
  266.      there is any data to flush on the _REENT std stream.  There
  267.      are two alternatives to fix this:  1) make a reentrant fflush
  268.      or 2) simply recognize that this file has nothing to flush
  269.      and return immediately before performing a CHECK_INIT.  Choice
  270.      2 is implemented here due to its simplicity.  */
  271.   if (fp->_bf._base == NULL)
  272.     return 0;
  273. #endif /* _REENT_SMALL  */
  274.  
  275.   CHECK_INIT (ptr, fp);
  276.  
  277.   if (!fp->_flags)
  278.     return 0;
  279.  
  280.   _newlib_flockfile_start (fp);
  281.   ret = __sflush_r (ptr, fp);
  282.   _newlib_flockfile_end (fp);
  283.   return ret;
  284. }
  285.  
  286. #ifndef _REENT_ONLY
  287.  
  288. int
  289. _DEFUN(fflush, (fp),
  290.        register FILE * fp)
  291. {
  292.   if (fp == NULL)
  293.     return _fwalk_reent (_GLOBAL_REENT, _fflush_r);
  294.  
  295.   return _fflush_r (_REENT, fp);
  296. }
  297.  
  298. #endif /* _REENT_ONLY */
  299.