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