1 // 2 // fopen.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // Functions that open a file as a stdio stream. 7 // 8 #include <corecrt_internal_stdio.h> 9 10 11 12 // Opens the file named by 'file_name' as a stdio stream. The 'mode' determines 13 // the mode in which the file is opened and the 'share_flag' determines the 14 // sharing mode. Supported modes are "r" (read), "w" (write), "a" (append), 15 // "r+" (read and write), "w+" (open empty for read and write), and "a+" (read 16 // and append). A "t" or "b" may be appended to the mode string to request text 17 // or binary mode, respectively. 18 // 19 // Returns the FILE* for the newly opened stream on success; returns nullptr on 20 // failure. 21 template <typename Character> 22 static FILE* __cdecl common_fsopen( 23 Character const* const file_name, 24 Character const* const mode, 25 int const share_flag 26 ) throw() 27 { 28 typedef __acrt_stdio_char_traits<Character> stdio_traits; 29 30 _VALIDATE_RETURN(file_name != nullptr, EINVAL, nullptr); 31 _VALIDATE_RETURN(mode != nullptr, EINVAL, nullptr); 32 _VALIDATE_RETURN(*mode != 0, EINVAL, nullptr); 33 34 // We deliberately don't hard-validate for empty strings here. All other 35 // invalid path strings are treated as runtime errors by the inner code 36 // in _open and openfile. This is also the appropriate treatment here. 37 // Since fopen is the primary access point for file strings it might be 38 // subjected to direct user input and thus must be robust to that rather 39 // than aborting. The CRT and OS do not provide any other path validator 40 // (because Win32 doesn't allow such things to exist in full generality). 41 _VALIDATE_RETURN_NOEXC(*file_name != 0, EINVAL, nullptr); 42 43 // Obtain a free stream. Note that the stream is returned locked: 44 __crt_stdio_stream stream = __acrt_stdio_allocate_stream(); 45 if (!stream.valid()) 46 { 47 errno = EMFILE; 48 return nullptr; 49 } 50 51 FILE* return_value = nullptr; 52 __try 53 { 54 return_value = stdio_traits::open_file(file_name, mode, share_flag, stream.public_stream()); 55 } 56 __finally 57 { 58 if (return_value == nullptr) 59 __acrt_stdio_free_stream(stream); 60 61 stream.unlock(); 62 } 63 __endtry 64 65 return return_value; 66 } 67 68 69 70 // A "secure" version of fsopen, which sets the result and returns zero on 71 // success and an error code on failure. 72 template <typename Character> 73 static errno_t __cdecl common_fopen_s( 74 FILE** const result, 75 Character const* const file_name, 76 Character const* const mode 77 ) throw() 78 { 79 _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL); 80 81 *result = common_fsopen(file_name, mode, _SH_SECURE); 82 if (*result == nullptr) 83 return errno; 84 85 return 0; 86 } 87 88 89 90 extern "C" FILE* __cdecl _fsopen( 91 char const* const file, 92 char const* const mode, 93 int const share_flag 94 ) 95 { 96 return common_fsopen(file, mode, share_flag); 97 } 98 99 extern "C" FILE* __cdecl fopen( 100 char const* const file, 101 char const* const mode 102 ) 103 { 104 return common_fsopen(file, mode, _SH_DENYNO); 105 } 106 107 extern "C" errno_t __cdecl fopen_s( 108 FILE** const result, 109 char const* const file, 110 char const* const mode 111 ) 112 { 113 return common_fopen_s(result, file, mode); 114 } 115 116 extern "C" FILE* __cdecl _wfsopen( 117 wchar_t const* const file, 118 wchar_t const* const mode, 119 int const share_flag 120 ) 121 { 122 return common_fsopen(file, mode, share_flag); 123 } 124 125 extern "C" FILE* __cdecl _wfopen( 126 wchar_t const* const file, 127 wchar_t const* const mode 128 ) 129 { 130 return common_fsopen(file, mode, _SH_DENYNO); 131 } 132 133 extern "C" errno_t __cdecl _wfopen_s( 134 FILE** const result, 135 wchar_t const* const file, 136 wchar_t const* const mode 137 ) 138 { 139 return common_fopen_s(result, file, mode); 140 } 141