< prev index next >
src/hotspot/os/windows/os_windows.cpp
Print this page
rev 55820 : 8191521: handle long relative path specified in -Xbootclasspath/a on windows
Reviewed-by:
*** 4277,4408 ****
} else {
sbuf->st_mode |= S_IFREG;
}
}
! // The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c
! // Creates an UNC path from a single byte path. Return buffer is
! // allocated in C heap and needs to be freed by the caller.
! // Returns NULL on error.
! static wchar_t* create_unc_path(const char* path, errno_t &err) {
! wchar_t* wpath = NULL;
! size_t converted_chars = 0;
! size_t path_len = strlen(path) + 1; // includes the terminating NULL
! if (path[0] == '\\' && path[1] == '\\') {
! if (path[2] == '?' && path[3] == '\\'){
! // if it already has a \\?\ don't do the prefix
! wpath = (wchar_t*)os::malloc(path_len * sizeof(wchar_t), mtInternal);
! if (wpath != NULL) {
! err = ::mbstowcs_s(&converted_chars, wpath, path_len, path, path_len);
! } else {
err = ENOMEM;
- }
} else {
! // only UNC pathname includes double slashes here
! wpath = (wchar_t*)os::malloc((path_len + 7) * sizeof(wchar_t), mtInternal);
! if (wpath != NULL) {
! ::wcscpy(wpath, L"\\\\?\\UNC\0");
! err = ::mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len);
} else {
! err = ENOMEM;
! }
}
} else {
! wpath = (wchar_t*)os::malloc((path_len + 4) * sizeof(wchar_t), mtInternal);
! if (wpath != NULL) {
! ::wcscpy(wpath, L"\\\\?\\\0");
! err = ::mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len);
} else {
err = ENOMEM;
}
}
- return wpath;
- }
! static void destroy_unc_path(wchar_t* wpath) {
! os::free(wpath);
! }
! int os::stat(const char *path, struct stat *sbuf) {
! char* pathbuf = (char*)os::strdup(path, mtInternal);
! if (pathbuf == NULL) {
! errno = ENOMEM;
! return -1;
}
- os::native_path(pathbuf);
- int ret;
- WIN32_FILE_ATTRIBUTE_DATA file_data;
- // Not using stat() to avoid the problem described in JDK-6539723
- if (strlen(path) < MAX_PATH) {
- BOOL bret = ::GetFileAttributesExA(pathbuf, GetFileExInfoStandard, &file_data);
- if (!bret) {
- errno = ::GetLastError();
- ret = -1;
}
- else {
- file_attribute_data_to_stat(sbuf, file_data);
- ret = 0;
}
! } else {
! errno_t err = ERROR_SUCCESS;
! wchar_t* wpath = create_unc_path(pathbuf, err);
if (err != ERROR_SUCCESS) {
! if (wpath != NULL) {
! destroy_unc_path(wpath);
}
! os::free(pathbuf);
errno = err;
return -1;
}
! BOOL bret = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_data);
if (!bret) {
errno = ::GetLastError();
! ret = -1;
! } else {
! file_attribute_data_to_stat(sbuf, file_data);
! ret = 0;
! }
! destroy_unc_path(wpath);
}
! os::free(pathbuf);
! return ret;
}
static HANDLE create_read_only_file_handle(const char* file) {
! if (file == NULL) {
! return INVALID_HANDLE_VALUE;
! }
! char* nativepath = (char*)os::strdup(file, mtInternal);
! if (nativepath == NULL) {
! errno = ENOMEM;
return INVALID_HANDLE_VALUE;
}
- os::native_path(nativepath);
-
- size_t len = strlen(nativepath);
- HANDLE handle = INVALID_HANDLE_VALUE;
! if (len < MAX_PATH) {
! handle = ::CreateFile(nativepath, 0, FILE_SHARE_READ,
! NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
! } else {
! errno_t err = ERROR_SUCCESS;
! wchar_t* wfile = create_unc_path(nativepath, err);
! if (err != ERROR_SUCCESS) {
! if (wfile != NULL) {
! destroy_unc_path(wfile);
! }
! os::free(nativepath);
! return INVALID_HANDLE_VALUE;
! }
! handle = ::CreateFileW(wfile, 0, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
! destroy_unc_path(wfile);
! }
- os::free(nativepath);
return handle;
}
bool os::same_files(const char* file1, const char* file2) {
--- 4277,4417 ----
} 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) {
! 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] == '\\') {
! assert(buf[2] != '\\');
!
! 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);
!
! if (wide_path == NULL) {
errno = err;
return -1;
}
!
! WIN32_FILE_ATTRIBUTE_DATA file_data;;
! BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data);
! os::free(wide_path);
!
if (!bret) {
errno = ::GetLastError();
! return -1;
}
!
! file_attribute_data_to_stat(sbuf, file_data);
! return 0;
}
static HANDLE create_read_only_file_handle(const char* file) {
! errno_t err;
! wchar_t* wide_path = wide_abs_unc_path(file, err);
! if (wide_path == NULL) {
! errno = err;
return INVALID_HANDLE_VALUE;
}
! HANDLE handle = ::CreateFileW(wide_path, 0, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
! os::free(wide_path);
return handle;
}
bool os::same_files(const char* file1, const char* file2) {
*** 4447,4457 ****
}
return result;
}
-
#define FT2INT64(ft) \
((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime))
// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
--- 4456,4465 ----
*** 4552,4644 ****
// DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield()
bool os::dont_yield() {
return DontYieldALot;
}
- // This method is a slightly reworked copy of JDK's sysOpen
- // from src/windows/hpi/src/sys_api_md.c
-
int os::open(const char *path, int oflag, int mode) {
! char* pathbuf = (char*)os::strdup(path, mtInternal);
! if (pathbuf == NULL) {
! errno = ENOMEM;
! return -1;
! }
! os::native_path(pathbuf);
! int ret;
! if (strlen(path) < MAX_PATH) {
! ret = ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
! } else {
! errno_t err = ERROR_SUCCESS;
! wchar_t* wpath = create_unc_path(pathbuf, err);
! if (err != ERROR_SUCCESS) {
! if (wpath != NULL) {
! destroy_unc_path(wpath);
! }
! os::free(pathbuf);
errno = err;
return -1;
}
! ret = ::_wopen(wpath, oflag | O_BINARY | O_NOINHERIT, mode);
! if (ret == -1) {
errno = ::GetLastError();
}
! destroy_unc_path(wpath);
! }
! os::free(pathbuf);
! return ret;
}
FILE* os::open(int fd, const char* mode) {
return ::_fdopen(fd, mode);
}
// Is a (classpath) directory empty?
bool os::dir_is_empty(const char* path) {
! char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal);
! if (search_path == NULL) {
! errno = ENOMEM;
! return false;
! }
! strcpy(search_path, path);
! os::native_path(search_path);
! // Append "*", or possibly "\\*", to path
! if (search_path[1] == ':' &&
! (search_path[2] == '\0' ||
! (search_path[2] == '\\' && search_path[3] == '\0'))) {
! // No '\\' needed for cases like "Z:" or "Z:\"
! strcat(search_path, "*");
! }
! else {
! strcat(search_path, "\\*");
! }
! errno_t err = ERROR_SUCCESS;
! wchar_t* wpath = create_unc_path(search_path, err);
! if (err != ERROR_SUCCESS) {
! if (wpath != NULL) {
! destroy_unc_path(wpath);
! }
! os::free(search_path);
errno = err;
return false;
}
WIN32_FIND_DATAW fd;
! HANDLE f = ::FindFirstFileW(wpath, &fd);
! destroy_unc_path(wpath);
bool is_empty = true;
if (f != INVALID_HANDLE_VALUE) {
while (is_empty && ::FindNextFileW(f, &fd)) {
// An empty directory contains only the current directory file
// and the previous directory file.
if ((wcscmp(fd.cFileName, L".") != 0) &&
(wcscmp(fd.cFileName, L"..") != 0)) {
is_empty = false;
}
}
FindClose(f);
}
! os::free(search_path);
return is_empty;
}
// create binary file, rewriting existing file if required
int os::create_binary_file(const char* path, bool rewrite_existing) {
--- 4560,4627 ----
// DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield()
bool os::dont_yield() {
return DontYieldALot;
}
int os::open(const char *path, int oflag, int mode) {
! errno_t err;
! wchar_t* wide_path = wide_abs_unc_path(path, err);
!
! if (wide_path == NULL) {
errno = err;
return -1;
}
! int fd = ::_wopen(wide_path, oflag | O_BINARY | O_NOINHERIT, mode);
! os::free(wide_path);
!
! if (fd == -1) {
errno = ::GetLastError();
}
!
! return fd;
}
FILE* os::open(int fd, const char* mode) {
return ::_fdopen(fd, mode);
}
// Is a (classpath) directory empty?
bool os::dir_is_empty(const char* path) {
! errno_t err;
! wchar_t* wide_path = wide_abs_unc_path(path, err, 2);
!
! if (wide_path == NULL) {
errno = err;
return false;
}
+
+ // Make sure we end with "\\*"
+ if (wide_path[wcslen(wide_path) - 1] == L'\\') {
+ wcscat(wide_path, L"*");
+ } else {
+ wcscat(wide_path, L"\\*");
+ }
+
WIN32_FIND_DATAW fd;
! HANDLE f = ::FindFirstFileW(wide_path, &fd);
! os::free(wide_path);
bool is_empty = true;
+
if (f != INVALID_HANDLE_VALUE) {
while (is_empty && ::FindNextFileW(f, &fd)) {
// An empty directory contains only the current directory file
// and the previous directory file.
if ((wcscmp(fd.cFileName, L".") != 0) &&
(wcscmp(fd.cFileName, L"..") != 0)) {
is_empty = false;
}
}
FindClose(f);
+ } else {
+ errno = ::GetLastError();
}
!
return is_empty;
}
// create binary file, rewriting existing file if required
int os::create_binary_file(const char* path, bool rewrite_existing) {
< prev index next >