| // |
| // Copyright (c) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
| // |
| |
| /*++ |
| |
| |
| |
| Module Name: |
| |
| misc/utils.c |
| |
| Abstract: |
| |
| Miscellaneous helper functions for the PAL, which don't fit anywhere else |
| |
| |
| |
| --*/ |
| |
| #include "pal/palinternal.h" |
| #if HAVE_VM_ALLOCATE |
| #include <mach/message.h> |
| #endif //HAVE_VM_ALLOCATE |
| |
| #include "pal/utils.h" |
| #include "pal/dbgmsg.h" |
| #include "pal/file.h" |
| |
| #include <errno.h> |
| #include <string.h> |
| |
| |
| SET_DEFAULT_DEBUG_CHANNEL(MISC); |
| |
| // In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable |
| // defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL. Therefore, the include statement |
| // should be placed after the SET_DEFAULT_DEBUG_CHANNEL(MISC) |
| #include <safemath.h> |
| |
| /*++ |
| Function: |
| UTIL_inverse_wcspbrk |
| |
| Opposite of wcspbrk : searches a string for the first character NOT in the |
| given set |
| |
| Parameters : |
| LPWSTR lpwstr : string to search |
| LPCWSTR charset : list of characters to search for |
| |
| Return value : |
| pointer to first character of lpwstr that isn't in the set |
| NULL if all characters are in the set |
| --*/ |
| LPWSTR UTIL_inverse_wcspbrk(LPWSTR lpwstr, LPCWSTR charset) |
| { |
| while(*lpwstr) |
| { |
| if(NULL == PAL_wcschr(charset,*lpwstr)) |
| { |
| return lpwstr; |
| } |
| lpwstr++; |
| } |
| return NULL; |
| } |
| |
| |
| /*++ |
| Function : |
| UTIL_IsReadOnlyBitsSet |
| |
| Takes a struct stat * |
| Returns true if the file is read only, |
| --*/ |
| BOOL UTIL_IsReadOnlyBitsSet( struct stat * stat_data ) |
| { |
| BOOL bRetVal = FALSE; |
| |
| /* Check for read permissions. */ |
| if ( stat_data->st_uid == geteuid() ) |
| { |
| /* The process owner is the file owner as well. */ |
| if ( ( stat_data->st_mode & S_IRUSR ) && !( stat_data->st_mode & S_IWUSR ) ) |
| { |
| bRetVal = TRUE; |
| } |
| } |
| else if ( stat_data->st_gid == getegid() ) |
| { |
| /* The process's owner is in the same group as the file's owner. */ |
| if ( ( stat_data->st_mode & S_IRGRP ) && !( stat_data->st_mode & S_IWGRP ) ) |
| { |
| bRetVal = TRUE; |
| } |
| } |
| else |
| { |
| /* Check the other bits to see who can access the file. */ |
| if ( ( stat_data->st_mode & S_IROTH ) && !( stat_data->st_mode & S_IWOTH ) ) |
| { |
| bRetVal = TRUE; |
| } |
| } |
| |
| return bRetVal; |
| } |
| |
| /*++ |
| Function : |
| UTIL_IsExecuteBitsSet |
| |
| Takes a struct stat * |
| Returns true if the file is executable, |
| --*/ |
| BOOL UTIL_IsExecuteBitsSet( struct stat * stat_data ) |
| { |
| BOOL bRetVal = FALSE; |
| |
| if ( (stat_data->st_mode & S_IFMT) == S_IFDIR ) |
| { |
| return FALSE; |
| } |
| |
| /* Check for read permissions. */ |
| if ( stat_data->st_uid == geteuid() ) |
| { |
| /* The process owner is the file owner as well. */ |
| if ( ( stat_data->st_mode & S_IXUSR ) ) |
| { |
| bRetVal = TRUE; |
| } |
| } |
| else if ( stat_data->st_gid == getegid() ) |
| { |
| /* The process's owner is in the same group as the file's owner. */ |
| if ( ( stat_data->st_mode & S_IXGRP ) ) |
| { |
| bRetVal = TRUE; |
| } |
| } |
| else |
| { |
| /* Check the other bits to see who can access the file. */ |
| if ( ( stat_data->st_mode & S_IXOTH ) ) |
| { |
| bRetVal = TRUE; |
| } |
| } |
| |
| return bRetVal; |
| } |
| |
| /*++ |
| Function : |
| UTIL_WCToMB_Alloc |
| |
| Converts a wide string to a multibyte string, allocating the required buffer |
| |
| Parameters : |
| LPCWSTR lpWideCharStr : string to convert |
| int cchWideChar : number of wide characters to convert |
| (-1 to convert a complete null-termnated string) |
| |
| Return Value : |
| newly allocated buffer containing the converted string. Conversion is |
| performed using CP_ACP. Buffer is allocated with malloc(), release it |
| with free(). |
| In case if failure, LastError will be set. |
| --*/ |
| LPSTR UTIL_WCToMB_Alloc(LPCWSTR lpWideCharStr, int cchWideChar) |
| { |
| int length; |
| LPSTR lpMultiByteStr; |
| |
| /* get required buffer length */ |
| length = WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, cchWideChar, |
| NULL, 0, NULL, NULL); |
| if(0 == length) |
| { |
| ERROR("WCToMB error; GetLastError returns %#x", GetLastError()); |
| return NULL; |
| } |
| |
| /* allocate required buffer */ |
| lpMultiByteStr = (LPSTR)PAL_malloc(length); |
| if(NULL == lpMultiByteStr) |
| { |
| ERROR("malloc() failed! errno is %d (%s)\n", errno,strerror(errno)); |
| SetLastError(ERROR_NOT_ENOUGH_MEMORY); |
| return NULL; |
| } |
| |
| /* convert into allocated buffer */ |
| length = WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, cchWideChar, |
| lpMultiByteStr, length, NULL, NULL); |
| if(0 == length) |
| { |
| ASSERT("WCToMB error; GetLastError returns %#x\n", GetLastError()); |
| PAL_free(lpMultiByteStr); |
| return NULL; |
| } |
| return lpMultiByteStr; |
| } |
| |
| /*++ |
| Function : |
| UTIL_MBToWC_Alloc |
| |
| Converts a multibyte string to a wide string, allocating the required buffer |
| |
| Parameters : |
| LPCSTR lpMultiByteStr : string to convert |
| int cbMultiByte : number of bytes to convert |
| (-1 to convert a complete null-termnated string) |
| |
| Return Value : |
| newly allocated buffer containing the converted string. Conversion is |
| performed using CP_ACP. Buffer is allocated with malloc(), release it |
| with free(). |
| In case if failure, LastError will be set. |
| --*/ |
| LPWSTR UTIL_MBToWC_Alloc(LPCSTR lpMultiByteStr, int cbMultiByte) |
| { |
| int length; |
| LPWSTR lpWideCharStr; |
| |
| /* get required buffer length */ |
| length = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, cbMultiByte, |
| NULL, 0); |
| if(0 == length) |
| { |
| ERROR("MBToWC error; GetLastError returns %#x", GetLastError()); |
| return NULL; |
| } |
| |
| if (length >= (INT_MAX / sizeof(WCHAR))) |
| { |
| ERROR("integer overflow! length = %d , sizeof(WCHAR) = (%d)\n", length,sizeof(WCHAR) ); |
| SetLastError(ERROR_ARITHMETIC_OVERFLOW); |
| return NULL; |
| } |
| |
| /* allocate required buffer */ |
| size_t fullsize = length * sizeof(WCHAR); |
| lpWideCharStr = (LPWSTR)PAL_malloc(fullsize); |
| if(NULL == lpWideCharStr) |
| { |
| ERROR("malloc() failed! errno is %d (%s)\n", errno,strerror(errno)); |
| SetLastError(FILEGetLastErrorFromErrno()); |
| return NULL; |
| } |
| |
| /* convert into allocated buffer */ |
| length = MultiByteToWideChar(CP_ACP, 0, lpMultiByteStr, cbMultiByte, |
| lpWideCharStr, length); |
| if(0 >= length) |
| { |
| ASSERT("MCToMB error; GetLastError returns %#x\n", GetLastError()); |
| PAL_free(lpWideCharStr); |
| return NULL; |
| } |
| return lpWideCharStr; |
| } |
| |
| #if HAVE_VM_ALLOCATE |
| /*++ |
| Function: |
| UTIL_MachErrorToPalError |
| |
| Maps a Mach kern_return_t to a Win32 error code. |
| --*/ |
| DWORD UTIL_MachErrorToPalError(kern_return_t MachReturn) |
| { |
| switch (MachReturn) |
| { |
| case KERN_SUCCESS: |
| return ERROR_SUCCESS; |
| |
| case KERN_NO_ACCESS: |
| case KERN_INVALID_CAPABILITY: |
| return ERROR_ACCESS_DENIED; |
| |
| case KERN_TERMINATED: |
| return ERROR_INVALID_HANDLE; |
| |
| case KERN_INVALID_ADDRESS: |
| return ERROR_INVALID_ADDRESS; |
| |
| case KERN_NO_SPACE: |
| return ERROR_NOT_ENOUGH_MEMORY; |
| |
| case KERN_INVALID_ARGUMENT: |
| return ERROR_INVALID_PARAMETER; |
| |
| default: |
| ASSERT("Unknown kern_return_t value %d - reporting ERROR_INTERNAL_ERROR\n", MachReturn); |
| return ERROR_INTERNAL_ERROR; |
| } |
| } |
| |
| /*++ |
| Function: |
| UTIL_SetLastErrorFromMach |
| |
| Sets Win32 LastError according to the argument Mach kern_return_t value, |
| provided it indicates an error. If the argument indicates success, does |
| not modify LastError. |
| --*/ |
| void UTIL_SetLastErrorFromMach(kern_return_t MachReturn) |
| { |
| DWORD palError = UTIL_MachErrorToPalError(MachReturn); |
| if (palError != ERROR_SUCCESS) |
| { |
| SetLastError(palError); |
| } |
| } |
| #endif //HAVE_VM_ALLOCATE |