blob: 8e8e47bbca93247742011ed68b3d73950d00fadf [file]
//
// 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