< prev index next >

src/hotspot/os/windows/os_windows.cpp

Print this page

        

*** 4159,4260 **** } else { sbuf->st_mode |= S_IFREG; } } ! // Returns the given path as an absolute wide path in unc format. The returned path is NULL ! // on error (with err being set accordingly) and should be freed via os::free() otherwise. ! // additional_space is the number of additionally allocated wchars after the terminating L'\0'. ! // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for ! // short paths. ! static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) { ! if ((path == NULL) || (path[0] == '\0')) { ! err = ENOENT; ! return NULL; ! } ! size_t path_len = strlen(path); ! // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:. ! char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal); ! wchar_t* result = NULL; ! if (buf == NULL) { ! err = ENOMEM; ! } else { ! memcpy(buf, path, path_len + 1); ! os::native_path(buf); ! wchar_t* prefix; ! int prefix_off = 0; ! bool is_abs = true; ! bool needs_fullpath = true; if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') { ! prefix = L"\\\\?\\"; } else if (buf[0] == '\\' && buf[1] == '\\') { if (buf[2] == '?' && buf[3] == '\\') { ! prefix = L""; ! needs_fullpath = false; } else { ! prefix = L"\\\\?\\UNC"; ! prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path } } else { ! is_abs = false; ! prefix = L"\\\\?\\"; } ! size_t buf_len = strlen(buf); ! size_t prefix_len = wcslen(prefix); ! size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN; ! size_t result_size = prefix_len + full_path_size - prefix_off; ! result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal); ! if (result == NULL) { ! err = ENOMEM; ! } else { ! size_t converted_chars; ! wchar_t* path_start = result + prefix_len - prefix_off; ! err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len); ! if ((err == ERROR_SUCCESS) && needs_fullpath) { ! wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal); ! if (tmp == NULL) { ! err = ENOMEM; ! } else { ! if (!_wfullpath(tmp, path_start, full_path_size)) { ! err = ENOENT; ! } else { ! ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t)); } ! os::free(tmp); ! } } ! memcpy(result, prefix, sizeof(wchar_t) * prefix_len); // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative) ! size_t result_len = wcslen(result); ! ! if (result[result_len - 1] == L'\\') { ! if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) { result[result_len - 1] = L'\0'; } } - } - } ! os::free(buf); ! ! if (err != ERROR_SUCCESS) { ! os::free(result); ! result = NULL; } ! return result; } int os::stat(const char *path, struct stat *sbuf) { errno_t err; wchar_t* wide_path = wide_abs_unc_path(path, err); --- 4159,4283 ---- } else { sbuf->st_mode |= S_IFREG; } } ! static errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path) { ! // Get required buffer size to convert to Unicode ! int unicode_path_len = MultiByteToWideChar(CP_THREAD_ACP, ! MB_ERR_INVALID_CHARS, ! char_path, -1, ! NULL, 0); ! if (unicode_path_len == 0) { ! return EINVAL; ! } ! ! *unicode_path = NEW_C_HEAP_ARRAY(WCHAR, unicode_path_len, mtInternal); ! ! int result = MultiByteToWideChar(CP_THREAD_ACP, ! MB_ERR_INVALID_CHARS, ! char_path, -1, ! *unicode_path, unicode_path_len); ! assert(result == unicode_path_len, "length already checked above"); ! return ERROR_SUCCESS; ! } ! static errno_t get_full_path(LPCWSTR unicode_path, LPWSTR* full_path) { ! // Get required buffer size to convert to full path. The return ! // value INCLUDES the terminating null character. ! DWORD full_path_len = GetFullPathNameW(unicode_path, 0, NULL, NULL); ! if (full_path_len == 0) { ! return EINVAL; ! } ! ! *full_path = NEW_C_HEAP_ARRAY(WCHAR, full_path_len, mtInternal); ! ! // When the buffer has sufficient size, the return value EXCLUDES the ! // terminating null character ! DWORD result = GetFullPathNameW(unicode_path, full_path_len, *full_path, NULL); ! assert(result <= full_path_len, "length already checked above"); ! return ERROR_SUCCESS; ! } ! ! static void set_path_prefix(char* buf, LPWSTR* prefix, int* prefix_off, bool* needs_fullpath) { ! *prefix_off = 0; ! *needs_fullpath = true; if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') { ! *prefix = L"\\\\?\\"; } else if (buf[0] == '\\' && buf[1] == '\\') { if (buf[2] == '?' && buf[3] == '\\') { ! *prefix = L""; ! *needs_fullpath = false; } else { ! *prefix = L"\\\\?\\UNC"; ! *prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path } } else { ! *prefix = L"\\\\?\\"; } + } ! // Returns the given path as an absolute wide path in unc format. The returned path is NULL ! // on error (with err being set accordingly) and should be freed via os::free() otherwise. ! // additional_space is the size of space, in wchar_t, the function will additionally add to ! // the allocation of return buffer (such that the size of the returned buffer is at least ! // wcslen(buf) + 1 + additional_space). ! static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) { ! if ((path == NULL) || (path[0] == '\0')) { ! err = ENOENT; ! return NULL; ! } ! // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:. ! size_t buf_len = 1 + MAX2((size_t)3, strlen(path)); ! char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal); ! strncpy(buf, path, buf_len); ! os::native_path(buf); ! LPWSTR prefix = NULL; ! int prefix_off = 0; ! bool needs_fullpath = true; ! set_path_prefix(buf, &prefix, &prefix_off, &needs_fullpath); ! LPWSTR unicode_path = NULL; ! err = convert_to_unicode(buf, &unicode_path); ! FREE_C_HEAP_ARRAY(char, buf); ! if (err != ERROR_SUCCESS) { ! return NULL; } ! LPWSTR converted_path = NULL; ! if (needs_fullpath) { ! err = get_full_path(unicode_path, &converted_path); ! } else { ! converted_path = unicode_path; } ! LPWSTR result = NULL; ! if (converted_path != NULL) { ! size_t prefix_len = wcslen(prefix); ! size_t result_len = prefix_len - prefix_off + wcslen(converted_path) + additional_space + 1; ! result = NEW_C_HEAP_ARRAY(WCHAR, result_len, mtInternal); ! _snwprintf(result, result_len, L"%s%s", prefix, &converted_path[prefix_off]); // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative) ! result_len = wcslen(result); ! if ((result[result_len - 1] == L'\\') && ! !(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) { result[result_len - 1] = L'\0'; } } ! if (converted_path != unicode_path) { ! FREE_C_HEAP_ARRAY(WCHAR, converted_path); } + FREE_C_HEAP_ARRAY(WCHAR, unicode_path); ! return static_cast<wchar_t*>(result); // LPWSTR and wchat_t* are the same type on Windows. } int os::stat(const char *path, struct stat *sbuf) { errno_t err; wchar_t* wide_path = wide_abs_unc_path(path, err);
< prev index next >