# HG changeset patch # User mbaesken # Date 1554206040 -7200 # Node ID dad2c80ae0b27b6aa1fe2dcabe1024d1cab4e25b # Parent b34bcfbcc2fd6eac898122f0a15ee849a574434d 8218547: Simplify JLI_Open on Windows in native code (libjli) Reviewed-by: alanb, clanger diff -r b34bcfbcc2fd -r dad2c80ae0b2 src/java.base/windows/native/libjli/java_md.c --- a/src/java.base/windows/native/libjli/java_md.c Fri Apr 05 07:59:13 2019 +0200 +++ b/src/java.base/windows/native/libjli/java_md.c Tue Apr 02 13:54:00 2019 +0200 @@ -41,8 +41,6 @@ #define JVM_DLL "jvm.dll" #define JAVA_DLL "java.dll" -#define ELP_PREFIX L"\\\\?\\" - /* * Prototypes. */ @@ -497,57 +495,67 @@ return rc; } -/* On Windows, if _open fails, retry again with CreateFileW and - * "\\?\" prefix ( extended-length paths) - this allows to open paths with larger file names; - * otherwise we run into the MAX_PATH limitation */ -int JLI_Open(const char* name, int flags) { - int fd = _open(name, flags); - if (fd == -1 && errno == ENOENT) { - wchar_t* wname = NULL; - wchar_t* wfullname = NULL; - wchar_t* wfullname_w_prefix = NULL; - size_t wnamelen, wfullnamelen, elplen; - HANDLE h; - - wnamelen = strlen(name) + 1; - wname = (wchar_t*) malloc(wnamelen*sizeof(wchar_t)); - if (wname == NULL) { - goto end; - } - if (mbstowcs(wname, name, wnamelen - 1) == -1) { - goto end; +/* taken from hotspot and slightly adjusted for jli lib; + * creates a UNC/ELP path from input 'path' + * the return buffer is allocated in C heap and needs to be freed using + * JLI_MemFree by the caller. + */ +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*) JLI_MemAlloc(path_len * sizeof(wchar_t)); + 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*) JLI_MemAlloc((path_len + 7) * sizeof(wchar_t)); + if (wpath != NULL) { + wcscpy(wpath, L"\\\\?\\UNC\0"); + *err = mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len); + } else { + *err = ENOMEM; + } } - wname[wnamelen - 1] = L'\0'; - wfullname = _wfullpath(wfullname, wname, 0); - if (wfullname == NULL) { - goto end; + } else { + wpath = (wchar_t*) JLI_MemAlloc((path_len + 4) * sizeof(wchar_t)); + if (wpath != NULL) { + wcscpy(wpath, L"\\\\?\\\0"); + *err = mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len); + } else { + *err = ENOMEM; } - - wfullnamelen = wcslen(wfullname); - if (wfullnamelen > 247) { - elplen = wcslen(ELP_PREFIX); - wfullname_w_prefix = (wchar_t*) malloc((elplen+wfullnamelen+1)*sizeof(wchar_t)); - wcscpy(wfullname_w_prefix, ELP_PREFIX); - wcscpy(wfullname_w_prefix+elplen, wfullname); + } + return wpath; +} - h = CreateFileW(wfullname_w_prefix, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (h == INVALID_HANDLE_VALUE) { - goto end; - } - /* associates fd with handle */ - fd = _open_osfhandle((intptr_t)h, _O_RDONLY); +int JLI_Open(const char* name, int flags) { + int fd; + if (strlen(name) < MAX_PATH) { + fd = _open(name, flags); + } else { + errno_t err = ERROR_SUCCESS; + wchar_t* wpath = create_unc_path(name, &err); + if (err != ERROR_SUCCESS) { + if (wpath != NULL) JLI_MemFree(wpath); + errno = err; + return -1; } -end: - free(wname); - free(wfullname); - free(wfullname_w_prefix); + fd = _wopen(wpath, flags); + if (fd == -1) { + errno = GetLastError(); + } + JLI_MemFree(wpath); } return fd; } - - JNIEXPORT void JNICALL JLI_ReportErrorMessage(const char* fmt, ...) { va_list vl; diff -r b34bcfbcc2fd -r dad2c80ae0b2 test/jdk/tools/launcher/Arrrghs.java --- a/test/jdk/tools/launcher/Arrrghs.java Fri Apr 05 07:59:13 2019 +0200 +++ b/test/jdk/tools/launcher/Arrrghs.java Tue Apr 02 13:54:00 2019 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /** * @test * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938 - * 6894719 6968053 7151434 7146424 8007333 8077822 8143640 8132379 + * 6894719 6968053 7151434 7146424 8007333 8077822 8143640 8132379 8218547 * @summary Argument parsing validation. * @modules jdk.compiler * jdk.zipfs @@ -36,6 +36,9 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -55,20 +58,6 @@ * */ - /* - * SIGH, On Windows all strings are quoted, we need to unwrap it - */ - private static String removeExtraQuotes(String in) { - if (isWindows) { - // Trim the string and remove the enclosed quotes if any. - in = in.trim(); - if (in.startsWith("\"") && in.endsWith("\"")) { - return in.substring(1, in.length()-1); - } - } - return in; - } - // the pattern we hope to see in the output static final Pattern ArgPattern = Pattern.compile("\\s*argv\\[[0-9]*\\].*=.*"); @@ -490,6 +479,27 @@ } /* + * Tests -jar command on a jar file with "long" (> 260 chars) full path on Windows + */ + @Test + void testLongPathJarFile() throws IOException { + if (!isWindows) { + return; + } + // put the jar file to a location with long path + String longPathPart = "longpathtest_longpathtest/"; + String longPathStr = longPathPart.repeat(15); + Path longPath = Paths.get(longPathStr); + Path jarPath = Files.createDirectories(longPath).resolve("elp.jar"); + File elp = jarPath.toFile(); + createJar(elp, new File("Foo"), "public static void main(String[] args){ System.out.println(\"Hello from ELP\"); }"); + System.out.println("execute " + elp.getAbsolutePath()); + TestResult tr = doExec(javaCmd, "-jar", elp.getAbsolutePath()); + tr.checkPositive(); + tr.contains("Hello from ELP"); + } + + /* * Tests various dispositions of the main method, these tests are limited * to English locales as they check for error messages that are localized. */