6481955: Uncanonicalized absolute filepath with length 248-260 no longer works (win)
Summary: Uncanonicalized absolute filepath with length 248-260 no longer works (win)
Reviewed-by: alanb
--- a/jdk/src/windows/native/java/io/io_util_md.c Wed Jun 25 08:27:06 2008 -0700
+++ b/jdk/src/windows/native/java/io/io_util_md.c Wed Jun 25 13:58:22 2008 -0700
@@ -104,23 +104,56 @@
}
}
+/*
+ The "abpathlen" is the size of the buffer needed by _wfullpath. If the
+ "path" is a relative path, it is "the length of the current dir" + "the
+ length of the path", if it's "absolute" already, it's the same as
+ pathlen which is the length of "path".
+ */
+WCHAR* prefixAbpath(const WCHAR* path, int pathlen, int abpathlen) {
+ WCHAR* pathbuf = NULL;
+ WCHAR* abpath = NULL;
+
+ abpathlen += 10; //padding
+ abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR));
+ if (abpath) {
+ /* Collapse instances of "foo\.." and ensure absoluteness before
+ going down to prefixing.
+ */
+ if (_wfullpath(abpath, path, abpathlen)) {
+ pathbuf = getPrefixed(abpath, abpathlen);
+ } else {
+ /* _wfullpath fails if the pathlength exceeds 32k wchar.
+ Instead of doing more fancy things we simply copy the
+ ps into the return buffer, the subsequent win32 API will
+ probably fail with FileNotFoundException, which is expected
+ */
+ pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
+ if (pathbuf != 0) {
+ wcscpy(pathbuf, path);
+ }
+ }
+ free(abpath);
+ }
+ return pathbuf;
+}
+
/* If this returns NULL then an exception is pending */
WCHAR*
pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) {
int pathlen = 0;
WCHAR *pathbuf = NULL;
- int max_path = 248; /* Since CreateDirectoryW() has the limit of
- 248 instead of the normal MAX_PATH, we
- use 248 as the max_path to satisfy both
- */
+ int max_path = 248; /* CreateDirectoryW() has the limit of 248 */
+
WITH_UNICODE_STRING(env, path, ps) {
pathlen = wcslen(ps);
if (pathlen != 0) {
if (pathlen > 2 &&
(ps[0] == L'\\' && ps[1] == L'\\' || //UNC
- ps[1] == L':' && ps[2] == L'\\')) { //absolute
+ ps[1] == L':' && ps[2] == L'\\')) //absolute
+ {
if (pathlen > max_path - 1) {
- pathbuf = getPrefixed(ps, pathlen);
+ pathbuf = prefixAbpath(ps, pathlen, pathlen);
} else {
pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
if (pathbuf != 0) {
@@ -132,7 +165,7 @@
its absolute form is bigger than max_path or not, if yes
need to (1)convert it to absolute and (2)prefix. This is
obviously a burden to all relative paths (The current dir/len
- for "dirve & directory" relative path is cached, so we only
+ for "drive & directory" relative path is cached, so we only
calculate it once but for "drive-relative path we call
_wgetdcwd() and wcslen() everytime), but a hit we have
to take if we want to support relative path beyond max_path.
@@ -143,24 +176,7 @@
WCHAR *abpath = NULL;
int dirlen = currentDirLength(ps, pathlen);
if (dirlen + pathlen + 1 > max_path - 1) {
- int abpathlen = dirlen + pathlen + 10;
- abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR));
- if (abpath) {
- if (_wfullpath(abpath, ps, abpathlen)) {
- pathbuf = getPrefixed(abpath, abpathlen);
- } else {
- /* _wfullpath fails if the pathlength exceeds 32k wchar.
- Instead of doing more fancy things we simply copy the
- ps into the return buffer, the subsequent win32 API will
- probably fail with FileNotFoundException, which is expected
- */
- pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
- if (pathbuf != 0) {
- wcscpy(pathbuf, ps);
- }
- }
- free(abpath);
- }
+ pathbuf = prefixAbpath(ps, pathlen, dirlen + pathlen);
} else {
pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
if (pathbuf != 0) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/File/MaxPath.java Wed Jun 25 13:58:22 2008 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ @bug 6481955
+ @summary Path length less than MAX_PATH (260) works on Windows
+ */
+
+import java.io.*;
+
+public class MaxPath {
+ public static void main(String[] args) throws Exception {
+ String osName = System.getProperty("os.name");
+ if (!osName.startsWith("Windows")) {
+ return;
+ }
+ int MAX_PATH = 260;
+ String dir = new File(".").getAbsolutePath() + "\\";
+ String padding = "1234567890123456789012345678901234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890";
+ for (int i = 240 - dir.length(); i < MAX_PATH - dir.length(); i++) {
+ String longname = dir + padding.substring(0, i);
+ try {
+ File f = new File(longname);
+ if (f.createNewFile()) {
+ if (!f.exists() || !f.canRead()) {
+ throw new RuntimeException("Failed at length: " + longname.length());
+ }
+ f.delete();
+ }
+ } catch (IOException e) {
+ System.out.println("Failed at length: " + longname.length());
+ throw e;
+ }
+ }
+ }
+}