Subversion Repositories Kolibri OS

Rev

Rev 4874 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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