8307887: (fs) Files.createSymbolicLink throws less specific exception when in developer mode and file already exists

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2023-06-06 15:14:57 +00:00
parent ca6f07f9ab
commit d709c25cbf
4 changed files with 41 additions and 24 deletions

View File

@ -238,9 +238,9 @@ class WindowsFileCopy {
} else {
String linkTarget = WindowsLinkSupport.readLink(source);
int flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
CreateSymbolicLink(targetPath,
WindowsPath.addPrefixIfNeeded(linkTarget),
flags);
WindowsLinkSupport.createSymbolicLink(targetPath,
WindowsPath.addPrefixIfNeeded(linkTarget),
flags);
}
} catch (WindowsException x) {
x.rethrowAsIOException(target);
@ -441,9 +441,9 @@ class WindowsFileCopy {
CreateDirectory(targetPath, 0L);
} else {
String linkTarget = WindowsLinkSupport.readLink(source);
CreateSymbolicLink(targetPath,
WindowsPath.addPrefixIfNeeded(linkTarget),
SYMBOLIC_LINK_FLAG_DIRECTORY);
WindowsLinkSupport.createSymbolicLink(targetPath,
WindowsPath.addPrefixIfNeeded(linkTarget),
SYMBOLIC_LINK_FLAG_DIRECTORY);
}
} catch (WindowsException x) {
x.rethrowAsIOException(target);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2023, 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
@ -594,9 +594,9 @@ class WindowsFileSystemProvider
// create the link
try {
CreateSymbolicLink(link.getPathForWin32Calls(),
WindowsPath.addPrefixIfNeeded(target.toString()),
flags);
WindowsLinkSupport.createSymbolicLink(link.getPathForWin32Calls(),
WindowsPath.addPrefixIfNeeded(target.toString()),
flags);
} catch (WindowsException x) {
if (x.lastError() == ERROR_INVALID_REPARSE_DATA) {
x.rethrowAsIOException(link, target);

View File

@ -45,6 +45,36 @@ class WindowsLinkSupport {
private WindowsLinkSupport() {
}
/**
* Creates a symbolic link, retyring if not privileged
*/
static void createSymbolicLink(String link, String target, int flags)
throws WindowsException
{
try {
CreateSymbolicLink(link, target, flags);
} catch (WindowsException x) {
// Retry if the privilege to create symbolic links is not held
if (x.lastError() == ERROR_PRIVILEGE_NOT_HELD) {
flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
try {
CreateSymbolicLink(link, target, flags);
return;
} catch (WindowsException y) {
// Throw an exception if and only if it is not due to symbolic link creation
// privilege not being held (ERROR_PRIVILEGE_NOT_HELD) nor the
// SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE flag not being recognized
// (ERROR_INVALID_PARAMETER). The latter will occur for Windows builds
// older than 14972.
int lastError = y.lastError();
if (lastError != ERROR_PRIVILEGE_NOT_HELD && lastError != ERROR_INVALID_PARAMETER)
throw y;
}
}
throw x;
}
}
/**
* Returns the target of a symbolic link
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2023, 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
@ -975,19 +975,6 @@ class WindowsNativeDispatcher {
try {
CreateSymbolicLink0(linkBuffer.address(), targetBuffer.address(),
flags);
} catch (WindowsException x) {
if (x.lastError() == ERROR_PRIVILEGE_NOT_HELD) {
flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
try {
CreateSymbolicLink0(linkBuffer.address(),
targetBuffer.address(), flags);
return;
} catch (WindowsException ignored) {
// Will fail with ERROR_INVALID_PARAMETER for Windows
// builds older than 14972.
}
}
throw x;
} finally {
targetBuffer.release();
linkBuffer.release();