xref: /reactos/sdk/lib/ucrt/stdio/fopen.cpp (revision a6a07059)
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