1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*++ |
6 | |
7 | |
8 | |
9 | Module Name: |
10 | |
11 | file.c |
12 | |
13 | Abstract: |
14 | |
15 | Implementation of the file functions in the C runtime library that |
16 | are Windows specific. |
17 | |
18 | |
19 | |
20 | --*/ |
21 | |
22 | #include "pal/palinternal.h" |
23 | #include "pal/dbgmsg.h" |
24 | #include "pal/file.h" |
25 | #include "pal/cruntime.h" |
26 | |
27 | #include "pal/thread.hpp" |
28 | #include "pal/threadsusp.hpp" |
29 | |
30 | #include <unistd.h> |
31 | #include <errno.h> |
32 | #include <sys/stat.h> |
33 | #include <pthread.h> |
34 | |
35 | #if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL |
36 | #define CLEARERR(f) clearerr((f)->bsdFilePtr) |
37 | #else |
38 | #define CLEARERR(f) |
39 | #endif |
40 | |
41 | SET_DEFAULT_DEBUG_CHANNEL(CRT); |
42 | |
43 | /* Global variables storing the std streams.*/ |
44 | PAL_FILE PAL_Stdout; |
45 | PAL_FILE PAL_Stdin; |
46 | PAL_FILE PAL_Stderr; |
47 | |
48 | /*++ |
49 | |
50 | Function: |
51 | |
52 | CRTInitStdStreams. |
53 | |
54 | Initilizes the standard streams. |
55 | Returns TRUE on success, FALSE otherwise. |
56 | --*/ |
57 | BOOL CRTInitStdStreams() |
58 | { |
59 | /* stdout */ |
60 | PAL_Stdout.bsdFilePtr = stdout; |
61 | PAL_Stdout.PALferrorCode = PAL_FILE_NOERROR; |
62 | PAL_Stdout.bTextMode = TRUE; |
63 | |
64 | /* stdin */ |
65 | PAL_Stdin.bsdFilePtr = stdin; |
66 | PAL_Stdin.PALferrorCode = PAL_FILE_NOERROR; |
67 | PAL_Stdin.bTextMode = TRUE; |
68 | |
69 | /* stderr */ |
70 | PAL_Stderr.bsdFilePtr = stderr; |
71 | PAL_Stderr.PALferrorCode = PAL_FILE_NOERROR; |
72 | PAL_Stderr.bTextMode = TRUE; |
73 | return TRUE; |
74 | } |
75 | |
76 | /*++ |
77 | Function : |
78 | |
79 | MapFileOpenModes |
80 | |
81 | Maps Windows file open modes to Unix fopen modes and validates. |
82 | |
83 | --*/ |
84 | static LPSTR MapFileOpenModes(LPSTR str , BOOL * bTextMode) |
85 | { |
86 | LPSTR retval = NULL; |
87 | LPSTR temp = NULL; |
88 | |
89 | if (NULL == bTextMode) |
90 | { |
91 | ASSERT("MapFileOpenModes called with a NULL parameter for bTextMode.\n" ); |
92 | return NULL; |
93 | } |
94 | |
95 | *bTextMode = TRUE; |
96 | |
97 | if (NULL == str) |
98 | { |
99 | ASSERT("MapFileOpenModes called with a NULL parameter for str.\n" ); |
100 | return NULL; |
101 | } |
102 | |
103 | /* The PAL behaves differently for some Windows file open modes: |
104 | |
105 | c, n, S, R, and T: these are all hints to the system that aren't supported |
106 | by the PAL. Since the user cannot depend on this behavior, it's safe to |
107 | simply ignore these modes. |
108 | |
109 | D: specifies a file as temporary. This file is expected to be deleted when |
110 | the last file descriptor is closed. The PAL does not support this behavior |
111 | and asserts when this mode is used. |
112 | |
113 | t: represents opening in text mode. Calls to fdopen on Unix don't accept |
114 | 't' so it is silently stripped out. However, the PAL supports the mode by |
115 | having the PAL wrappers do the translation of CR-LF to LF and vice versa. |
116 | |
117 | t vs. b: To get binary mode, you must explicitly use 'b'. If neither mode |
118 | is specified on Windows, the default mode is defined by the global |
119 | variable _fmode. The PAL simply defaults to text mode. After examining |
120 | CLR usage patterns, the PAL behavior seems acceptable. */ |
121 | |
122 | /* Check if the mode specifies deleting the temporary file |
123 | automatically when the last file descriptor is closed. |
124 | The PAL does not support this behavior. */ |
125 | if (NULL != strchr(str,'D')) |
126 | { |
127 | ASSERT("The PAL doesn't support the 'D' flag for _fdopen and fopen.\n" ); |
128 | return NULL; |
129 | } |
130 | |
131 | /* Check if the mode specifies opening in binary. |
132 | If so, set the bTextMode to false. */ |
133 | if(NULL != strchr(str,'b')) |
134 | { |
135 | *bTextMode = FALSE; |
136 | } |
137 | |
138 | retval = (LPSTR)PAL_malloc( ( strlen( str ) + 1 ) * sizeof( CHAR ) ); |
139 | if (NULL == retval) |
140 | { |
141 | ERROR("Unable to allocate memory.\n" ); |
142 | return NULL; |
143 | } |
144 | |
145 | temp = retval; |
146 | while ( *str ) |
147 | { |
148 | if ( *str == 'r' || *str == 'w' || *str == 'a' ) |
149 | { |
150 | *temp = *str; |
151 | temp++; |
152 | if ( ( ++str != NULL ) && *str == '+' ) |
153 | { |
154 | *temp = *str; |
155 | temp++; |
156 | str++; |
157 | } |
158 | } |
159 | else |
160 | { |
161 | str++; |
162 | } |
163 | } |
164 | *temp = '\0'; |
165 | return retval; |
166 | } |
167 | |
168 | #if UNGETC_NOT_RETURN_EOF |
169 | /*++ |
170 | Function : |
171 | |
172 | WriteOnlyMode |
173 | |
174 | Returns TRUE to if a file is opened in write-only mode, |
175 | Otherwise FALSE. |
176 | |
177 | --*/ |
178 | static BOOL WriteOnlyMode(FILE* pFile) |
179 | { |
180 | INT fd, flags; |
181 | |
182 | if (pFile != NULL) |
183 | { |
184 | fd = fileno(pFile); |
185 | if ((flags = fcntl(fd, F_GETFL)) >= 0) |
186 | { |
187 | if ((flags & O_ACCMODE) == O_WRONLY) |
188 | { |
189 | return TRUE; |
190 | } |
191 | } |
192 | } |
193 | return FALSE; |
194 | } |
195 | #endif //UNGETC_NOT_RETURN_EOF |
196 | |
197 | /*++ |
198 | Function: |
199 | _fdopen |
200 | |
201 | see MSDN |
202 | |
203 | --*/ |
204 | PAL_FILE * |
205 | __cdecl |
206 | _fdopen( |
207 | int handle, |
208 | const char *mode) |
209 | { |
210 | PAL_FILE *f = NULL; |
211 | LPSTR supported = NULL; |
212 | BOOL bTextMode = TRUE; |
213 | |
214 | PERF_ENTRY(_fdopen); |
215 | ENTRY("_fdopen (handle=%d mode=%p (%s))\n" , handle, mode, mode); |
216 | |
217 | _ASSERTE(mode != NULL); |
218 | |
219 | f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); |
220 | if ( f ) |
221 | { |
222 | supported = MapFileOpenModes( (char*)mode , &bTextMode); |
223 | if ( !supported ) |
224 | { |
225 | PAL_free(f); |
226 | f = NULL; |
227 | goto EXIT; |
228 | } |
229 | |
230 | f->bsdFilePtr = (FILE *)fdopen( handle, supported ); |
231 | f->PALferrorCode = PAL_FILE_NOERROR; |
232 | /* Make sure fdopen did not fail. */ |
233 | if ( !f->bsdFilePtr ) |
234 | { |
235 | PAL_free( f ); |
236 | f = NULL; |
237 | } |
238 | |
239 | PAL_free( supported ); |
240 | supported = NULL; |
241 | } |
242 | else |
243 | { |
244 | ERROR( "Unable to allocate memory for the PAL_FILE wrapper!\n" ); |
245 | } |
246 | |
247 | EXIT: |
248 | LOGEXIT( "_fdopen returns FILE* %p\n" , f ); |
249 | PERF_EXIT(_fdopen); |
250 | return f; |
251 | } |
252 | |
253 | |
254 | /*++ |
255 | |
256 | Function : |
257 | fopen |
258 | |
259 | see MSDN doc. |
260 | |
261 | --*/ |
262 | PAL_FILE * |
263 | __cdecl |
264 | PAL_fopen(const char * fileName, const char * mode) |
265 | { |
266 | PAL_FILE *f = NULL; |
267 | LPSTR supported = NULL; |
268 | LPSTR UnixFileName = NULL; |
269 | struct stat stat_data; |
270 | BOOL bTextMode = TRUE; |
271 | |
272 | PERF_ENTRY(fopen); |
273 | ENTRY("fopen ( fileName=%p (%s) mode=%p (%s))\n" , fileName, fileName, mode , mode ); |
274 | |
275 | _ASSERTE(fileName != NULL); |
276 | _ASSERTE(mode != NULL); |
277 | |
278 | if ( *mode == 'r' || *mode == 'w' || *mode == 'a' ) |
279 | { |
280 | supported = MapFileOpenModes( (char*)mode,&bTextMode); |
281 | |
282 | if ( !supported ) |
283 | { |
284 | goto done; |
285 | } |
286 | |
287 | UnixFileName = PAL__strdup(fileName); |
288 | if (UnixFileName == NULL ) |
289 | { |
290 | ERROR("PAL__strdup() failed\n" ); |
291 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); |
292 | goto done; |
293 | } |
294 | |
295 | FILEDosToUnixPathA( UnixFileName ); |
296 | |
297 | /*I am not checking for the case where stat fails |
298 | *as fopen will handle the error more gracefully in case |
299 | *UnixFileName is invalid*/ |
300 | if ((stat(UnixFileName, &stat_data) == 0 ) && |
301 | ((stat_data.st_mode & S_IFMT) == S_IFDIR)) |
302 | { |
303 | goto done; |
304 | } |
305 | |
306 | f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); |
307 | if ( f ) |
308 | { |
309 | f->bsdFilePtr = (FILE*)fopen( UnixFileName, supported ); |
310 | f->PALferrorCode = PAL_FILE_NOERROR; |
311 | f->bTextMode = bTextMode; |
312 | if ( !f->bsdFilePtr ) |
313 | { |
314 | /* Failed */ |
315 | PAL_free( f ); |
316 | f = NULL; |
317 | } |
318 | #if UNGETC_NOT_RETURN_EOF |
319 | else |
320 | { |
321 | f->bWriteOnlyMode = WriteOnlyMode(f->bsdFilePtr); |
322 | } |
323 | #endif //UNGETC_NOT_RETURN_EOF |
324 | } |
325 | else |
326 | { |
327 | ERROR( "Unable to allocate memory to the PAL_FILE wrapper\n" ); |
328 | } |
329 | } |
330 | else |
331 | { |
332 | ERROR( "The mode flags must start with either an a, w, or r.\n" ); |
333 | } |
334 | |
335 | done: |
336 | PAL_free( supported ); |
337 | supported = NULL; |
338 | PAL_free( UnixFileName ); |
339 | |
340 | LOGEXIT( "fopen returns FILE* %p\n" , f ); |
341 | PERF_EXIT(fopen); |
342 | return f; |
343 | } |
344 | |
345 | /*++ |
346 | Function: |
347 | _wfopen |
348 | |
349 | see MSDN doc. |
350 | |
351 | --*/ |
352 | PAL_FILE * |
353 | __cdecl |
354 | _wfopen( |
355 | const wchar_16 *fileName, |
356 | const wchar_16 *mode) |
357 | { |
358 | CHAR mbFileName[ _MAX_PATH ]; |
359 | CHAR mbMode[ 10 ]; |
360 | PAL_FILE * filePtr = NULL; |
361 | |
362 | PERF_ENTRY(_wfopen); |
363 | ENTRY("_wfopen(fileName:%p (%S), mode:%p (%S))\n" , fileName, fileName, mode, mode); |
364 | |
365 | _ASSERTE(fileName != NULL); |
366 | _ASSERTE(mode != NULL); |
367 | |
368 | /* Convert the parameters to ASCII and defer to PAL_fopen */ |
369 | if ( WideCharToMultiByte( CP_ACP, 0, fileName, -1, mbFileName, |
370 | sizeof mbFileName, NULL, NULL ) != 0 ) |
371 | { |
372 | if ( WideCharToMultiByte( CP_ACP, 0, mode, -1, mbMode, |
373 | sizeof mbMode, NULL, NULL ) != 0 ) |
374 | { |
375 | filePtr = PAL_fopen(mbFileName, mbMode); |
376 | } |
377 | else |
378 | { |
379 | ERROR( "An error occurred while converting mode to ANSI.\n" ); |
380 | } |
381 | } |
382 | else |
383 | { |
384 | ERROR( "An error occurred while converting" |
385 | " fileName to ANSI string.\n" ); |
386 | } |
387 | LOGEXIT("_wfopen returning FILE* %p\n" , filePtr); |
388 | PERF_EXIT(_wfopen); |
389 | return filePtr; |
390 | } |
391 | |
392 | /*++ |
393 | Function: |
394 | _wfsopen |
395 | |
396 | see MSDN doc. |
397 | |
398 | --*/ |
399 | PAL_FILE * |
400 | __cdecl |
401 | _wfsopen( |
402 | const wchar_16 *fileName, |
403 | const wchar_16 *mode, |
404 | int shflag) |
405 | { |
406 | // UNIXTODO: Implement this. |
407 | ERROR("Needs Implementation!!!" ); |
408 | return NULL; |
409 | } |
410 | |
411 | /*++ |
412 | Function |
413 | PAL_get_stdout. |
414 | |
415 | Returns the stdout stream. |
416 | --*/ |
417 | PAL_FILE * __cdecl PAL_get_stdout(int caller) |
418 | { |
419 | PERF_ENTRY(get_stdout); |
420 | ENTRY("PAL_get_stdout\n" ); |
421 | LOGEXIT("PAL_get_stdout returns PAL_FILE * %p\n" , &PAL_Stdout ); |
422 | PERF_EXIT(get_stdout); |
423 | return &PAL_Stdout; |
424 | } |
425 | |
426 | /*++ |
427 | Function |
428 | PAL_get_stdin. |
429 | |
430 | Returns the stdin stream. |
431 | --*/ |
432 | PAL_FILE * __cdecl PAL_get_stdin(int caller) |
433 | { |
434 | PERF_ENTRY(get_stdin); |
435 | ENTRY("PAL_get_stdin\n" ); |
436 | LOGEXIT("PAL_get_stdin returns PAL_FILE * %p\n" , &PAL_Stdin ); |
437 | PERF_EXIT(get_stdin); |
438 | return &PAL_Stdin; |
439 | } |
440 | |
441 | /*++ |
442 | Function |
443 | PAL_get_stderr. |
444 | |
445 | Returns the stderr stream. |
446 | --*/ |
447 | PAL_FILE * __cdecl PAL_get_stderr(int caller) |
448 | { |
449 | PERF_ENTRY(get_stderr); |
450 | ENTRY("PAL_get_stderr\n" ); |
451 | LOGEXIT("PAL_get_stderr returns PAL_FILE * %p\n" , &PAL_Stderr ); |
452 | PERF_EXIT(get_stderr); |
453 | return &PAL_Stderr; |
454 | } |
455 | |
456 | |
457 | /*++ |
458 | |
459 | Function: |
460 | |
461 | _close |
462 | |
463 | See msdn for more details. |
464 | --*/ |
465 | int __cdecl PAL__close(int handle) |
466 | { |
467 | INT nRetVal = 0; |
468 | |
469 | PERF_ENTRY(_close); |
470 | ENTRY( "_close( handle=%d )\n" , handle ); |
471 | |
472 | nRetVal = close( handle ); |
473 | |
474 | LOGEXIT( "_close returning %d.\n" , nRetVal ); |
475 | PERF_EXIT(_close); |
476 | return nRetVal; |
477 | } |
478 | |
479 | int __cdecl PAL__flushall() |
480 | { |
481 | return fflush(NULL); |
482 | } |
483 | |
484 | wchar_16 * |
485 | __cdecl |
486 | PAL_fgetws(wchar_16 *s, int n, PAL_FILE *f) |
487 | { |
488 | ASSERT (0); |
489 | return NULL; |
490 | } |
491 | |
492 | |
493 | /*++ |
494 | Function : |
495 | |
496 | fread |
497 | |
498 | See MSDN for more details. |
499 | --*/ |
500 | |
501 | size_t |
502 | __cdecl |
503 | PAL_fread(void * buffer, size_t size, size_t count, PAL_FILE * f) |
504 | { |
505 | size_t nReadBytes = 0; |
506 | |
507 | PERF_ENTRY(fread); |
508 | ENTRY( "fread( buffer=%p, size=%d, count=%d, f=%p )\n" , |
509 | buffer, size, count, f ); |
510 | |
511 | _ASSERTE(f != NULL); |
512 | |
513 | CLEARERR(f); |
514 | |
515 | if(f->bTextMode != TRUE) |
516 | { |
517 | nReadBytes = fread( buffer, size, count, f->bsdFilePtr ); |
518 | } |
519 | else |
520 | { |
521 | size_t i=0; |
522 | if(size > 0) |
523 | { |
524 | size_t j=0; |
525 | LPSTR temp = (LPSTR)buffer; |
526 | int nChar = 0; |
527 | int nCount =0; |
528 | |
529 | for(i=0; i< count; i++) |
530 | { |
531 | for(j=0; j< size; j++) |
532 | { |
533 | if((nChar = PAL_getc(f)) == EOF) |
534 | { |
535 | nReadBytes = i; |
536 | goto done; |
537 | } |
538 | else |
539 | { |
540 | temp[nCount++]=nChar; |
541 | } |
542 | } |
543 | } |
544 | } |
545 | nReadBytes = i; |
546 | } |
547 | |
548 | done: |
549 | LOGEXIT( "fread returning size_t %d\n" , nReadBytes ); |
550 | PERF_EXIT(fread); |
551 | return nReadBytes; |
552 | } |
553 | |
554 | |
555 | /*++ |
556 | Function : |
557 | |
558 | ferror |
559 | |
560 | See MSDN for more details. |
561 | --*/ |
562 | int |
563 | _cdecl |
564 | PAL_ferror(PAL_FILE * f) |
565 | { |
566 | INT nErrorCode = PAL_FILE_NOERROR; |
567 | |
568 | PERF_ENTRY(ferror); |
569 | ENTRY( "ferror( f=%p )\n" , f ); |
570 | |
571 | _ASSERTE(f != NULL); |
572 | |
573 | nErrorCode = ferror( f->bsdFilePtr ); |
574 | if ( 0 == nErrorCode ) |
575 | { |
576 | /* See if the PAL file error code is set. */ |
577 | nErrorCode = f->PALferrorCode; |
578 | } |
579 | |
580 | LOGEXIT( "ferror returns %d\n" , nErrorCode ); |
581 | PERF_EXIT(ferror); |
582 | return nErrorCode; |
583 | } |
584 | |
585 | |
586 | /*++ |
587 | Function : |
588 | |
589 | fclose |
590 | |
591 | See MSDN for more details. |
592 | --*/ |
593 | int |
594 | _cdecl |
595 | PAL_fclose(PAL_FILE * f) |
596 | { |
597 | INT nRetVal = 0; |
598 | |
599 | PERF_ENTRY(fclose); |
600 | ENTRY( "fclose( f=%p )\n" , f ); |
601 | |
602 | _ASSERTE(f != NULL); |
603 | |
604 | CLEARERR(f); |
605 | |
606 | nRetVal = fclose( f->bsdFilePtr ); |
607 | PAL_free( f ); |
608 | |
609 | LOGEXIT( "fclose returning %d\n" , nRetVal ); |
610 | PERF_EXIT(fclose); |
611 | return nRetVal; |
612 | } |
613 | |
614 | /*++ |
615 | Function : |
616 | |
617 | setbuf |
618 | |
619 | See MSDN for more details. |
620 | --*/ |
621 | void |
622 | _cdecl |
623 | PAL_setbuf(PAL_FILE * f, char * buffer) |
624 | { |
625 | PERF_ENTRY(setbuf); |
626 | ENTRY( "setbuf( %p, %p )\n" , f, buffer ); |
627 | |
628 | _ASSERTE(f != NULL); |
629 | |
630 | setbuf( f->bsdFilePtr, buffer ); |
631 | |
632 | LOGEXIT( "setbuf\n" ); |
633 | PERF_EXIT(setbuf); |
634 | } |
635 | |
636 | /*++ |
637 | Function : |
638 | |
639 | fputs |
640 | |
641 | See MSDN for more details. |
642 | --*/ |
643 | int |
644 | _cdecl |
645 | PAL_fputs(const char * str, PAL_FILE * f) |
646 | { |
647 | INT nRetVal = 0; |
648 | |
649 | PERF_ENTRY(fputs); |
650 | ENTRY( "fputs( %p (%s), %p )\n" , str, str, f); |
651 | |
652 | _ASSERTE(str != NULL); |
653 | _ASSERTE(f != NULL); |
654 | |
655 | CLEARERR(f); |
656 | |
657 | nRetVal = fputs( str, f->bsdFilePtr ); |
658 | |
659 | LOGEXIT( "fputs returning %d\n" , nRetVal ); |
660 | PERF_EXIT(fputs); |
661 | return nRetVal; |
662 | } |
663 | |
664 | /*-- |
665 | Function : |
666 | |
667 | fputc |
668 | |
669 | See MSDN for more details. |
670 | --*/ |
671 | int |
672 | _cdecl |
673 | PAL_fputc(int c, PAL_FILE * f) |
674 | { |
675 | INT nRetVal = 0; |
676 | |
677 | PERF_ENTRY(fputc); |
678 | ENTRY( "fputc( 0x%x (%c), %p )\n" , c, c, f); |
679 | |
680 | _ASSERTE(f != NULL); |
681 | |
682 | CLEARERR(f); |
683 | |
684 | nRetVal = fputc( c, f->bsdFilePtr ); |
685 | |
686 | LOGEXIT( "fputc returning %d\n" , nRetVal ); |
687 | PERF_EXIT(fputc); |
688 | return nRetVal; |
689 | } |
690 | |
691 | /*-- |
692 | Function : |
693 | |
694 | putchar |
695 | |
696 | See MSDN for more details. |
697 | --*/ |
698 | int |
699 | _cdecl |
700 | PAL_putchar( int c ) |
701 | { |
702 | INT nRetVal = 0; |
703 | |
704 | PERF_ENTRY(putchar); |
705 | ENTRY( "putchar( 0x%x (%c) )\n" , c, c); |
706 | |
707 | nRetVal = putchar( c ); |
708 | |
709 | LOGEXIT( "putchar returning %d\n" , nRetVal ); |
710 | PERF_EXIT(putchar); |
711 | return nRetVal; |
712 | } |
713 | |
714 | /*++ |
715 | Function : |
716 | |
717 | ftell |
718 | |
719 | See MSDN for more details. |
720 | --*/ |
721 | LONG |
722 | _cdecl |
723 | PAL_ftell(PAL_FILE * f) |
724 | { |
725 | long lRetVal = 0; |
726 | |
727 | PERF_ENTRY(ftell); |
728 | ENTRY( "ftell( %p )\n" , f ); |
729 | |
730 | _ASSERTE(f != NULL); |
731 | lRetVal = ftell( f->bsdFilePtr ); |
732 | |
733 | #ifdef BIT64 |
734 | /* Windows does not set an error if the file pointer's position |
735 | is greater than _I32_MAX. It just returns -1. */ |
736 | if (lRetVal > _I32_MAX) |
737 | { |
738 | lRetVal = -1; |
739 | } |
740 | #endif |
741 | |
742 | LOGEXIT( "ftell returning %ld\n" , lRetVal ); |
743 | PERF_EXIT(ftell); |
744 | /* This explicit cast to LONG is used to silence any potential warnings |
745 | due to implicitly casting the native long lRetVal to LONG when returning. */ |
746 | return (LONG)lRetVal; |
747 | } |
748 | |
749 | /*++ |
750 | Function : |
751 | |
752 | feof |
753 | |
754 | See MSDN for more details. |
755 | --*/ |
756 | int |
757 | _cdecl |
758 | PAL_feof(PAL_FILE * f) |
759 | { |
760 | INT nRetVal = 0; |
761 | |
762 | PERF_ENTRY(feof); |
763 | ENTRY( "feof( %p )\n" , f ); |
764 | |
765 | _ASSERTE(f != NULL); |
766 | nRetVal = feof( f->bsdFilePtr ); |
767 | |
768 | LOGEXIT( "feof returning %d\n" , nRetVal ); |
769 | PERF_EXIT(feof); |
770 | return nRetVal; |
771 | } |
772 | |
773 | /*++ |
774 | Function : |
775 | |
776 | getc |
777 | |
778 | See MSDN for more details. |
779 | --*/ |
780 | int |
781 | _cdecl |
782 | PAL_getc(PAL_FILE * f) |
783 | { |
784 | INT nRetVal = 0; |
785 | INT temp =0; |
786 | |
787 | PERF_ENTRY(getc); |
788 | ENTRY( "getc( %p )\n" , f ); |
789 | |
790 | _ASSERTE(f != NULL); |
791 | |
792 | CLEARERR(f); |
793 | |
794 | nRetVal = getc( f->bsdFilePtr ); |
795 | |
796 | if ( (f->bTextMode) && (nRetVal == '\r') ) |
797 | { |
798 | if ((temp = getc( f->bsdFilePtr ))== '\n') |
799 | { |
800 | nRetVal ='\n'; |
801 | } |
802 | else if (EOF == ungetc( temp, f->bsdFilePtr )) |
803 | { |
804 | ERROR("ungetc operation failed\n" ); |
805 | } |
806 | } |
807 | |
808 | LOGEXIT( "getc returning %d\n" , nRetVal ); |
809 | PERF_EXIT(getc); |
810 | return nRetVal; |
811 | } |
812 | |
813 | /*++ |
814 | Function : |
815 | |
816 | ungetc |
817 | |
818 | See MSDN for more details. |
819 | --*/ |
820 | int |
821 | _cdecl |
822 | PAL_ungetc(int c, PAL_FILE * f) |
823 | { |
824 | INT nRetVal = 0; |
825 | |
826 | PERF_ENTRY(ungetc); |
827 | ENTRY( "ungetc( %c, %p )\n" , c, f ); |
828 | |
829 | _ASSERTE(f != NULL); |
830 | |
831 | #if UNGETC_NOT_RETURN_EOF |
832 | /* On some Unix platform such as Solaris, ungetc does not return EOF |
833 | on write-only file. */ |
834 | if (f->bWriteOnlyMode) |
835 | { |
836 | nRetVal = EOF; |
837 | } |
838 | else |
839 | #endif //UNGETC_NOT_RETURN_EOF |
840 | { |
841 | CLEARERR(f); |
842 | |
843 | nRetVal = ungetc( c, f->bsdFilePtr ); |
844 | } |
845 | |
846 | LOGEXIT( "ungetc returning %d\n" , nRetVal ); |
847 | PERF_EXIT(ungetc); |
848 | return nRetVal; |
849 | } |
850 | |
851 | |
852 | |
853 | /*++ |
854 | Function : |
855 | |
856 | setvbuf |
857 | |
858 | See MSDN for more details. |
859 | --*/ |
860 | int |
861 | _cdecl |
862 | PAL_setvbuf(PAL_FILE *f, char *buf, int type, size_t size) |
863 | { |
864 | INT nRetVal = 0; |
865 | |
866 | PERF_ENTRY(setvbuf); |
867 | ENTRY( "setvbuf( %p, %p, %d, %ul )\n" , f, buf, type, size); |
868 | |
869 | _ASSERTE(f != NULL); |
870 | |
871 | nRetVal = setvbuf(f->bsdFilePtr, buf, type, size); |
872 | |
873 | LOGEXIT( "setvbuf returning %d\n" , nRetVal ); |
874 | PERF_EXIT(setvbuf); |
875 | return nRetVal; |
876 | } |
877 | |