]> pd.if.org Git - pdclib.old/blob - platform/example_cygwin/functions/_PDCLIB/flushbuffer.c
Improved by Caleb1994 of osdev.org.
[pdclib.old] / platform / example_cygwin / functions / _PDCLIB / flushbuffer.c
1 /* $Id$ */
2
3 /* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * )
4
5    This file is part of the Public Domain C Library (PDCLib).
6    Permission is granted to use, modify, and / or redistribute at will.
7 */
8
9 /* This is an example implementation of _PDCLIB_flushbuffer() fit for
10    use with POSIX kernels.
11 */
12
13 #include <stdio.h>
14 #include <string.h>
15
16 #ifndef REGTEST
17 #include <_PDCLIB_glue.h>
18
19 #include </usr/include/errno.h>
20
21 typedef long ssize_t;
22 extern ssize_t write( int fd, const void * buf, size_t count );
23
24 /* The number of attempts to complete an output buffer flushing before giving
25  *    up.
26  *    */
27 #define _PDCLIB_IO_RETRIES 1
28
29 /* What the system should do after an I/O operation did not succeed, before   */
30 /* trying again. (Empty by default.)                                          */
31 #define _PDCLIB_IO_RETRY_OP( stream )
32
33 int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream )
34 {
35     if ( ! ( stream->status & _PDCLIB_FBIN ) )
36     {
37         /* TODO: Text stream conversion here */
38     }
39     /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */
40     _PDCLIB_size_t written = 0;
41     int rc;
42     /* Keep trying to write data until everything is written, an error
43        occurs, or the configured number of retries is exceeded.
44     */
45     for ( unsigned int retries = _PDCLIB_IO_RETRIES; retries > 0; --retries )
46     {
47         rc = (int)write( stream->handle, stream->buffer + written, stream->bufidx - written );
48         if ( rc < 0 )
49         {
50             /* Write error */
51             switch ( errno )
52             {
53                 /* See <_PDCLIB_config.h>. There should be differenciated errno
54                    handling here, possibly even a 1:1 mapping; but that is up
55                    to the individual platform.
56                 */
57                 case EBADF:
58                 case EFAULT:
59                 case EFBIG:
60                 case EINTR:
61                 case EINVAL:
62                 case EIO:
63                 case ENOSPC:
64                 case EPIPE:
65                     _PDCLIB_errno = _PDCLIB_ERROR;
66                     break;
67                 default:
68                     /* This should be something like EUNKNOWN. */
69                     _PDCLIB_errno = _PDCLIB_ERROR;
70                     break;
71             }
72             stream->status |= _PDCLIB_ERRORFLAG;
73             /* Move unwritten remains to begin of buffer. */
74             stream->bufidx -= written;
75             memmove( stream->buffer, stream->buffer + written, stream->bufidx );
76             return EOF;
77         }
78         written += (_PDCLIB_size_t)rc;
79         stream->pos.offset += rc;
80         if ( written == stream->bufidx )
81         {
82             /* Buffer written completely. */
83             stream->bufidx = 0;
84             return 0;
85         }
86     }
87     /* Number of retries exceeded. You probably want a different errno value
88        here.
89     */
90     _PDCLIB_errno = _PDCLIB_ERROR;
91     stream->status |= _PDCLIB_ERRORFLAG;
92     /* Move unwritten remains to begin of buffer. */
93     stream->bufidx -= written;
94     memmove( stream->buffer, stream->buffer + written, stream->bufidx );
95     return EOF;
96 }
97
98 #endif
99
100
101 #ifdef TEST
102 #include <_PDCLIB_test.h>
103
104 int main( void )
105 {
106     /* Testing covered by ftell.c */
107     return TEST_RESULTS;
108 }
109
110 #endif
111