/*++ Function : getc See MSDN for more details. --*/ int _cdecl PAL_getc(PAL_FILE * f) { INT nRetVal = 0; INT temp =0; PERF_ENTRY(getc); ENTRY( "getc( %p )\n", f ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_fgetc"); CLEARERR(f); nRetVal = getc( f->bsdFilePtr ); if ( (f->bTextMode) && (nRetVal == '\r') ) { if ((temp = getc( f->bsdFilePtr ))== '\n') { nRetVal ='\n'; } else if (EOF == ungetc( temp, f->bsdFilePtr )) { ERROR("ungetc operation failed\n"); } } LOGEXIT( "getc returning %d\n", nRetVal ); PERF_EXIT(getc); return nRetVal; }
/*++ Function : ftell See MSDN for more details. --*/ LONG _cdecl PAL_ftell(PAL_FILE * f) { long lRetVal = 0; PERF_ENTRY(ftell); ENTRY( "ftell( %p )\n", f ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_ftell"); lRetVal = ftell( f->bsdFilePtr ); #ifdef BIT64 /* Windows does not set an error if the file pointer's position is greater than _I32_MAX. It just returns -1. */ if (lRetVal > _I32_MAX) { lRetVal = -1; } #endif LOGEXIT( "ftell returning %ld\n", lRetVal ); PERF_EXIT(ftell); /* This explicit cast to LONG is used to silence any potential warnings due to implicitly casting the native long lRetVal to LONG when returning. */ return (LONG)lRetVal; }
/*++ Function : ungetc See MSDN for more details. --*/ int _cdecl PAL_ungetc(int c, PAL_FILE * f) { INT nRetVal = 0; PERF_ENTRY(ungetc); ENTRY( "ungetc( %c, %p )\n", c, f ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_fungetc"); #if UNGETC_NOT_RETURN_EOF /* On some Unix platform such as Solaris, ungetc does not return EOF on write-only file. */ if (f->bWriteOnlyMode) { nRetVal = EOF; } else #endif //UNGETC_NOT_RETURN_EOF { CLEARERR(f); nRetVal = ungetc( c, f->bsdFilePtr ); } LOGEXIT( "ungetc returning %d\n", nRetVal ); PERF_EXIT(ungetc); return nRetVal; }
size_t __cdecl PAL_fread(void * buffer, size_t size, size_t count, PAL_FILE * f) { size_t nReadBytes = 0; PERF_ENTRY(fread); ENTRY( "fread( buffer=%p, size=%d, count=%d, f=%p )\n", buffer, size, count, f ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_fread"); CLEARERR(f); if(f->bTextMode != TRUE) { nReadBytes = fread( buffer, size, count, f->bsdFilePtr ); } else { size_t i=0; if(size > 0) { size_t j=0; LPSTR temp = (LPSTR)buffer; int nChar = 0; int nCount =0; for(i=0; i< count; i++) { for(j=0; j< size; j++) { if((nChar = PAL_getc(f)) == EOF) { nReadBytes = i; goto done; } else { temp[nCount++]=nChar; } } } } nReadBytes = i; } done: LOGEXIT( "fread returning size_t %d\n", nReadBytes ); PERF_EXIT(fread); return nReadBytes; }
/*++ Function: _close See msdn for more details. --*/ int __cdecl PAL__close(int handle) { INT nRetVal = 0; PERF_ENTRY(_close); ENTRY( "_close( handle=%d )\n", handle ); THREADMarkDiagnostic("PAL__close"); nRetVal = close( handle ); LOGEXIT( "_close returning %d.\n", nRetVal ); PERF_EXIT(_close); return nRetVal; }
/*-- Function : putchar See MSDN for more details. --*/ int _cdecl PAL_putchar( int c ) { INT nRetVal = 0; PERF_ENTRY(putchar); ENTRY( "putchar( 0x%x (%c) )\n", c, c); THREADMarkDiagnostic("PAL_putchar"); nRetVal = putchar( c ); LOGEXIT( "putchar returning %d\n", nRetVal ); PERF_EXIT(putchar); return nRetVal; }
/*++ Function : setbuf See MSDN for more details. --*/ void _cdecl PAL_setbuf(PAL_FILE * f, char * buffer) { PERF_ENTRY(setbuf); ENTRY( "setbuf( %p, %p )\n", f, buffer ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_setbuf"); setbuf( f->bsdFilePtr, buffer ); LOGEXIT( "setbuf\n" ); PERF_EXIT(setbuf); }
/*++ Function : feof See MSDN for more details. --*/ int _cdecl PAL_feof(PAL_FILE * f) { INT nRetVal = 0; PERF_ENTRY(feof); ENTRY( "feof( %p )\n", f ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_feof"); nRetVal = feof( f->bsdFilePtr ); LOGEXIT( "feof returning %d\n", nRetVal ); PERF_EXIT(feof); return nRetVal; }
/*++ Function : setvbuf See MSDN for more details. --*/ int _cdecl PAL_setvbuf(PAL_FILE *f, char *buf, int type, size_t size) { INT nRetVal = 0; PERF_ENTRY(setvbuf); ENTRY( "setvbuf( %p, %p, %d, %ul )\n", f, buf, type, size); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_setvbuf"); nRetVal = setvbuf(f->bsdFilePtr, buf, type, size); LOGEXIT( "setvbuf returning %d\n", nRetVal ); PERF_EXIT(setvbuf); return nRetVal; }
/*-- Function : fputc See MSDN for more details. --*/ int _cdecl PAL_fputc(int c, PAL_FILE * f) { INT nRetVal = 0; PERF_ENTRY(fputc); ENTRY( "fputc( 0x%x (%c), %p )\n", c, c, f); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_fputc"); CLEARERR(f); nRetVal = fputc( c, f->bsdFilePtr ); LOGEXIT( "fputc returning %d\n", nRetVal ); PERF_EXIT(fputc); return nRetVal; }
/*++ Function : fclose See MSDN for more details. --*/ int _cdecl PAL_fclose(PAL_FILE * f) { INT nRetVal = 0; PERF_ENTRY(fclose); ENTRY( "fclose( f=%p )\n", f ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_fclose"); CLEARERR(f); nRetVal = fclose( f->bsdFilePtr ); PAL_free( f ); LOGEXIT( "fclose returning %d\n", nRetVal ); PERF_EXIT(fclose); return nRetVal; }
/*++ Function : fputs See MSDN for more details. --*/ int _cdecl PAL_fputs(const char * str, PAL_FILE * f) { INT nRetVal = 0; PERF_ENTRY(fputs); ENTRY( "fputs( %p (%s), %p )\n", str, str, f); _ASSERTE(str != NULL); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_fputs"); CLEARERR(f); nRetVal = fputs( str, f->bsdFilePtr ); LOGEXIT( "fputs returning %d\n", nRetVal ); PERF_EXIT(fputs); return nRetVal; }
int __cdecl PAL_fgetpos ( PAL_FILE *f, PAL_fpos_t *pos ) { #ifdef __LINUX__ // TODO: implement for Linux if required ASSERT(FALSE); return -1; #else int nRetVal = -1; fpos_t native_pos; PERF_ENTRY(fgetpos); ENTRY("fgetpos( f=%p, pos=%p )\n", f, pos); _ASSERTE(f != NULL); _ASSERTE(pos != NULL); THREADMarkDiagnostic("PAL_fgetpos"); if (pos) { native_pos = *pos; nRetVal = fgetpos (f->bsdFilePtr, &native_pos); *pos = native_pos; } else { ERROR ("Error: NULL pos pointer\n"); errno = EINVAL; } LOGEXIT( "fgetpos returning error code %d, pos %d\n", nRetVal, pos ? *pos : 0); PERF_EXIT(fgetpos); return nRetVal; #endif // __LINUX__ }
/*++ Function : ferror See MSDN for more details. --*/ int _cdecl PAL_ferror(PAL_FILE * f) { INT nErrorCode = PAL_FILE_NOERROR; PERF_ENTRY(ferror); ENTRY( "ferror( f=%p )\n", f ); _ASSERTE(f != NULL); THREADMarkDiagnostic("PAL_ferror"); nErrorCode = ferror( f->bsdFilePtr ); if ( 0 == nErrorCode ) { /* See if the PAL file error code is set. */ nErrorCode = f->PALferrorCode; } LOGEXIT( "ferror returns %d\n", nErrorCode ); PERF_EXIT(ferror); return nErrorCode; }
ULONGLONG __cdecl PAL__wcstoui64( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; unsigned long long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstoul); ENTRY("_wcstoui64 (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); THREADMarkDiagnostic("PAL__wcstoui64 -> strtoull"); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL__wcstoui64Exit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL__wcstoui64Exit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL__wcstoui64Exit; } res = strtoull(s_nptr, &s_endptr, base); /* only ASCII characters will be accepted by strtoull, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL__wcstoui64Exit: PAL_free(s_nptr); LOGEXIT("_wcstoui64 returning unsigned long long %llu\n", res); PERF_EXIT(_wcstoui64); return res; }
/* The use of ULONG is by design, to ensure that a 32 bit value is always returned from this function. If "unsigned long" is used instead of ULONG, then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus breaking Windows behavior .*/ ULONG __cdecl PAL_wcstoul( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; unsigned long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstoul); ENTRY("wcstoul (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); THREADMarkDiagnostic("PAL_wcstoul -> strtoul"); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstoulExit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL_wcstoulExit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstoulExit; } res = strtoul(s_nptr, &s_endptr, base); #ifdef BIT64 if (res > _UI32_MAX) { wchar_16 wc = *nptr; while (PAL_iswspace(wc)) { wc = *nptr++; } /* If the string represents a positive number that is greater than _UI32_MAX, set errno to ERANGE. Otherwise, don't set errno to match Windows behavior. */ if (wc != '-') { res = _UI32_MAX; errno = ERANGE; } } #endif /* only ASCII characters will be accepted by strtol, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL_wcstoulExit: PAL_free(s_nptr); LOGEXIT("wcstoul returning unsigned long %lu\n", res); PERF_EXIT(wcstoul); /* When returning unsigned long res from this function, it will be implicitly cast to ULONG. This handles situations where a string that represents a negative number is passed in to wcstoul. The Windows behavior is analogous to taking the binary equivalent of the negative value and treating it as a positive number. Returning a ULONG from this function, as opposed to native unsigned long, allows us to match this behavior. The explicit case to ULONG below is used to silence any potential warnings due to the implicit casting. */ return (ULONG)res; }
/*++ Function : wcstod There is a slight difference between the Windows version of wcstod and the BSD versio of wcstod. Under Windows the string " -1b " returns -1.000000 stop char = 'b' Under BSD the same string returns 0.000000 stop ' ' see msdn doc. --*/ double __cdecl PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) { double RetVal = 0.0; LPSTR lpStringRep = NULL; LPWSTR lpStartOfExpression = (LPWSTR)nptr; LPWSTR lpEndOfExpression = NULL; UINT Length = 0; PERF_ENTRY(wcstod); ENTRY( "wcstod( %p (%S), %p (%S) )\n", nptr, nptr, endptr , endptr ); THREADMarkDiagnostic("PAL_wcstod -> strtod"); if ( !nptr ) { ERROR( "nptr is invalid.\n" ); LOGEXIT( "wcstod returning 0.0\n" ); PERF_EXIT(wcstod); return 0.0; } /* Eat white space. */ while ( PAL_iswspace( *lpStartOfExpression ) ) { lpStartOfExpression++; } /* Get the end of the expression. */ lpEndOfExpression = lpStartOfExpression; while ( *lpEndOfExpression ) { if ( !MISC_CRT_WCSTOD_IsValidCharacter( *lpEndOfExpression ) ) { break; } lpEndOfExpression++; } if ( lpEndOfExpression != lpStartOfExpression ) { Length = lpEndOfExpression - lpStartOfExpression; lpStringRep = (LPSTR)PAL_malloc( Length + 1); if ( lpStringRep ) { if ( WideCharToMultiByte( CP_ACP, 0, lpStartOfExpression, Length, lpStringRep, Length + 1 , NULL, 0 ) != 0 ) { LPSTR ScanStop = NULL; lpStringRep[Length]= 0; RetVal = strtod( lpStringRep, &ScanStop ); /* See if strtod failed. */ if ( RetVal == 0.0 && ScanStop == lpStringRep ) { ASSERT( "An error occured in the conversion.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ASSERT( "Wide char to multibyte conversion failed.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ERROR( "Not enough memory.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ERROR( "Malformed expression.\n" ); lpEndOfExpression = (LPWSTR)nptr; } /* Set the stop scan character. */ if ( endptr != NULL ) { *endptr = lpEndOfExpression; } PAL_free( lpStringRep ); LOGEXIT( "wcstod returning %f.\n", RetVal ); PERF_EXIT(wcstod); return RetVal; }
__cdecl PAL_fopen(const char * fileName, const char * mode) { PAL_FILE *f = NULL; LPSTR supported = NULL; LPSTR UnixFileName = NULL; struct stat stat_data; BOOL bTextMode = TRUE; PERF_ENTRY(fopen); ENTRY("fopen ( fileName=%p (%s) mode=%p (%s))\n", fileName, fileName, mode , mode ); _ASSERTE(fileName != NULL); _ASSERTE(mode != NULL); THREADMarkDiagnostic("PAL_fopen"); if ( *mode == 'r' || *mode == 'w' || *mode == 'a' ) { supported = MapFileOpenModes( (char*)mode,&bTextMode); if ( !supported ) { goto done; } UnixFileName = PAL__strdup(fileName); if (UnixFileName == NULL ) { ERROR("PAL__strdup() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } FILEDosToUnixPathA( UnixFileName ); /*I am not checking for the case where stat fails *as fopen will handle the error more gracefully in case *UnixFileName is invalid*/ if ((stat(UnixFileName, &stat_data) == 0 ) && ((stat_data.st_mode & S_IFMT) == S_IFDIR)) { goto done; } f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); if ( f ) { f->bsdFilePtr = (FILE*)fopen( UnixFileName, supported ); f->PALferrorCode = PAL_FILE_NOERROR; f->bTextMode = bTextMode; if ( !f->bsdFilePtr ) { /* Failed */ PAL_free( f ); f = NULL; } #if UNGETC_NOT_RETURN_EOF else { f->bWriteOnlyMode = WriteOnlyMode(f->bsdFilePtr); } #endif //UNGETC_NOT_RETURN_EOF } else { ERROR( "Unable to allocate memory to the PAL_FILE wrapper\n" ); } } else { ERROR( "The mode flags must start with either an a, w, or r.\n" ); } done: PAL_free( supported ); supported = NULL; PAL_free( UnixFileName ); LOGEXIT( "fopen returns FILE* %p\n", f ); PERF_EXIT(fopen); return f; }