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
9Module Name:
10
11 misc/utils.c
12
13Abstract:
14
15 Miscellaneous helper functions for the PAL, which don't fit anywhere else
16
17
18
19--*/
20
21#include "pal/dbgmsg.h"
22SET_DEFAULT_DEBUG_CHANNEL(MISC); // some headers have code with asserts, so do this first
23
24#include "pal/palinternal.h"
25#if HAVE_VM_ALLOCATE
26#include <mach/message.h>
27#endif //HAVE_VM_ALLOCATE
28
29#include "pal/utils.h"
30#include "pal/file.h"
31
32#include <errno.h>
33#include <string.h>
34
35
36// In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable
37// defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL. Therefore, the include statement
38// should be placed after the SET_DEFAULT_DEBUG_CHANNEL(MISC)
39#include <safemath.h>
40
41/*++
42Function:
43 UTIL_inverse_wcspbrk
44
45 Opposite of wcspbrk : searches a string for the first character NOT in the
46 given set
47
48Parameters :
49 LPWSTR lpwstr : string to search
50 LPCWSTR charset : list of characters to search for
51
52Return value :
53 pointer to first character of lpwstr that isn't in the set
54 NULL if all characters are in the set
55--*/
56LPWSTR UTIL_inverse_wcspbrk(LPWSTR lpwstr, LPCWSTR charset)
57{
58 while(*lpwstr)
59 {
60 if(NULL == PAL_wcschr(charset,*lpwstr))
61 {
62 return lpwstr;
63 }
64 lpwstr++;
65 }
66 return NULL;
67}
68
69
70/*++
71Function :
72 UTIL_IsReadOnlyBitsSet
73
74 Takes a struct stat *
75 Returns true if the file is read only,
76--*/
77BOOL UTIL_IsReadOnlyBitsSet( struct stat * stat_data )
78{
79 BOOL bRetVal = FALSE;
80
81 /* Check for read permissions. */
82 if ( stat_data->st_uid == geteuid() )
83 {
84 /* The process owner is the file owner as well. */
85 if ( ( stat_data->st_mode & S_IRUSR ) && !( stat_data->st_mode & S_IWUSR ) )
86 {
87 bRetVal = TRUE;
88 }
89 }
90 else if ( stat_data->st_gid == getegid() )
91 {
92 /* The process's owner is in the same group as the file's owner. */
93 if ( ( stat_data->st_mode & S_IRGRP ) && !( stat_data->st_mode & S_IWGRP ) )
94 {
95 bRetVal = TRUE;
96 }
97 }
98 else
99 {
100 /* Check the other bits to see who can access the file. */
101 if ( ( stat_data->st_mode & S_IROTH ) && !( stat_data->st_mode & S_IWOTH ) )
102 {
103 bRetVal = TRUE;
104 }
105 }
106
107 return bRetVal;
108}
109
110/*++
111Function :
112 UTIL_IsExecuteBitsSet
113
114 Takes a struct stat *
115 Returns true if the file is executable,
116--*/
117BOOL UTIL_IsExecuteBitsSet( struct stat * stat_data )
118{
119 BOOL bRetVal = FALSE;
120
121 if ( (stat_data->st_mode & S_IFMT) == S_IFDIR )
122 {
123 return FALSE;
124 }
125
126 /* Check for read permissions. */
127 if ( 0 == geteuid() )
128 {
129 /* The process owner is root */
130 bRetVal = TRUE;
131 }
132 else if ( stat_data->st_uid == geteuid() )
133 {
134 /* The process owner is the file owner as well. */
135 if ( ( stat_data->st_mode & S_IXUSR ) )
136 {
137 bRetVal = TRUE;
138 }
139 }
140 else if ( stat_data->st_gid == getegid() )
141 {
142 /* The process's owner is in the same group as the file's owner. */
143 if ( ( stat_data->st_mode & S_IXGRP ) )
144 {
145 bRetVal = TRUE;
146 }
147 }
148 else
149 {
150 /* Check the other bits to see who can access the file. */
151 if ( ( stat_data->st_mode & S_IXOTH ) )
152 {
153 bRetVal = TRUE;
154 }
155 }
156
157 return bRetVal;
158}
159
160/*++
161Function :
162 UTIL_WCToMB_Alloc
163
164 Converts a wide string to a multibyte string, allocating the required buffer
165
166Parameters :
167 LPCWSTR lpWideCharStr : string to convert
168 int cchWideChar : number of wide characters to convert
169 (-1 to convert a complete null-termnated string)
170
171Return Value :
172 newly allocated buffer containing the converted string. Conversion is
173 performed using CP_ACP. Buffer is allocated with malloc(), release it
174 with free().
175 In case if failure, LastError will be set.
176--*/
177LPSTR UTIL_WCToMB_Alloc(LPCWSTR lpWideCharStr, int cchWideChar)
178{
179 int length;
180 LPSTR lpMultiByteStr;
181
182 /* get required buffer length */
183 length = WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, cchWideChar,
184 NULL, 0, NULL, NULL);
185 if(0 == length)
186 {
187 ERROR("WCToMB error; GetLastError returns %#x", GetLastError());
188 return NULL;
189 }
190
191 /* allocate required buffer */
192 lpMultiByteStr = (LPSTR)PAL_malloc(length);
193 if(NULL == lpMultiByteStr)
194 {
195 ERROR("malloc() failed! errno is %d (%s)\n", errno,strerror(errno));
196 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
197 return NULL;
198 }
199
200 /* convert into allocated buffer */
201 length = WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, cchWideChar,
202 lpMultiByteStr, length, NULL, NULL);
203 if(0 == length)
204 {
205 ASSERT("WCToMB error; GetLastError returns %#x\n", GetLastError());
206 PAL_free(lpMultiByteStr);
207 return NULL;
208 }
209 return lpMultiByteStr;
210}
211
212/*++
213Function :
214 UTIL_MBToWC_Alloc
215
216 Converts a multibyte string to a wide string, allocating the required buffer
217
218Parameters :
219 LPCSTR lpMultiByteStr : string to convert
220 int cbMultiByte : number of bytes to convert
221 (-1 to convert a complete null-termnated string)
222
223Return Value :
224 newly allocated buffer containing the converted string. Conversion is
225 performed using CP_ACP. Buffer is allocated with malloc(), release it
226 with free().
227 In case if failure, LastError will be set.
228--*/
229LPWSTR UTIL_MBToWC_Alloc(LPCSTR lpMultiByteStr, int cbMultiByte)
230{
231 int length;
232 LPWSTR lpWideCharStr;
233
234 /* get required buffer length */
235 length = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, cbMultiByte,
236 NULL, 0);
237 if(0 == length)
238 {
239 ERROR("MBToWC error; GetLastError returns %#x", GetLastError());
240 return NULL;
241 }
242
243 /* allocate required buffer */
244 size_t fullsize;
245 if (!ClrSafeInt<size_t>::multiply(length,sizeof(WCHAR),fullsize))
246 {
247 ERROR("integer overflow! length = %d , sizeof(WCHAR) = (%d)\n", length,sizeof(WCHAR) );
248 SetLastError(ERROR_ARITHMETIC_OVERFLOW);
249 return NULL;
250 }
251
252 lpWideCharStr = (LPWSTR)PAL_malloc(fullsize);
253 if(NULL == lpWideCharStr)
254 {
255 ERROR("malloc() failed! errno is %d (%s)\n", errno,strerror(errno));
256 SetLastError(FILEGetLastErrorFromErrno());
257 return NULL;
258 }
259
260 /* convert into allocated buffer */
261 length = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, cbMultiByte,
262 lpWideCharStr, length);
263 if(0 >= length)
264 {
265 ASSERT("MCToMB error; GetLastError returns %#x\n", GetLastError());
266 PAL_free(lpWideCharStr);
267 return NULL;
268 }
269 return lpWideCharStr;
270}
271
272#if HAVE_VM_ALLOCATE
273/*++
274Function:
275 UTIL_MachErrorToPalError
276
277 Maps a Mach kern_return_t to a Win32 error code.
278--*/
279DWORD UTIL_MachErrorToPalError(kern_return_t MachReturn)
280{
281 switch (MachReturn)
282 {
283 case KERN_SUCCESS:
284 return ERROR_SUCCESS;
285
286 case KERN_NO_ACCESS:
287 case KERN_INVALID_CAPABILITY:
288 return ERROR_ACCESS_DENIED;
289
290 case KERN_TERMINATED:
291 return ERROR_INVALID_HANDLE;
292
293 case KERN_INVALID_ADDRESS:
294 return ERROR_INVALID_ADDRESS;
295
296 case KERN_NO_SPACE:
297 return ERROR_NOT_ENOUGH_MEMORY;
298
299 case KERN_INVALID_ARGUMENT:
300 return ERROR_INVALID_PARAMETER;
301
302 default:
303 ASSERT("Unknown kern_return_t value %d - reporting ERROR_INTERNAL_ERROR\n", MachReturn);
304 return ERROR_INTERNAL_ERROR;
305 }
306}
307
308/*++
309Function:
310 UTIL_SetLastErrorFromMach
311
312 Sets Win32 LastError according to the argument Mach kern_return_t value,
313 provided it indicates an error. If the argument indicates success, does
314 not modify LastError.
315--*/
316void UTIL_SetLastErrorFromMach(kern_return_t MachReturn)
317{
318 DWORD palError = UTIL_MachErrorToPalError(MachReturn);
319 if (palError != ERROR_SUCCESS)
320 {
321 SetLastError(palError);
322 }
323}
324#endif //HAVE_VM_ALLOCATE
325
326