static char* FindCgroupPath(bool (*is_subsystem)(const char *)){ char *cgroup_path = nullptr; char *hierarchy_mount = nullptr; char *hierarchy_root = nullptr; char *cgroup_path_relative_to_mount = nullptr; size_t len; FindHierarchyMount(is_subsystem, &hierarchy_mount, &hierarchy_root); if (hierarchy_mount == nullptr || hierarchy_root == nullptr) goto done; cgroup_path_relative_to_mount = FindCGroupPathForSubsystem(is_subsystem); if (cgroup_path_relative_to_mount == nullptr) goto done; len = strlen(hierarchy_mount); len += strlen(cgroup_path_relative_to_mount); cgroup_path = (char*)PAL_malloc(len+1); if (cgroup_path == nullptr) goto done; strcpy_s(cgroup_path, len+1, hierarchy_mount); // For a host cgroup, we need to append the relative path. // In a docker container, the root and relative path are the same and we don't need to append. if (strcmp(hierarchy_root, cgroup_path_relative_to_mount) != 0) strcat_s(cgroup_path, len+1, cgroup_path_relative_to_mount); done: PAL_free(hierarchy_mount); PAL_free(hierarchy_root); PAL_free(cgroup_path_relative_to_mount); return cgroup_path; }
__cdecl _fdopen( int handle, const char *mode) { PAL_FILE *f = NULL; LPSTR supported = NULL; BOOL bTextMode = TRUE; PERF_ENTRY(_fdopen); ENTRY("_fdopen (handle=%d mode=%p (%s))\n", handle, mode, mode); _ASSERTE(mode != NULL); f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); if ( f ) { supported = MapFileOpenModes( (char*)mode , &bTextMode); if ( !supported ) { PAL_free(f); f = NULL; goto EXIT; } f->bsdFilePtr = (FILE *)fdopen( handle, supported ); f->PALferrorCode = PAL_FILE_NOERROR; /* Make sure fdopen did not fail. */ if ( !f->bsdFilePtr ) { PAL_free( f ); f = NULL; } PAL_free( supported ); supported = NULL; } else { ERROR( "Unable to allocate memory for the PAL_FILE wrapper!\n" ); } EXIT: LOGEXIT( "_fdopen returns FILE* %p\n", f ); PERF_EXIT(_fdopen); return f; }
/*++ Function: GetCurrentDirectoryW See MSDN doc. --*/ DWORD PALAPI GetCurrentDirectoryW( IN DWORD nBufferLength, OUT LPWSTR lpBuffer) { DWORD dwWideLen = 0; DWORD dwLastError = 0; char *current_dir; int dir_len; PERF_ENTRY(GetCurrentDirectoryW); ENTRY("GetCurrentDirectoryW(nBufferLength=%u, lpBuffer=%p)\n", nBufferLength, lpBuffer); current_dir = PAL__getcwd( NULL, MAX_LONGPATH + 1 ); if ( !current_dir ) { WARN( "PAL__getcwd returned NULL\n" ); dwLastError = DIRGetLastErrorFromErrno(); goto done; } dir_len = strlen( current_dir ); dwWideLen = MultiByteToWideChar( CP_ACP, 0, current_dir, dir_len, NULL, 0 ); /* if the supplied buffer isn't long enough, return the required length, including room for the NULL terminator */ if ( nBufferLength > dwWideLen ) { if(!MultiByteToWideChar( CP_ACP, 0, current_dir, dir_len + 1, lpBuffer, nBufferLength )) { ASSERT("MultiByteToWideChar failure!\n"); dwWideLen = 0; dwLastError = ERROR_INTERNAL_ERROR; } } else { ++dwWideLen; /* include space for the NULL */ } done: PAL_free( current_dir ); if ( dwLastError ) { SetLastError(dwLastError); } LOGEXIT("GetCurrentDirectoryW returns DWORD %u\n", dwWideLen); PERF_EXIT(GetCurrentDirectoryW); return dwWideLen; }
void DeleteBuffer() { if (m_innerBuffer != m_buffer) PAL_free(m_buffer); m_buffer = NULL; return; }
/*++ Function: TIMECleanUpTransitionDates Free the memory allocated in TIMEGetStdDstDates. --*/ void TIMECleanUpTransitionDates() { if (glob_trans_dates) { PAL_free(glob_trans_dates); glob_trans_dates = 0; } }
/*++ Function: CreateDirectoryW Note: lpSecurityAttributes always NULL. See MSDN doc. --*/ BOOL PALAPI CreateDirectoryW( IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) { BOOL bRet = FALSE; DWORD dwLastError = 0; int mb_size; char *mb_dir = NULL; PERF_ENTRY(CreateDirectoryW); ENTRY("CreateDirectoryW(lpPathName=%p (%S), lpSecurityAttr=%p)\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING, lpSecurityAttributes); if ( lpSecurityAttributes ) { ASSERT("lpSecurityAttributes is not NULL as it should be\n"); dwLastError = ERROR_INVALID_PARAMETER; goto done; } /* translate the wide char lpPathName string to multibyte string */ if(0 == (mb_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, NULL, 0, NULL, NULL ))) { ASSERT("WideCharToMultiByte failure! error is %d\n", GetLastError()); dwLastError = ERROR_INTERNAL_ERROR; goto done; } if (((mb_dir = (char *)PAL_malloc(mb_size)) == NULL) || (WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, mb_dir, mb_size, NULL, NULL) != mb_size)) { ASSERT("WideCharToMultiByte or PAL_malloc failure! LastError:%d errno:%d\n", GetLastError(), errno); dwLastError = ERROR_INTERNAL_ERROR; goto done; } bRet = CreateDirectoryA(mb_dir,NULL); done: if( dwLastError ) { SetLastError( dwLastError ); } if (mb_dir != NULL) { PAL_free(mb_dir); } LOGEXIT("CreateDirectoryW returns BOOL %d\n", bRet); PERF_EXIT(CreateDirectoryW); return bRet; }
/*-- Function: _wtoi See MSDN doc --*/ int __cdecl _wtoi( const wchar_16 *string) { int len; int ret; char *tempStr; PERF_ENTRY(_wtoi); ENTRY("_wtoi (string=%p)\n", string); len = WideCharToMultiByte(CP_ACP, 0, string, -1, 0, 0, 0, 0); if (!len) { ASSERT("WideCharToMultiByte failed. Error is %d\n", GetLastError()); return -1; } tempStr = (char *) PAL_malloc(len); if (!tempStr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return -1; } len = WideCharToMultiByte(CP_ACP, 0, string, -1, tempStr, len, 0, 0); if (!len) { ASSERT("WideCharToMultiByte failed. Error is %d\n", GetLastError()); PAL_free(tempStr); return -1; } ret = atoi(tempStr); PAL_free(tempStr); LOGEXIT("_wtoi returns int %d\n", ret); PERF_EXIT(_wtoi); return ret; }
/*++ Function: GetCurrentDirectoryA See MSDN doc. --*/ DWORD PALAPI GetCurrentDirectoryA( IN DWORD nBufferLength, OUT LPSTR lpBuffer) { DWORD dwDirLen = 0; DWORD dwLastError = 0; char *current_dir; PERF_ENTRY(GetCurrentDirectoryA); ENTRY("GetCurrentDirectoryA(nBufferLength=%u, lpBuffer=%p)\n", nBufferLength, lpBuffer); /* NULL first arg means getcwd will allocate the string */ current_dir = PAL__getcwd( NULL, MAX_LONGPATH + 1 ); if ( !current_dir ) { WARN( "PAL__getcwd returned NULL\n" ); dwLastError = DIRGetLastErrorFromErrno(); goto done; } dwDirLen = strlen( current_dir ); /* if the supplied buffer isn't long enough, return the required length, including room for the NULL terminator */ if ( nBufferLength <= dwDirLen ) { ++dwDirLen; /* include space for the NULL */ goto done; } else { strcpy_s( lpBuffer, nBufferLength, current_dir ); } done: PAL_free( current_dir ); if ( dwLastError ) { SetLastError(dwLastError); } LOGEXIT("GetCurrentDirectoryA returns DWORD %u\n", dwDirLen); PERF_EXIT(GetCurrentDirectoryA); return dwDirLen; }
/*++ Function: GetCurrentDirectoryA --*/ DWORD GetCurrentDirectoryA(PathCharString& lpBuffer) { DWORD dwDirLen = 0; DWORD dwLastError = 0; char *current_dir; PERF_ENTRY(GetCurrentDirectoryA); ENTRY("GetCurrentDirectoryA(lpBuffer=%p)\n", lpBuffer.GetString()); current_dir = lpBuffer.OpenStringBuffer(MAX_PATH); /* NULL first arg means getcwd will allocate the string */ current_dir = PAL__getcwd( current_dir, MAX_PATH); if (current_dir != NULL ) { dwDirLen = strlen( current_dir ); lpBuffer.CloseBuffer(dwDirLen); goto done; } else if ( errno == ERANGE ) { lpBuffer.CloseBuffer(0); current_dir = PAL__getcwd( NULL, 0); } if ( !current_dir ) { WARN("Getcwd failed with errno=%d [%s]\n", errno, strerror(errno)); dwLastError = DIRGetLastErrorFromErrno(); dwDirLen = 0; goto done; } dwDirLen = strlen( current_dir ); lpBuffer.Set(current_dir, dwDirLen); PAL_free(current_dir); done: if ( dwLastError ) { SetLastError(dwLastError); } LOGEXIT("GetCurrentDirectoryA returns DWORD %u\n", dwDirLen); PERF_EXIT(GetCurrentDirectoryA); return dwDirLen; }
/*++ Function : fclose See MSDN for more details. --*/ int _cdecl PAL_fclose(PAL_FILE * f) { INT nRetVal = 0; PERF_ENTRY(fclose); ENTRY( "fclose( f=%p )\n", f ); _ASSERTE(f != NULL); CLEARERR(f); nRetVal = fclose( f->bsdFilePtr ); PAL_free( f ); LOGEXIT( "fclose returning %d\n", nRetVal ); PERF_EXIT(fclose); return nRetVal; }
static bool GetPhysicalMemoryLimit(size_t *val) { char *mem_limit_filename = nullptr; bool result = false; if (s_memory_cgroup_path == nullptr) return result; size_t len = strlen(s_memory_cgroup_path); len += strlen(MEM_LIMIT_FILENAME); mem_limit_filename = (char*)PAL_malloc(len+1); if (mem_limit_filename == nullptr) return result; strcpy_s(mem_limit_filename, len+1, s_memory_cgroup_path); strcat_s(mem_limit_filename, len+1, MEM_LIMIT_FILENAME); result = ReadMemoryValueFromFile(mem_limit_filename, val); PAL_free(mem_limit_filename); return result; }
static long long ReadCpuCGroupValue(const char* subsystemFilename){ char *filename = nullptr; bool result = false; long long val; size_t len; if (s_cpu_cgroup_path == nullptr) return -1; len = strlen(s_cpu_cgroup_path); len += strlen(subsystemFilename); filename = (char*)PAL_malloc(len + 1); if (filename == nullptr) return -1; strcpy_s(filename, len+1, s_cpu_cgroup_path); strcat_s(filename, len+1, subsystemFilename); result = ReadLongLongValueFromFile(filename, &val); PAL_free(filename); if (!result) return -1; return val; }
/* The use of LONG is by design, to ensure that a 32 bit value is always returned from this function. If "long" is used instead of LONG, then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus breaking Windows behavior. */ LONG __cdecl PAL_wcstol( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstol); ENTRY("wcstol (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstolExit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL_wcstolExit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if( size==0 ) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstolExit; } res = strtol(s_nptr, &s_endptr, base); #ifdef BIT64 if (res > _I32_MAX) { res = _I32_MAX; errno = ERANGE; } else if (res < _I32_MIN) { res = _I32_MIN; errno = ERANGE; } #endif /* only ASCII characters will be accepted by strtol, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL_wcstolExit: PAL_free(s_nptr); LOGEXIT("wcstol returning long %ld\n", res); PERF_EXIT(wcstol); /* This explicit cast to LONG is used to silence any potential warnings due to implicitly casting the native long res to LONG when returning. */ return (LONG)res; }
static void FindHierarchyMount(bool (*is_subsystem)(const char *), char** pmountpath, char** pmountroot) { char *line = nullptr; size_t lineLen = 0, maxLineLen = 0; char *filesystemType = nullptr; char *options = nullptr; char *mountpath = nullptr; char *mountroot = nullptr; FILE *mountinfofile = fopen(PROC_MOUNTINFO_FILENAME, "r"); if (mountinfofile == nullptr) goto done; while (getline(&line, &lineLen, mountinfofile) != -1) { if (filesystemType == nullptr || lineLen > maxLineLen) { PAL_free(filesystemType); PAL_free(options); filesystemType = (char*)PAL_malloc(lineLen+1); if (filesystemType == nullptr) goto done; options = (char*)PAL_malloc(lineLen+1); if (options == nullptr) goto done; maxLineLen = lineLen; } char* separatorChar = strstr(line, " - ");; // See man page of proc to get format for /proc/self/mountinfo file int sscanfRet = sscanf_s(separatorChar, " - %s %*s %s", filesystemType, lineLen+1, options, lineLen+1); if (sscanfRet != 2) { _ASSERTE(!"Failed to parse mount info file contents with sscanf_s."); goto done; } if (strncmp(filesystemType, "cgroup", 6) == 0) { char* context = nullptr; char* strTok = strtok_s(options, ",", &context); while (strTok != nullptr) { if (is_subsystem(strTok)) { mountpath = (char*)PAL_malloc(lineLen+1); if (mountpath == nullptr) goto done; mountroot = (char*)PAL_malloc(lineLen+1); if (mountroot == nullptr) goto done; sscanfRet = sscanf_s(line, "%*s %*s %*s %s %s ", mountroot, lineLen+1, mountpath, lineLen+1); if (sscanfRet != 2) _ASSERTE(!"Failed to parse mount info file contents with sscanf_s."); // assign the output arguments and clear the locals so we don't free them. *pmountpath = mountpath; *pmountroot = mountroot; mountpath = mountroot = nullptr; goto done; } strTok = strtok_s(nullptr, ",", &context); } } } done: PAL_free(mountpath); PAL_free(mountroot); PAL_free(filesystemType); PAL_free(options); free(line); if (mountinfofile) fclose(mountinfofile); }
/*++ Function : wcstod There is a slight difference between the Windows version of wcstod and the BSD versio of wcstod. Under Windows the string " -1b " returns -1.000000 stop char = 'b' Under BSD the same string returns 0.000000 stop ' ' see msdn doc. --*/ double __cdecl PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) { double RetVal = 0.0; LPSTR lpStringRep = NULL; LPWSTR lpStartOfExpression = (LPWSTR)nptr; LPWSTR lpEndOfExpression = NULL; UINT Length = 0; PERF_ENTRY(wcstod); ENTRY( "wcstod( %p (%S), %p (%S) )\n", nptr, nptr, endptr , endptr ); THREADMarkDiagnostic("PAL_wcstod -> strtod"); if ( !nptr ) { ERROR( "nptr is invalid.\n" ); LOGEXIT( "wcstod returning 0.0\n" ); PERF_EXIT(wcstod); return 0.0; } /* Eat white space. */ while ( PAL_iswspace( *lpStartOfExpression ) ) { lpStartOfExpression++; } /* Get the end of the expression. */ lpEndOfExpression = lpStartOfExpression; while ( *lpEndOfExpression ) { if ( !MISC_CRT_WCSTOD_IsValidCharacter( *lpEndOfExpression ) ) { break; } lpEndOfExpression++; } if ( lpEndOfExpression != lpStartOfExpression ) { Length = lpEndOfExpression - lpStartOfExpression; lpStringRep = (LPSTR)PAL_malloc( Length + 1); if ( lpStringRep ) { if ( WideCharToMultiByte( CP_ACP, 0, lpStartOfExpression, Length, lpStringRep, Length + 1 , NULL, 0 ) != 0 ) { LPSTR ScanStop = NULL; lpStringRep[Length]= 0; RetVal = strtod( lpStringRep, &ScanStop ); /* See if strtod failed. */ if ( RetVal == 0.0 && ScanStop == lpStringRep ) { ASSERT( "An error occured in the conversion.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ASSERT( "Wide char to multibyte conversion failed.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ERROR( "Not enough memory.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ERROR( "Malformed expression.\n" ); lpEndOfExpression = (LPWSTR)nptr; } /* Set the stop scan character. */ if ( endptr != NULL ) { *endptr = lpEndOfExpression; } PAL_free( lpStringRep ); LOGEXIT( "wcstod returning %f.\n", RetVal ); PERF_EXIT(wcstod); return RetVal; }
/*++ Function: SetCurrentDirectoryA See MSDN doc. --*/ BOOL PALAPI SetCurrentDirectoryA( IN LPCSTR lpPathName) { BOOL bRet = FALSE; DWORD dwLastError = 0; int result; LPSTR UnixPathName = NULL; PERF_ENTRY(SetCurrentDirectoryA); ENTRY("SetCurrentDirectoryA(lpPathName=%p (%s))\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL"); /*check if the given path is null. If so return FALSE*/ if (lpPathName == NULL ) { ERROR("Invalid path/directory name\n"); dwLastError = ERROR_INVALID_NAME; goto done; } if (strlen(lpPathName) >= MAX_LONGPATH) { WARN("Path/directory name longer than MAX_LONGPATH characters\n"); dwLastError = ERROR_FILENAME_EXCED_RANGE; goto done; } UnixPathName = PAL__strdup(lpPathName); if (UnixPathName == NULL ) { ERROR("PAL__strdup() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( UnixPathName ); TRACE("Attempting to open Unix dir [%s]\n", UnixPathName); result = chdir(UnixPathName); if ( result == 0 ) { bRet = TRUE; } else { if ( errno == ENOTDIR || errno == ENOENT ) { struct stat stat_data; if ( stat( UnixPathName, &stat_data) == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ dwLastError = ERROR_DIRECTORY; } else { FILEGetProperNotFoundError( UnixPathName, &dwLastError ); } TRACE("chdir() failed, path was invalid.\n"); } else { dwLastError = ERROR_ACCESS_DENIED; ERROR("chdir() failed; errno is %d (%s)\n", errno, strerror(errno)); } } done: if( dwLastError ) { SetLastError(dwLastError); } if(UnixPathName != NULL) { PAL_free( UnixPathName ); } LOGEXIT("SetCurrentDirectoryA returns BOOL %d\n", bRet); PERF_EXIT(SetCurrentDirectoryA); return bRet; }
/*++ Function: CreateDirectoryA Note: lpSecurityAttributes always NULL. See MSDN doc. --*/ BOOL PALAPI CreateDirectoryA( IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) { BOOL bRet = FALSE; DWORD dwLastError = 0; char *realPath; LPSTR UnixPathName = NULL; int pathLength; int i; const int mode = S_IRWXU | S_IRWXG | S_IRWXO; PERF_ENTRY(CreateDirectoryA); ENTRY("CreateDirectoryA(lpPathName=%p (%s), lpSecurityAttr=%p)\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL", lpSecurityAttributes); if ( lpSecurityAttributes ) { ASSERT("lpSecurityAttributes is not NULL as it should be\n"); dwLastError = ERROR_INVALID_PARAMETER; goto done; } // Windows returns ERROR_PATH_NOT_FOUND when called with NULL. // If we don't have this check, strdup(NULL) segfaults. if (lpPathName == NULL) { ERROR("CreateDirectoryA called with NULL pathname!\n"); dwLastError = ERROR_PATH_NOT_FOUND; goto done; } UnixPathName = PAL__strdup(lpPathName); if (UnixPathName == NULL ) { ERROR("PAL__strdup() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( UnixPathName ); // Remove any trailing slashes at the end because mkdir might not // handle them appropriately on all platforms. pathLength = strlen(UnixPathName); i = pathLength; while(i > 1) { if(UnixPathName[i - 1] =='/') { UnixPathName[i - 1]='\0'; i--; } else { break; } } // Check the constraint for the real path length (should be < MAX_LONGPATH). // Get an absolute path. if (UnixPathName[0] == '/') { realPath = UnixPathName; } else { const char *cwd = PAL__getcwd(NULL, MAX_LONGPATH); if (NULL == cwd) { WARN("Getcwd failed with errno=%d [%s]\n", errno, strerror(errno)); dwLastError = DIRGetLastErrorFromErrno(); goto done; } // Copy cwd, '/', path int iLen = strlen(cwd) + 1 + pathLength + 1; realPath = static_cast<char *>(alloca(iLen)); sprintf_s(realPath, iLen, "%s/%s", cwd, UnixPathName); PAL_free((char *)cwd); } // Canonicalize the path so we can determine its length. FILECanonicalizePath(realPath); if (strlen(realPath) >= MAX_LONGPATH) { WARN("UnixPathName is larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH); dwLastError = ERROR_FILENAME_EXCED_RANGE; goto done; } if ( mkdir(realPath, mode) != 0 ) { TRACE("Creation of directory [%s] was unsuccessful, errno = %d.\n", UnixPathName, errno); switch( errno ) { case ENOTDIR: /* FALL THROUGH */ case ENOENT: FILEGetProperNotFoundError( realPath, &dwLastError ); goto done; case EEXIST: dwLastError = ERROR_ALREADY_EXISTS; break; default: dwLastError = ERROR_ACCESS_DENIED; } } else { TRACE("Creation of directory [%s] was successful.\n", UnixPathName); bRet = TRUE; } done: if( dwLastError ) { SetLastError( dwLastError ); } PAL_free( UnixPathName ); LOGEXIT("CreateDirectoryA returns BOOL %d\n", bRet); PERF_EXIT(CreateDirectoryA); return bRet; }
static char* FindCGroupPathForSubsystem(bool (*is_subsystem)(const char *)) { char *line = nullptr; size_t lineLen = 0; size_t maxLineLen = 0; char *subsystem_list = nullptr; char *cgroup_path = nullptr; bool result = false; FILE *cgroupfile = fopen(PROC_CGROUP_FILENAME, "r"); if (cgroupfile == nullptr) goto done; while (!result && getline(&line, &lineLen, cgroupfile) != -1) { if (subsystem_list == nullptr || lineLen > maxLineLen) { PAL_free(subsystem_list); PAL_free(cgroup_path); subsystem_list = (char*)PAL_malloc(lineLen+1); if (subsystem_list == nullptr) goto done; cgroup_path = (char*)PAL_malloc(lineLen+1); if (cgroup_path == nullptr) goto done; maxLineLen = lineLen; } // See man page of proc to get format for /proc/self/cgroup file int sscanfRet = sscanf_s(line, "%*[^:]:%[^:]:%s", subsystem_list, lineLen+1, cgroup_path, lineLen+1); if (sscanfRet != 2) { _ASSERTE(!"Failed to parse cgroup info file contents with sscanf_s."); goto done; } char* context = nullptr; char* strTok = strtok_s(subsystem_list, ",", &context); while (strTok != nullptr) { if (is_subsystem(strTok)) { result = true; break; } strTok = strtok_s(nullptr, ",", &context); } } done: PAL_free(subsystem_list); if (!result) { PAL_free(cgroup_path); cgroup_path = nullptr; } free(line); if (cgroupfile) fclose(cgroupfile); return cgroup_path; }
__cdecl PAL_fopen(const char * fileName, const char * mode) { PAL_FILE *f = NULL; LPSTR supported = NULL; LPSTR UnixFileName = NULL; struct stat stat_data; BOOL bTextMode = TRUE; PERF_ENTRY(fopen); ENTRY("fopen ( fileName=%p (%s) mode=%p (%s))\n", fileName, fileName, mode , mode ); _ASSERTE(fileName != NULL); _ASSERTE(mode != NULL); if ( *mode == 'r' || *mode == 'w' || *mode == 'a' ) { supported = MapFileOpenModes( (char*)mode,&bTextMode); if ( !supported ) { goto done; } UnixFileName = PAL__strdup(fileName); if (UnixFileName == NULL ) { ERROR("PAL__strdup() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } FILEDosToUnixPathA( UnixFileName ); /*I am not checking for the case where stat fails *as fopen will handle the error more gracefully in case *UnixFileName is invalid*/ if ((stat(UnixFileName, &stat_data) == 0 ) && ((stat_data.st_mode & S_IFMT) == S_IFDIR)) { goto done; } f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); if ( f ) { f->bsdFilePtr = (FILE*)fopen( UnixFileName, supported ); f->PALferrorCode = PAL_FILE_NOERROR; f->bTextMode = bTextMode; if ( !f->bsdFilePtr ) { /* Failed */ PAL_free( f ); f = NULL; } #if UNGETC_NOT_RETURN_EOF else { f->bWriteOnlyMode = WriteOnlyMode(f->bsdFilePtr); } #endif //UNGETC_NOT_RETURN_EOF } else { ERROR( "Unable to allocate memory to the PAL_FILE wrapper\n" ); } } else { ERROR( "The mode flags must start with either an a, w, or r.\n" ); } done: PAL_free( supported ); supported = NULL; PAL_free( UnixFileName ); LOGEXIT( "fopen returns FILE* %p\n", f ); PERF_EXIT(fopen); return f; }
static void Cleanup() { PAL_free(s_memory_cgroup_path); PAL_free(s_cpu_cgroup_path); }
/*++ Function: FormatMessageW See MSDN doc. --*/ DWORD PALAPI FormatMessageW( IN DWORD dwFlags, IN LPCVOID lpSource, IN DWORD dwMessageId, IN DWORD dwLanguageId, OUT LPWSTR lpBuffer, IN DWORD nSize, IN va_list *Arguments) { BOOL bIgnoreInserts = FALSE; BOOL bIsVaList = TRUE; BOOL bIsLocalAlloced = FALSE; LPWSTR lpSourceString = NULL; UINT nCount = 0; LPWSTR lpReturnString = NULL; LPWSTR lpWorkingString = NULL; PERF_ENTRY(FormatMessageW); ENTRY( "FormatMessageW(dwFlags=%#x, lpSource=%p, dwMessageId=%#x, " "dwLanguageId=%#x, lpBuffer=%p, nSize=%u, va_list=%p)\n", dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments); /* Sanity checks. */ if ( dwFlags & FORMAT_MESSAGE_FROM_STRING && !lpSource ) { /* This behavior is different then in Windows. Windows would just crash.*/ ERROR( "lpSource cannot be NULL.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( !(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) && !lpBuffer ) { /* This behavior is different then in Windows. Windows would just crash.*/ ERROR( "lpBuffer cannot be NULL, if " " FORMAT_MESSAGE_ALLOCATE_BUFFER is not specified.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) ) { ERROR( "These flags cannot co-exist. You can either " "specify FORMAT_MESSAGE_FROM_STRING, or " "FORMAT_MESSAGE_FROM_SYSTEM.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( !( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && ( dwLanguageId != 0 #if ENABLE_DOWNLEVEL_FOR_NLS && dwLanguageId != MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) #endif ) ) { ERROR( "Invalid language indentifier.\n" ); SetLastError( ERROR_RESOURCE_LANG_NOT_FOUND ); goto exit; } /* Parameter processing. */ if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) { TRACE( "Allocated %d TCHARs. Don't forget to call LocalFree to " "free the memory when done.\n", nSize ); bIsLocalAlloced = TRUE; } if ( dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS ) { bIgnoreInserts = TRUE; } if ( dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY ) { if ( !Arguments && !bIgnoreInserts ) { ERROR( "The va_list cannot be NULL.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } else { bIsVaList = FALSE; } } if ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) { lpSourceString = (LPWSTR)lpSource; } else if ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) { if ((dwMessageId & 0xFFFF0000) == 0x80070000) { // This message has been produced by HRESULT_FROM_WIN32. Undo its work. dwMessageId &= 0xFFFF; } lpWorkingString = lpReturnString = FMTMSG_GetMessageString( dwMessageId ); if ( !lpWorkingString ) { ERROR( "Unable to find the message %d.\n", dwMessageId ); SetLastError( ERROR_INTERNAL_ERROR ); nCount = 0; goto exit; } nCount = PAL_wcslen( lpWorkingString ); if ( !bIsLocalAlloced && nCount > nSize ) { ERROR( "Insufficient buffer.\n" ); SetLastError( ERROR_INSUFFICIENT_BUFFER ); lpWorkingString = NULL; nCount = 0; goto exit; } if ( !lpWorkingString ) { ERROR( "Invalid error indentifier.\n" ); SetLastError( ERROR_INVALID_ADDRESS ); } goto exit; } else { ERROR( "Unknown flag.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( nSize == 0 && bIsLocalAlloced ) { nSize = 1; } lpWorkingString = static_cast<WCHAR *>( LocalAlloc( LMEM_FIXED, nSize * sizeof( WCHAR ) ) ); if ( !lpWorkingString ) { ERROR( "Unable to allocate memory for the working string.\n" ); SetLastError( ERROR_INSUFFICIENT_BUFFER ); goto exit; } /* Process the string. */ lpReturnString = lpWorkingString; while ( *lpSourceString ) { if ( *lpSourceString == '%' && !bIgnoreInserts ) { lpSourceString++; /* Escape sequences. */ if ( *lpSourceString == '0' ) { /* Terminates a message without a newline character. */ *lpWorkingString = '\0'; goto exit; } else if ( PAL_iswdigit( *lpSourceString ) ) { /* Get the insert number. */ WCHAR Number[] = { '\0', '\0', '\0' }; SIZE_T Index = 0; Number[ 0 ] = *lpSourceString; lpSourceString++; if ( PAL_iswdigit( *lpSourceString ) ) { Number[ 1 ] = *lpSourceString; lpSourceString++; if ( PAL_iswdigit( *lpSourceString ) ) { ERROR( "Invalid insert indentifier.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } } Index = FMTMSG__watoi( Number ); if ( Index == 0 ) { ERROR( "Invalid insert indentifier.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } if ( *lpSourceString == '!' ) { LPWSTR lpInsertString = NULL; LPWSTR lpPrintfString = NULL; LPWSTR lpStartOfFormattedString = NULL; UINT nPrintfLength = 0; LPWSTR lpFormattedString = NULL; UINT nFormattedLength = 0; if ( !bIsVaList ) { lpInsertString = (LPWSTR)Arguments[ Index - 1 ]; } else { va_list TheArgs; va_copy(TheArgs, *Arguments); UINT i = 0; for ( ; i < Index; i++ ) { lpInsertString = va_arg( TheArgs, LPWSTR ); } } /* Calculate the length, and extract the printf string.*/ lpSourceString++; { LPWSTR p = PAL_wcschr( lpSourceString, '!' ); if ( NULL == p ) { nPrintfLength = 0; } else { nPrintfLength = p - lpSourceString; } } lpPrintfString = (LPWSTR)PAL_malloc( ( nPrintfLength + 1 ) * sizeof( WCHAR ) ); if ( !lpPrintfString ) { ERROR( "Unable to allocate memory.\n" ); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); lpWorkingString = NULL; nCount = 0; goto exit; } PAL_wcsncpy( lpPrintfString, lpSourceString, nPrintfLength ); *( lpPrintfString + nPrintfLength ) = '\0'; lpStartOfFormattedString = lpFormattedString = FMTMSG_ProcessPrintf( *lpPrintfString, lpPrintfString, lpInsertString); if ( !lpFormattedString ) { ERROR( "Unable to process the format string.\n" ); /* Function will set the error code. */ PAL_free( lpPrintfString ); lpWorkingString = NULL; goto exit; } nFormattedLength = PAL_wcslen( lpFormattedString ); /* Append the processed printf string into the working string */ while ( *lpFormattedString ) { _CHECKED_ADD_TO_STRING( *lpFormattedString ); lpFormattedString++; } lpSourceString += nPrintfLength + 1; PAL_free( lpPrintfString ); PAL_free( lpStartOfFormattedString ); lpPrintfString = lpFormattedString = NULL; } else { /* The printf format string defaults to 's'.*/ LPWSTR lpInsert = NULL; if ( !bIsVaList ) { lpInsert = (LPWSTR)Arguments[ Index - 1 ]; } else { va_list TheArgs; va_copy(TheArgs, *Arguments); UINT i = 0; for ( ; i < Index; i++ ) { lpInsert = va_arg( TheArgs, LPWSTR ); } } while ( *lpInsert ) { _CHECKED_ADD_TO_STRING( *lpInsert ); lpInsert++; } } } /* Format specifiers. */ else if ( *lpSourceString == '%' ) { _CHECKED_ADD_TO_STRING( '%' ); lpSourceString++; } else if ( *lpSourceString == 'n' ) { /* Hard line break. */ _CHECKED_ADD_TO_STRING( '\n' ); lpSourceString++; } else if ( *lpSourceString == '.' ) { _CHECKED_ADD_TO_STRING( '.' ); lpSourceString++; } else if ( *lpSourceString == '!' ) { _CHECKED_ADD_TO_STRING( '!' ); lpSourceString++; } else if ( !*lpSourceString ) { ERROR( "Invalid parameter.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } else /* Append the character. */ { _CHECKED_ADD_TO_STRING( *lpSourceString ); lpSourceString++; } }/* END if ( *lpSourceString == '%' ) */ else { /* In Windows if FormatMessage is called with ignore inserts, then FormatMessage strips %1!s! down to %1, since string is the default. */ if ( bIgnoreInserts && *lpSourceString == '!' && *( lpSourceString + 1 ) == 's' ) { LPWSTR lpLastBang = PAL_wcschr( lpSourceString + 1, '!' ); if ( lpLastBang && ( 2 == lpLastBang - lpSourceString ) ) { lpSourceString = lpLastBang + 1; } else { ERROR( "Mal-formed string\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } } else { /* Append to the string. */ _CHECKED_ADD_TO_STRING( *lpSourceString ); lpSourceString++; } } } /* Terminate the message. */ _CHECKED_ADD_TO_STRING( '\0' ); /* NULL does not count. */ nCount--; exit: /* Function clean-up and exit. */ if ( lpWorkingString ) { if ( bIsLocalAlloced ) { TRACE( "Assigning the buffer to the pointer.\n" ); // when FORMAT_MESSAGE_ALLOCATE_BUFFER is specified, nSize // does not specify the size of lpBuffer, rather it specifies // the minimum size of the string // as such we have to blindly assume that lpBuffer has enough space to // store PVOID // might cause a prefast warning, but there is no good way to suppress it yet _ASSERTE(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER); *((LPVOID*)lpBuffer) = (LPVOID)lpReturnString; } else /* Only delete lpReturnString if the caller has their own buffer.*/ { TRACE( "Copying the string into the buffer.\n" ); PAL_wcsncpy( lpBuffer, lpReturnString, nCount + 1 ); LocalFree( lpReturnString ); } } else /* Error, something occured. */ { if ( lpReturnString ) { LocalFree( lpReturnString ); } } LOGEXIT( "FormatMessageW returns %d.\n", nCount ); PERF_EXIT(FormatMessageW); return nCount; }
/*++ Function: MessageBoxW This is a small subset of MessageBox that simply logs a message to the system logging facility and returns. A typical log entry will look like: May 23 15:48:10 rice example1: MessageBox: Caption: Error Text Note: hWnd should always be NULL. See MSDN doc. --*/ int PALAPI MessageBoxW( IN LPVOID hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType) { CHAR *text = NULL; CHAR *caption = NULL; INT len = 0; INT rc = 0; PERF_ENTRY(MessageBoxW); ENTRY( "MessageBoxW (hWnd=%p, lpText=%p (%S), lpCaption=%p (%S), uType=%#x)\n", hWnd, lpText?lpText:W16_NULLSTRING, lpText?lpText:W16_NULLSTRING, lpCaption?lpCaption:W16_NULLSTRING, lpCaption?lpCaption:W16_NULLSTRING, uType ); if (hWnd != NULL) { ASSERT("hWnd != NULL"); } if(lpText) { len = WideCharToMultiByte(CP_ACP, 0, lpText, -1, NULL, 0, NULL, NULL); if(len) { text = (LPSTR)PAL_malloc(len); if(!text) { ERROR("malloc() failed!\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } if( !WideCharToMultiByte( CP_ACP, 0, lpText, -1, text, len, NULL, NULL)) { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { WARN("No message text\n"); if (NULL == (text = PAL__strdup("(no message text)"))) { ASSERT("strdup() failed\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } if (lpCaption) { len = WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, NULL, 0, NULL, NULL); if(len) { caption = (CHAR*)PAL_malloc(len); if(!caption) { ERROR("malloc() failed!\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } if( !WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, caption, len, NULL, NULL)) { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { if (NULL == (caption = PAL__strdup("Error"))) { ERROR("strdup() failed\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } } rc = MessageBoxA(hWnd, text, caption, uType); error: PAL_free(caption); PAL_free(text); LOGEXIT("MessageBoxW returns %d\n", rc); PERF_EXIT(MessageBoxW); return rc; }
/*++ Function: TIMEGetStdDstDates retrieve the two dates preceding the two transition dates: 1- from standard date to daylight date 2- from daylight date to standard date if daylight/standard date doesn't apply for the current zone, then tm_mon of dst_date and std_date parameters will be set to 0. Parameters dst_date: return transition date from standard date to daylight date std_date: return transition date from daylight date to standard date Return Values FALSE, if it fails, TRUE, otherwise. --*/ BOOL TIMEGetStdDstDates(int year, struct tm *dst_date, struct tm *std_date) { const int sec_per_year = 31536000; /* 365x24x60x60 */ int dayLightActive; /* the POSIX time_t type is opaque; to be portable, we should assume nothing about its representation. */ time_t date_LO; time_t date_MID; time_t date_HI; time_t date_HI_Copy; struct tm local_date; struct tm date_MID_tm; #if HAVE_LOCALTIME_R struct tm tmp_tm; #endif /* HAVE_LOCALTIME_R */ struct tm *dateMIDPtr; struct tm *tmpPtr; TRANS_DATES tmp_transd, *lptmp_transd; memset(&tmp_transd, 0, sizeof(tmp_transd)); /* initialize date_LO to the first date of the current year, and date_HI to the last date */ if( (glob_trans_dates) && (glob_trans_dates->dst_date.tm_year == year - 1900)) { /* tansition dates already calculated */ TRACE("Tansition dates already calculated\n"); *dst_date = glob_trans_dates->dst_date; *std_date = glob_trans_dates->std_date; return TRUE; } memset(&local_date, 0, sizeof(struct tm)); local_date.tm_year = year - 1900; local_date.tm_mday = 1; if (-1 == (date_LO = mktime(&local_date))) { ERROR("mktime() failed.\n"); return FALSE; } date_HI_Copy = date_HI = date_LO + sec_per_year; /* get the initial daylight status */ #if HAVE_LOCALTIME_R tmpPtr = &tmp_tm; if (NULL == localtime_r(&date_LO, &tmp_tm)) #else /* HAVE_LOCALTIME_R */ if (NULL == (tmpPtr = localtime(&date_LO))) #endif /* HAVE_LOCALTIME_R */ { ERROR("localtime_r() failed.\n"); return FALSE; } dayLightActive = tmpPtr->tm_isdst; /* retrieve the date before the first transition to/from daylight/standard date happens */ do { date_MID = date_LO + difftime (date_HI, date_LO) / 2.0; #if HAVE_LOCALTIME_R dateMIDPtr = &date_MID_tm; if (NULL == localtime_r(&date_MID, &date_MID_tm)) #else /* HAVE_LOCALTIME_R */ if (NULL == (dateMIDPtr = localtime(&date_MID))) #endif /* HAVE_LOCALTIME_R */ { ERROR("localtime_r() failed.\n"); return FALSE; } if(dateMIDPtr->tm_isdst != dayLightActive) { date_HI = date_MID - 1; } else { date_LO = date_MID + 1; } } while (!(difftime (date_LO, date_HI) > 0)); // date_LO <= date_HI if(dateMIDPtr->tm_isdst != dayLightActive) { /* passed the transition date, move back by one second */ dateMIDPtr->tm_sec--; date_MID = mktime(dateMIDPtr); #if HAVE_LOCALTIME_R localtime_r(&date_MID, dateMIDPtr); #else /* HAVE_LOCALTIME_R */ dateMIDPtr = localtime(&date_MID); #endif /* HAVE_LOCALTIME_R */ } if (date_HI_Copy == date_MID) { /* no daylight/standard date for the current zone */ memset(dst_date, 0, sizeof(*dst_date)); memset(std_date, 0, sizeof(*std_date)); return TRUE; } if (dayLightActive == 0) { tmp_transd.dst_date = *dateMIDPtr; dayLightActive = 1; } else { tmp_transd.std_date = *dateMIDPtr; dayLightActive = 0; } /* retrieve the date before the second transition to/from daylight/standard date happens */ date_HI = date_HI_Copy; date_MID_tm.tm_sec++; date_LO = mktime(dateMIDPtr); do { date_MID = date_LO + difftime (date_HI, date_LO) / 2.0; #if HAVE_LOCALTIME_R dateMIDPtr = &date_MID_tm; if (NULL == localtime_r(&date_MID, dateMIDPtr)) #else /* HAVE_LOCALTIME_R */ if (NULL == (dateMIDPtr = localtime(&date_MID))) #endif /* HAVE_LOCALTIME_R */ { ERROR("localtime() failed.\n"); return FALSE; } if(dateMIDPtr->tm_isdst != dayLightActive) { date_HI = date_MID - 1; } else { date_LO = date_MID + 1; } } while (!(difftime (date_LO, date_HI) > 0)); // date_LO <= date_HI if(dateMIDPtr->tm_isdst != dayLightActive) { /* passed the transition date, move back by one second */ date_MID_tm.tm_sec--; date_MID = mktime(dateMIDPtr); #if HAVE_LOCALTIME_R dateMIDPtr = &date_MID_tm; localtime_r(&date_MID, dateMIDPtr); #else /* HAVE_LOCALTIME_R */ dateMIDPtr = localtime(&date_MID); #endif /* HAVE_LOCALTIME_R */ } if (dayLightActive == 0) { tmp_transd.dst_date = *dateMIDPtr; } else { tmp_transd.std_date = *dateMIDPtr; } if(glob_trans_dates == NULL) { if((lptmp_transd = (TRANS_DATES*)PAL_malloc(sizeof(TRANS_DATES))) == NULL) { ERROR("can't allocate memory for global transition dates\n"); return FALSE; } *lptmp_transd = tmp_transd; if(NULL != InterlockedCompareExchangePointer(&glob_trans_dates, lptmp_transd, NULL)) { /* another thread got in before us! */ WARN("Another thread initialized global trans dates\n"); PAL_free(lptmp_transd); } } else { *glob_trans_dates = tmp_transd; } *dst_date = glob_trans_dates->dst_date; *std_date = glob_trans_dates->std_date; return TRUE; }
/* The use of ULONG is by design, to ensure that a 32 bit value is always returned from this function. If "unsigned long" is used instead of ULONG, then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus breaking Windows behavior .*/ ULONG __cdecl PAL_wcstoul( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; unsigned long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstoul); ENTRY("wcstoul (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); THREADMarkDiagnostic("PAL_wcstoul -> strtoul"); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstoulExit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL_wcstoulExit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstoulExit; } res = strtoul(s_nptr, &s_endptr, base); #ifdef BIT64 if (res > _UI32_MAX) { wchar_16 wc = *nptr; while (PAL_iswspace(wc)) { wc = *nptr++; } /* If the string represents a positive number that is greater than _UI32_MAX, set errno to ERANGE. Otherwise, don't set errno to match Windows behavior. */ if (wc != '-') { res = _UI32_MAX; errno = ERANGE; } } #endif /* only ASCII characters will be accepted by strtol, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL_wcstoulExit: PAL_free(s_nptr); LOGEXIT("wcstoul returning unsigned long %lu\n", res); PERF_EXIT(wcstoul); /* When returning unsigned long res from this function, it will be implicitly cast to ULONG. This handles situations where a string that represents a negative number is passed in to wcstoul. The Windows behavior is analogous to taking the binary equivalent of the negative value and treating it as a positive number. Returning a ULONG from this function, as opposed to native unsigned long, allows us to match this behavior. The explicit case to ULONG below is used to silence any potential warnings due to the implicit casting. */ return (ULONG)res; }
ULONGLONG __cdecl PAL__wcstoui64( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; unsigned long long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstoul); ENTRY("_wcstoui64 (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); THREADMarkDiagnostic("PAL__wcstoui64 -> strtoull"); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL__wcstoui64Exit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL__wcstoui64Exit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL__wcstoui64Exit; } res = strtoull(s_nptr, &s_endptr, base); /* only ASCII characters will be accepted by strtoull, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL__wcstoui64Exit: PAL_free(s_nptr); LOGEXIT("_wcstoui64 returning unsigned long long %llu\n", res); PERF_EXIT(_wcstoui64); return res; }
__cdecl _fullpath( char *absPath, const char *relPath, size_t maxLength) { char realpath_buf[PATH_MAX+1]; char path_copy[PATH_MAX+1]; char *retval = NULL; DWORD cPathCopy = sizeof(path_copy)/sizeof(path_copy[0]); size_t min_length; BOOL fBufAllocated = FALSE; PERF_ENTRY(_fullpath); ENTRY("_fullpath (absPath=%p, relPath=%p (%s), maxLength = %lu)\n", absPath, relPath ? relPath:"NULL", relPath ? relPath:"NULL", maxLength); if (strncpy_s(path_copy, sizeof(path_copy), relPath ? relPath : ".", cPathCopy) != SAFECRT_SUCCESS) { TRACE("_fullpath: strncpy_s failed!\n"); goto fullpathExit; } FILEDosToUnixPathA(path_copy); if(NULL == realpath(path_copy, realpath_buf)) { ERROR("realpath() failed; problem path is '%s'. errno is %d (%s)\n", realpath_buf, errno, strerror(errno)); goto fullpathExit; } TRACE("real path is %s\n", realpath_buf); min_length = strlen(realpath_buf)+1; // +1 for the NULL terminator if(NULL == absPath) { absPath = static_cast<char *>( PAL_malloc(_MAX_PATH * sizeof(char))); if (!absPath) { ERROR("PAL_malloc failed with error %d\n", errno); goto fullpathExit; } maxLength = _MAX_PATH; fBufAllocated = TRUE; } if(min_length > maxLength) { ERROR("maxLength is %lu, we need at least %lu\n", maxLength, min_length); if (fBufAllocated) { PAL_free(absPath); fBufAllocated = FALSE; } goto fullpathExit; } strcpy_s(absPath, maxLength, realpath_buf); retval = absPath; fullpathExit: LOGEXIT("_fullpath returns char * %p\n", retval); PERF_EXIT(_fullpath); return retval; }
static LPWSTR FMTMSG_ProcessPrintf( wchar_t c , LPWSTR lpPrintfString, LPWSTR lpInsertString) { LPWSTR lpBuffer = NULL; LPWSTR lpBuffer2 = NULL; LPWSTR lpFormat = NULL; #if _DEBUG // small size for _DEBUG to exercise buffer reallocation logic int tmpSize = 4; #else int tmpSize = 64; #endif UINT nFormatLength = 0; int nBufferLength = 0; TRACE( "FMTMSG_ProcessPrintf( %C, %S, %S )\n", c, lpPrintfString, lpInsertString ); switch ( c ) { case 'e' : /* Fall through */ case 'E' : /* Fall through */ case 'f' : /* Fall through */ case 'g' : /* Fall through */ case 'G' : ERROR( "%%%c is not supported by FormatMessage.\n", c ); SetLastError( ERROR_INVALID_PARAMETER ); return NULL; } nFormatLength = PAL_wcslen( lpPrintfString ) + 2; /* Need to count % AND NULL */ lpFormat = (LPWSTR)PAL_malloc( nFormatLength * sizeof( WCHAR ) ); if ( !lpFormat ) { ERROR( "Unable to allocate memory.\n" ); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return NULL; } /* Create the format string. */ memset( lpFormat, 0, nFormatLength * sizeof(WCHAR) ); *lpFormat = '%'; PAL_wcscat( lpFormat, lpPrintfString ); lpBuffer = (LPWSTR) PAL_malloc(tmpSize*sizeof(WCHAR)); /* try until the buffer is big enough */ while (TRUE) { if (!lpBuffer) { ERROR("Unable to allocate memory\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); PAL_free(lpFormat); return NULL; } nBufferLength = _snwprintf_s( lpBuffer, tmpSize, tmpSize, lpFormat, lpInsertString); if ((nBufferLength >= 0) && (nBufferLength != tmpSize)) { break; /* succeeded */ } else { tmpSize *= 2; lpBuffer2 = static_cast<WCHAR *>( PAL_realloc(lpBuffer, tmpSize*sizeof(WCHAR))); if (lpBuffer2 == NULL) PAL_free(lpBuffer); lpBuffer = lpBuffer2; } } PAL_free( lpFormat ); lpFormat = NULL; return lpBuffer; }
/*++ Function: CreateDirectoryA Note: lpSecurityAttributes always NULL. See MSDN doc. --*/ BOOL PALAPI CreateDirectoryA( IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) { BOOL bRet = FALSE; DWORD dwLastError = 0; PathCharString realPath; char* realPathBuf; LPSTR unixPathName = NULL; int pathLength; int i; const int mode = S_IRWXU | S_IRWXG | S_IRWXO; PERF_ENTRY(CreateDirectoryA); ENTRY("CreateDirectoryA(lpPathName=%p (%s), lpSecurityAttr=%p)\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL", lpSecurityAttributes); if ( lpSecurityAttributes ) { ASSERT("lpSecurityAttributes is not NULL as it should be\n"); dwLastError = ERROR_INVALID_PARAMETER; goto done; } // Windows returns ERROR_PATH_NOT_FOUND when called with NULL. // If we don't have this check, strdup(NULL) segfaults. if (lpPathName == NULL) { ERROR("CreateDirectoryA called with NULL pathname!\n"); dwLastError = ERROR_PATH_NOT_FOUND; goto done; } unixPathName = PAL__strdup(lpPathName); if (unixPathName == NULL ) { ERROR("PAL__strdup() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( unixPathName ); // Remove any trailing slashes at the end because mkdir might not // handle them appropriately on all platforms. pathLength = strlen(unixPathName); i = pathLength; while(i > 1) { if(unixPathName[i - 1] =='/') { unixPathName[i - 1]='\0'; i--; } else { break; } } // Get an absolute path. if (unixPathName[0] == '/') { realPathBuf = unixPathName; } else { DWORD len = GetCurrentDirectoryA(realPath); if (len == 0 || !realPath.Reserve(realPath.GetCount() + pathLength + 1 )) { dwLastError = DIRGetLastErrorFromErrno(); WARN("Getcwd failed with errno=%d \n", dwLastError); goto done; } realPath.Append("/", 1); realPath.Append(unixPathName, pathLength); realPathBuf = realPath.OpenStringBuffer(realPath.GetCount()); } // Canonicalize the path so we can determine its length. FILECanonicalizePath(realPathBuf); if ( mkdir(realPathBuf, mode) != 0 ) { TRACE("Creation of directory [%s] was unsuccessful, errno = %d.\n", unixPathName, errno); switch( errno ) { case ENOTDIR: /* FALL THROUGH */ case ENOENT: FILEGetProperNotFoundError( realPathBuf, &dwLastError ); goto done; case EEXIST: dwLastError = ERROR_ALREADY_EXISTS; break; default: dwLastError = ERROR_ACCESS_DENIED; } } else { TRACE("Creation of directory [%s] was successful.\n", unixPathName); bRet = TRUE; } realPath.CloseBuffer(0); //The PathCharString usage is done done: if( dwLastError ) { SetLastError( dwLastError ); } PAL_free( unixPathName ); LOGEXIT("CreateDirectoryA returns BOOL %d\n", bRet); PERF_EXIT(CreateDirectoryA); return bRet; }
/******************************************************************************* Function: PAL_vsnprintf (silent version) for more details, see PAL_vsnprintf in printf.c *******************************************************************************/ INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list aparg) { BOOL BufferRanOut = FALSE; CHAR TempBuff[1024]; /* used to hold a single %<foo> format string */ LPSTR BufferPtr = Buffer; LPCSTR Fmt = Format; LPWSTR TempWStr; CHAR TempStr[MAX_STR_LEN+1]; WCHAR TempWChar; INT Flags; INT Width; INT Precision; INT Prefix; INT Type; INT Length; INT TempInt; int wctombResult; va_list ap; va_copy(ap, aparg); while (*Fmt) { if ((BufferPtr - Buffer) >= Count) { BufferRanOut = TRUE; break; } else if(*Fmt == '%' && TRUE == Silent_ExtractFormatA(&Fmt, TempBuff, &Flags, &Width, &Precision, &Prefix, &Type)) { if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_STRING) { if (PRECISION_STAR == Precision) { Precision = va_arg(ap, INT); } else if (PRECISION_INVALID == Precision) { /* both a '*' and a number, ignore, but remove arg */ TempInt = va_arg(ap, INT); /* value not used */ } TempWStr = va_arg(ap, LPWSTR); Length = Silent_WideCharToMultiByte(TempWStr, -1, 0, 0); if (!Length) { va_end(ap); return -1; } /* clip string output to MAX_STR_LEN characters */ if(-1 == Precision) { Precision = MAX_STR_LEN; } if (PRECISION_DOT == Precision) { /* copy nothing */ *TempStr = 0; Length = 0; } else if (Precision > 0 && Precision < Length - 1) { Length = Silent_WideCharToMultiByte(TempWStr, Precision, TempStr, Length); if (!Length) { va_end(ap); return -1; } TempStr[Length] = 0; Length = Precision; } /* copy everything */ else { wctombResult = Silent_WideCharToMultiByte(TempWStr, -1, TempStr, Length); if (!wctombResult) { PAL_free(TempStr); va_end(ap); return -1; } --Length; /* exclude null char */ } /* do the padding (if needed)*/ BufferRanOut = !Internal_AddPaddingA(&BufferPtr, Count - (BufferPtr - Buffer), TempStr, Width - Length, Flags); } else if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_CHAR) { CHAR TempBuffer[4]; if (PRECISION_STAR == Precision || PRECISION_INVALID == Precision) { /* ignore (because it's a char), and remove arg */ TempInt = va_arg(ap, INT); /* value not used */ } TempWChar = va_arg(ap, int); Length = Silent_WideCharToMultiByte(&TempWChar, 1, TempBuffer, 4); if (!Length) { va_end(ap); return -1; } TempBuffer[Length] = 0; /* do the padding (if needed)*/ BufferRanOut = !Internal_AddPaddingA(&BufferPtr, Count - (BufferPtr - Buffer), TempBuffer, Width - Length, Flags); } /* this places the number of bytes written to the buffer in the next arg */ else if (Type == PFF_TYPE_N) { if (PRECISION_STAR == Precision) { Precision = va_arg(ap, INT); } if (Prefix == PFF_PREFIX_SHORT) { *(va_arg(ap, short *)) = BufferPtr - Buffer; } else { *(va_arg(ap, LPLONG)) = BufferPtr - Buffer; } } /* types that sprintf can handle */ else { size_t TempCount = Count - (BufferPtr - Buffer); TempInt = 0; /* %h (short) doesn't seem to be handled properly by local sprintf, so lets do the truncation ourselves. (ptr -> int -> short to avoid warnings */ if (Type == PFF_TYPE_P && Prefix == PFF_PREFIX_SHORT) { long trunc1; short trunc2; trunc1 = va_arg(ap, LONG); trunc2 = (short)trunc1; TempInt = snprintf(BufferPtr, TempCount, TempBuff, trunc2); } else { /* limit string output (%s) to 300 characters */ if(TempBuff[0]=='%' && TempBuff[1]=='s') { if (strcpy_s(TempBuff, sizeof(TempBuff), "%.300s") != SAFECRT_SUCCESS) { va_end(ap); return -1; } } va_list apcopy; va_copy(apcopy, ap); TempInt = PAL__vsnprintf(BufferPtr, TempCount, TempBuff, apcopy); va_end(apcopy); PAL_printf_arg_remover(&ap, Width, Precision, Type, Prefix); } if (TempInt < 0 || static_cast<size_t>(TempInt) >= TempCount) /* buffer not long enough */ { BufferPtr += TempCount; BufferRanOut = TRUE; } else { BufferPtr += TempInt; } } }
~CGroup() { PAL_free(m_memory_cgroup_path); PAL_free(m_cpu_cgroup_path); }