Skip to content
Permalink
Browse files
8276661: (fs) UserDefinedFileAttributeView no longer works with long …
…path (win)

Reviewed-by: alanb
  • Loading branch information
Brian Burkhalter committed Dec 2, 2021
1 parent 652b5f8 commit 15345e3edcd8beee0d2c3192cfaaf76c7accee1f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 24 deletions.
@@ -174,38 +174,48 @@ String getPathForPermissionCheck() {
// use this path for Win32 calls
// This method will prefix long paths with \\?\ or \\?\UNC as required.
String getPathForWin32Calls() throws WindowsException {
// short absolute paths can be used directly
if (isAbsolute() && path.length() <= MAX_PATH)
return path;
return getPathForWin32Calls(true);
}

String getPathWithPrefixForWin32Calls() throws WindowsException {
return getPathForWin32Calls(false);
}

// return cached values if available
WeakReference<String> ref = pathForWin32Calls;
String resolved = (ref != null) ? ref.get() : null;
if (resolved != null) {
// Win32 path already available
return resolved;
private String getPathForWin32Calls(boolean allowShortPath) throws WindowsException {
if (allowShortPath) {
// short absolute paths can be used directly
if (isAbsolute() && path.length() <= MAX_PATH)
return path;

// returned cached value if possible
WeakReference<String> ref = pathForWin32Calls;
String cached = (ref != null) ? ref.get() : null;
if (cached != null) {
// Win32 path already available
return cached;
}
}

// resolve against default directory
resolved = getAbsolutePath();
String resolved = getAbsolutePath();

// Long paths need to have "." and ".." removed and be prefixed with
// "\\?\". Note that it is okay to remove ".." even when it follows
// a link - for example, it is okay for foo/link/../bar to be changed
// to foo/bar. The reason is that Win32 APIs to access foo/link/../bar
// will access foo/bar anyway (which differs to Unix systems)
if (resolved.length() > MAX_PATH) {
if (resolved.length() > MAX_PATH || !allowShortPath) {
if (resolved.length() > MAX_LONG_PATH) {
throw new WindowsException("Cannot access file with path exceeding "
+ MAX_LONG_PATH + " characters");
}
resolved = addPrefixIfNeeded(GetFullPathName(resolved));
resolved = addPrefix(GetFullPathName(resolved));
}

// cache the resolved path (except drive relative paths as the working
// directory on removal media devices can change during the lifetime
// of the VM)
if (type != WindowsPathType.DRIVE_RELATIVE) {
if (allowShortPath && type != WindowsPathType.DRIVE_RELATIVE) {
synchronized (this) {
pathForWin32Calls = new WeakReference<String>(resolved);
}
@@ -279,14 +289,20 @@ private static boolean isSameDrive(String root1, String root2) {
Character.toUpperCase(root2.charAt(0));
}

// Add long path prefix to path
static String addPrefix(String path) {
if (path.startsWith("\\\\")) {
path = "\\\\?\\UNC" + path.substring(1, path.length());
} else {
path = "\\\\?\\" + path;
}
return path;
}

// Add long path prefix to path if required
static String addPrefixIfNeeded(String path) {
if (path.length() > MAX_PATH) {
if (path.startsWith("\\\\")) {
path = "\\\\?\\UNC" + path.substring(1, path.length());
} else {
path = "\\\\?\\" + path;
}
return addPrefix(path);
}
return path;
}
@@ -61,9 +61,7 @@ private String join(WindowsPath file, String name) throws WindowsException {
throw new IllegalArgumentException("'name' has a root component");
if (namePath.getParent() != null)
throw new IllegalArgumentException("'name' has more than one element");
String path = join(file.getPathForWin32Calls(), name);
WindowsPath wp = WindowsPath.createFromNormalizedPath(wfs, path);
return wp.getPathForWin32Calls();
return join(file.getPathWithPrefixForWin32Calls(), name);
}

private final WindowsPath file;
@@ -242,7 +242,7 @@ public void run() throws IOException {

// We need to run up to MAX_PATH for directories,
// but not quite go over it.
int MAX_PATH = 247;
int MAX_PATH = 250;
int requiredLen = MAX_PATH - len - 2;

// Create a really long directory name.
@@ -252,11 +252,15 @@ public void run() throws IOException {
Files.createDirectory(longPath);

try {
// Try to set absolute path as extended attribute; expect IAE
System.out.println("Testing " + longPath);

// Try to set absolute path as extended attribute;
// expect IAE
tryCatch(IllegalArgumentException.class, new Task() {
public void run() throws IOException {
setEA(longPath, "user:C:\\");
}});
}
});

// Try to set an extended attribute on it.
setEA(longPath, "user:short");

1 comment on commit 15345e3

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 15345e3 Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.