Merge branch 'alexischr/nursery-canaries-managed-alloc'
[mono.git] / support / stdio.c
1 /*
2  * <stdio.h> wrapper functions.
3  *
4  * Authors:
5  *   Jonathan Pryor (jonpryor@vt.edu)
6  *
7  * Copyright (C) 2004-2006 Jonathan Pryor
8  */
9
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #include "map.h"
15 #include "mph.h"
16
17 G_BEGIN_DECLS
18
19 #ifndef HOST_WIN32
20 gint32
21 Mono_Posix_Syscall_L_ctermid (void)
22 {
23         return L_ctermid;
24 }
25
26 gint32
27 Mono_Posix_Syscall_L_cuserid (void)
28 {
29 #if defined(__APPLE__) || defined (__OpenBSD__)
30         return -1;
31 #else
32         return L_cuserid;
33 #endif
34 }
35 #endif /* ndef HOST_WIN32 */
36
37 mph_size_t
38 Mono_Posix_Stdlib_fread (unsigned char *ptr, mph_size_t size, mph_size_t nmemb, void *stream)
39 {
40         mph_return_if_size_t_overflow (size);
41         mph_return_if_size_t_overflow (nmemb);
42
43         return fread (ptr, (size_t) size, (size_t) nmemb, (FILE*) stream);
44 }
45
46 mph_size_t
47 Mono_Posix_Stdlib_fwrite (unsigned char *ptr, mph_size_t size, mph_size_t nmemb, void *stream)
48 {
49         mph_return_if_size_t_overflow (size);
50         mph_return_if_size_t_overflow (nmemb);
51
52         size_t ret = fwrite (ptr, (size_t) size, (size_t) nmemb, (FILE*) stream);
53 #ifdef HOST_WIN32
54         // Workaround for a particular weirdness on Windows triggered by the
55         // StdioFileStreamTest.Write() test method. The test writes 15 bytes to a
56         // file, then rewinds the file pointer and reads the same bytes. It then
57         // writes 15 additional bytes to the file. This second write fails on
58         // Windows with 0 returned from fwrite(). Calling fseek() followed by a retry
59         // of fwrite() like we do here fixes the issue.
60         if (ret != nmemb)
61         {
62                 fseek (stream, 0, SEEK_CUR);
63                 ret = fwrite (ptr + (ret * nmemb), (size_t) size, (size_t) nmemb - ret, (FILE*) stream);
64         }
65 #endif
66         return ret;
67 }
68
69 #ifdef HAVE_VSNPRINTF
70 gint32
71 Mono_Posix_Stdlib_snprintf (char *s, mph_size_t n, char *format, ...);
72 gint32
73 Mono_Posix_Stdlib_snprintf (char *s, mph_size_t n, char *format, ...)
74 {
75         va_list ap;
76         gint32 r;
77         mph_return_if_size_t_overflow (n);
78
79         va_start (ap, format);
80         r = vsnprintf (s, (size_t) n, format, ap);
81         va_end (ap);
82
83         return r;
84 }
85 #endif /* def HAVE_VSNPRINTF */
86
87 gint32
88 Mono_Posix_Stdlib__IOFBF (void)
89 {
90         return _IOFBF;
91 }
92
93 gint32
94 Mono_Posix_Stdlib__IOLBF (void)
95 {
96         return _IOLBF;
97 }
98
99 gint32
100 Mono_Posix_Stdlib__IONBF (void)
101 {
102         return _IONBF;
103 }
104
105 gint32
106 Mono_Posix_Stdlib_BUFSIZ (void)
107 {
108         return BUFSIZ;
109 }
110
111 gint32
112 Mono_Posix_Stdlib_EOF (void)
113 {
114         return EOF;
115 }
116
117 gint32
118 Mono_Posix_Stdlib_FOPEN_MAX (void)
119 {
120         return FOPEN_MAX;
121 }
122
123 gint32
124 Mono_Posix_Stdlib_FILENAME_MAX (void)
125 {
126         return FILENAME_MAX;
127 }
128
129 gint32
130 Mono_Posix_Stdlib_L_tmpnam (void)
131 {
132         return L_tmpnam;
133 }
134
135 void*
136 Mono_Posix_Stdlib_stdin (void)
137 {
138         return stdin;
139 }
140
141 void*
142 Mono_Posix_Stdlib_stdout (void)
143 {
144         return stdout;
145 }
146
147 void*
148 Mono_Posix_Stdlib_stderr (void)
149 {
150         return stderr;
151 }
152
153 gint32
154 Mono_Posix_Stdlib_TMP_MAX (void)
155 {
156         return TMP_MAX;
157 }
158
159 void*
160 Mono_Posix_Stdlib_tmpfile (void)
161 {
162         return tmpfile ();
163 }
164
165 gint32
166 Mono_Posix_Stdlib_setvbuf (void* stream, void *buf, int mode, mph_size_t size)
167 {
168         mph_return_if_size_t_overflow (size);
169         return setvbuf (stream, (char *) buf, mode, (size_t) size);
170 }
171
172 int 
173 Mono_Posix_Stdlib_setbuf (void* stream, void* buf)
174 {
175         setbuf (stream, buf);
176         return 0;
177 }
178
179 void*
180 Mono_Posix_Stdlib_fopen (char* path, char* mode)
181 {
182         return fopen (path, mode);
183 }
184
185 void*
186 Mono_Posix_Stdlib_freopen (char* path, char* mode, void *stream)
187 {
188         return freopen (path, mode, stream);
189 }
190
191 gint32
192 Mono_Posix_Stdlib_fprintf (void* stream, char* format, char *message)
193 {
194         return fprintf (stream, format, message);
195 }
196
197 gint32
198 Mono_Posix_Stdlib_fgetc (void* stream)
199 {
200         return fgetc (stream);
201 }
202
203 char*
204 Mono_Posix_Stdlib_fgets (char* str, gint32 size, void* stream)
205 {
206         return fgets (str, size, stream);
207 }
208
209 gint32
210 Mono_Posix_Stdlib_fputc (gint32 c, void* stream)
211 {
212         return fputc (c, stream);
213 }
214
215 gint32
216 Mono_Posix_Stdlib_fputs (char* s, void* stream)
217 {
218         return fputs (s, stream);
219 }
220
221 gint32
222 Mono_Posix_Stdlib_fclose (void* stream)
223 {
224         return fclose (stream);
225 }
226
227 gint32
228 Mono_Posix_Stdlib_fflush (void* stream)
229 {
230         return fflush (stream);
231 }
232
233 gint32
234 Mono_Posix_Stdlib_fseek (void* stream, gint64 offset, int origin)
235 {
236         mph_return_if_long_overflow (offset);
237
238         return fseek (stream, offset, origin);
239 }
240
241 gint64
242 Mono_Posix_Stdlib_ftell (void* stream)
243 {
244         return ftell (stream);
245 }
246
247 void*
248 Mono_Posix_Stdlib_CreateFilePosition (void)
249 {
250         fpos_t* pos = malloc (sizeof(fpos_t));
251         return pos;
252 }
253
254 gint32
255 Mono_Posix_Stdlib_fgetpos (void* stream, void *pos)
256 {
257         return fgetpos (stream, (fpos_t*) pos);
258 }
259
260 gint32
261 Mono_Posix_Stdlib_fsetpos (void* stream, void *pos)
262 {
263         return fsetpos (stream, (fpos_t*) pos);
264 }
265
266 int
267 Mono_Posix_Stdlib_rewind (void* stream)
268 {
269         do {
270                 rewind (stream);
271         } while (errno == EINTR);
272         mph_return_if_val_in_list5(errno, EAGAIN, EBADF, EFBIG, EINVAL, EIO);
273         mph_return_if_val_in_list5(errno, ENOSPC, ENXIO, EOVERFLOW, EPIPE, ESPIPE);
274         return 0;
275 }
276
277 int
278 Mono_Posix_Stdlib_clearerr (void* stream)
279 {
280         clearerr (((FILE*) stream));
281         return 0;
282 }
283
284 gint32
285 Mono_Posix_Stdlib_ungetc (gint32 c, void* stream)
286 {
287         return ungetc (c, stream);
288 }
289
290 gint32
291 Mono_Posix_Stdlib_feof (void* stream)
292 {
293         return feof (((FILE*) stream));
294 }
295
296 gint32
297 Mono_Posix_Stdlib_ferror (void* stream)
298 {
299         return ferror (((FILE*) stream));
300 }
301
302 int
303 Mono_Posix_Stdlib_perror (const char* s, int err)
304 {
305         errno = err;
306         perror (s);
307         return 0;
308 }
309
310 #define MPH_FPOS_LENGTH (sizeof(fpos_t)*2)
311
312 int
313 Mono_Posix_Stdlib_DumpFilePosition (char *dest, void *pos, gint32 len)
314 {
315         char *destp;
316         unsigned char *posp, *pose;
317
318         if (dest == NULL)
319                 return MPH_FPOS_LENGTH;
320
321         if (pos == NULL || len <= 0) {
322                 errno = EINVAL;
323                 return -1;
324         }
325
326         posp = (unsigned char*) pos;
327         pose = posp + sizeof(fpos_t);
328         destp = dest;
329
330         for ( ; posp < pose && len > 1; destp += 2, ++posp, len -= 2) {
331                 sprintf (destp, "%02X", *posp);
332         }
333
334         if (len)
335                 dest[MPH_FPOS_LENGTH] = '\0';
336
337         return destp - dest;
338 }
339
340 G_END_DECLS
341
342 /*
343  * vim: noexpandtab
344  */