33
33
* OF THE POSSIBILITY OF SUCH DAMAGE.
34
34
*/
35
35
36
+ #define _DEFAULT_SOURCE /* for strnlen */
36
37
#include "stdio_private.h"
37
38
#include <stdlib.h>
38
39
#include <errno.h>
39
40
#include <fcntl.h>
41
+ #include <string.h>
40
42
#include <unistd.h>
41
43
42
44
#define __MALL 0x01
43
45
44
46
struct __file_mem {
45
47
struct __file_ext xfile ;
46
48
char * buf ;
47
- size_t size ;
49
+ size_t size ; /* Current size. */
50
+ size_t bufsize ; /* Upper limit on size. */
48
51
size_t pos ;
49
52
uint8_t mflags ;
50
53
};
@@ -53,11 +56,17 @@ static int
53
56
__fmem_put (char c , FILE * f )
54
57
{
55
58
struct __file_mem * mf = (struct __file_mem * )f ;
56
- if ((f -> flags & __SWR ) && mf -> pos < mf -> size ) {
59
+ if ((f -> flags & __SWR ) == 0 ) {
60
+ return _FDEV_ERR ;
61
+ } else if (mf -> pos < mf -> bufsize ) {
57
62
mf -> buf [mf -> pos ++ ] = c ;
63
+ if (mf -> pos > mf -> size ) {
64
+ mf -> size = mf -> pos ;
65
+ }
58
66
return (unsigned char )c ;
67
+ } else {
68
+ return _FDEV_EOF ;
59
69
}
60
- return _FDEV_ERR ;
61
70
}
62
71
63
72
static int
@@ -78,8 +87,12 @@ static int
78
87
__fmem_flush (FILE * f )
79
88
{
80
89
struct __file_mem * mf = (struct __file_mem * )f ;
81
- if ((f -> flags & __SWR ) && mf -> pos < mf -> size )
90
+ if ((f -> flags & __SWR ) && mf -> pos < mf -> bufsize ) {
82
91
mf -> buf [mf -> pos ] = '\0' ;
92
+ if (mf -> pos > mf -> size ) {
93
+ mf -> size = mf -> pos ;
94
+ }
95
+ }
83
96
return 0 ;
84
97
}
85
98
@@ -122,6 +135,8 @@ fmemopen(void *buf, size_t size, const char *mode)
122
135
{
123
136
int stdio_flags ;
124
137
uint8_t mflags = 0 ;
138
+ size_t initial_pos = 0 ;
139
+ size_t initial_size ;
125
140
struct __file_mem * mf ;
126
141
127
142
stdio_flags = __stdio_sflags (mode );
@@ -155,12 +170,28 @@ fmemopen(void *buf, size_t size, const char *mode)
155
170
mflags |= __MALL ;
156
171
}
157
172
173
+ /* Check mode directly to avoid _POSIX_IO dependency. */
174
+ if (mode [0 ] == 'a' ) {
175
+ /* For append the position is set to the first NUL byte or the end. */
176
+ initial_pos = (mflags & __MALL ) ? 0 : strnlen (buf , size );
177
+ initial_size = initial_pos ;
178
+ } else if (mode [0 ] == 'w' ) {
179
+ initial_size = 0 ;
180
+ /* w+ mode truncates the buffer, writing NUL */
181
+ if ((stdio_flags & (__SRD | __SWR )) == (__SRD | __SWR )) {
182
+ * ((char * )buf ) = '\0' ;
183
+ }
184
+ } else {
185
+ initial_size = size ;
186
+ }
187
+
158
188
* mf = (struct __file_mem ){
159
189
.xfile = FDEV_SETUP_EXT (__fmem_put , __fmem_get , __fmem_flush ,
160
190
__fmem_close , __fmem_seek , NULL , stdio_flags ),
161
191
.buf = buf ,
162
- .size = size ,
163
- .pos = 0 ,
192
+ .size = initial_size ,
193
+ .bufsize = size ,
194
+ .pos = initial_pos ,
164
195
.mflags = mflags ,
165
196
};
166
197
0 commit comments