JBR-4602 Unexpected NoSuchFileException running Rider test

This reverts commits for JBR-3680, JBR-4118, and JBR-4485.
This commit is contained in:
Maxim Kartashev
2022-06-27 15:55:26 +03:00
committed by jbrbot
parent 16de79785a
commit dece15e9df
14 changed files with 55 additions and 999 deletions

View File

@@ -25,8 +25,6 @@
package java.nio.file;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicWithKeyFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.io.Closeable;
import java.io.IOException;
@@ -219,11 +217,7 @@ class FileTreeWalker implements Closeable {
// links then a link target might not exist so get attributes of link
BasicFileAttributes attrs;
try {
BasicFileAttributeView view = Files.getFileAttributeView(file, BasicWithKeyFileAttributeView.class, linkOptions);
if (view == null) {
view = Files.getFileAttributeView(file, BasicFileAttributeView.class, linkOptions);
}
attrs = view.readAttributes();
attrs = Files.readAttributes(file, BasicFileAttributes.class, linkOptions);
} catch (IOException ioe) {
if (!followLinks)
throw ioe;

View File

@@ -1,38 +0,0 @@
/*
* Copyright (c) 2007, 2011, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.nio.file.attribute;
import java.io.IOException;
/**
* Similar to {@link BasicFileAttributeView} with a hint to implementors
* to retrieve a valid {@link BasicFileAttributes#fileKey()} if possible, even
* at a performance cost.
*/
public interface BasicWithKeyFileAttributeView
extends BasicFileAttributeView {
}

View File

@@ -41,16 +41,16 @@ import static sun.nio.fs.WindowsConstants.*;
class WindowsDirectoryStream
implements DirectoryStream<Path>
{
private static final int NATIVE_BUFFER_SIZE = 8192;
private final WindowsPath dir;
private final DirectoryStream.Filter<? super Path> filter;
// Query directory information data structure
private final QueryDirectoryInformation queryDirectoryInformation;
// handle to directory
private final long handle;
// first entry in the directory
private final String firstName;
// Buffer used to receive file entries from NtQueryDirectoryInformation calls
private final NativeBuffer queryDirectoryInformationBuffer;
// buffer for WIN32_FIND_DATA structure that receives information about file
private final NativeBuffer findDataBuffer;
private final Object closeLock = new Object();
@@ -65,15 +65,21 @@ class WindowsDirectoryStream
this.dir = dir;
this.filter = filter;
this.queryDirectoryInformationBuffer = NativeBuffers.getNativeBuffer(NATIVE_BUFFER_SIZE);
try {
// Open the directory for reading and read the first set of entries in the native buffer
// Need to append * or \* to match entries in directory.
String search = dir.getPathForWin32Calls();
this.queryDirectoryInformation = OpenNtQueryDirectoryInformation(search, this.queryDirectoryInformationBuffer);
} catch (WindowsException x) {
// Release the buffer, as this instance is not fully constructed
this.queryDirectoryInformationBuffer.release();
char last = search.charAt(search.length() -1);
if (last == ':' || last == '\\') {
search += "*";
} else {
search += "\\*";
}
FirstFile first = FindFirstFile(search);
this.handle = first.handle();
this.firstName = first.name();
this.findDataBuffer = WindowsFileAttributes.getBufferForFindData();
} catch (WindowsException x) {
if (x.lastError() == ERROR_DIRECTORY) {
throw new NotDirectoryException(dir.getPathForExceptionMessage());
}
@@ -93,9 +99,9 @@ class WindowsDirectoryStream
return;
isOpen = false;
}
queryDirectoryInformationBuffer.release();
findDataBuffer.release();
try {
CloseNtQueryDirectoryInformation(queryDirectoryInformation);
FindClose(handle);
} catch (WindowsException x) {
x.rethrowAsIOException(dir);
}
@@ -109,20 +115,20 @@ class WindowsDirectoryStream
synchronized (this) {
if (iterator != null)
throw new IllegalStateException("Iterator already obtained");
iterator = new WindowsDirectoryIterator();
iterator = new WindowsDirectoryIterator(firstName);
return iterator;
}
}
private class WindowsDirectoryIterator implements Iterator<Path> {
private boolean atEof;
private String first;
private Path nextEntry;
private String prefix;
private int nextOffset;
WindowsDirectoryIterator() {
WindowsDirectoryIterator(String first) {
atEof = false;
nextOffset = 0;
this.first = first;
if (dir.needsSlashWhenResolving()) {
prefix = dir.toString() + "\\";
} else {
@@ -150,48 +156,44 @@ class WindowsDirectoryStream
// reads next directory entry
private Path readNextEntry() {
// handle first element returned by search
if (first != null) {
nextEntry = isSelfOrParent(first) ? null : acceptEntry(first, null);
first = null;
if (nextEntry != null)
return nextEntry;
}
for (;;) {
String name;
String name = null;
WindowsFileAttributes attrs;
// synchronize on closeLock to prevent close while reading
synchronized (closeLock) {
// Fetch next set of entries if we don't have anything available in buffer
if (!isOpen) {
try {
if (isOpen) {
name = FindNextFile(handle, findDataBuffer.address());
}
} catch (WindowsException x) {
IOException ioe = x.asIOException(dir);
throw new DirectoryIteratorException(ioe);
}
// NO_MORE_FILES or stream closed
if (name == null) {
atEof = true;
return null;
}
if (nextOffset < 0) {
try {
atEof = !NextNtQueryDirectoryInformation(queryDirectoryInformation, queryDirectoryInformationBuffer);
} catch (WindowsException x) {
IOException ioe = x.asIOException(dir);
throw new DirectoryIteratorException(ioe);
}
if (atEof) {
return null;
}
nextOffset = 0;
}
long dirInformationAddress = queryDirectoryInformationBuffer.address() + nextOffset;
int nextEntryOffset = WindowsFileAttributes.getNextOffsetFromFileDirInformation(
queryDirectoryInformation, dirInformationAddress);
nextOffset = nextEntryOffset == 0 ? -1 : nextOffset + nextEntryOffset;
if (nextOffset > NATIVE_BUFFER_SIZE - WindowsFileAttributes.SIZEOF_FILE_DIRECTORY_INFORMATION) {
// The offset to the next data structure sometimes points past the end of the buffer.
// Treat this as there are no more data (and hope NextNtQueryDirectoryInformation()
// didn't write past the allocated memory).
nextOffset = -1;
}
name = WindowsFileAttributes.getFileNameFromFileDirInformation(
queryDirectoryInformation, dirInformationAddress);
if (isSelfOrParent(name)) {
// Skip "." and ".."
// ignore link to self and parent directories
if (isSelfOrParent(name))
continue;
}
attrs = WindowsFileAttributes.fromFileDirInformation(queryDirectoryInformation, dirInformationAddress);
// grab the attributes from the WIN32_FIND_DATA structure
// (needs to be done while holding closeLock because close
// will release the buffer)
attrs = WindowsFileAttributes
.fromFindData(findDataBuffer.address());
}
// return entry if accepted by filter

View File

@@ -148,23 +148,6 @@ class WindowsFileAttributeViews {
}
}
private static class BasicWithKey extends Basic {
BasicWithKey(WindowsPath file, boolean followLinks) {
super(file, followLinks);
}
@Override
public WindowsFileAttributes readAttributes() throws IOException {
file.checkRead();
try {
return WindowsFileAttributes.getWithFileKey(file, followLinks);
} catch (WindowsException x) {
x.rethrowAsIOException(file);
return null; // keep compiler happy
}
}
}
static class Dos extends Basic implements DosFileAttributeView {
private static final String READONLY_NAME = "readonly";
private static final String ARCHIVE_NAME = "archive";
@@ -304,10 +287,6 @@ class WindowsFileAttributeViews {
return new Basic(file, followLinks);
}
static Basic createBasicWithKeyView(WindowsPath file, boolean followLinks) {
return new BasicWithKey(file, followLinks);
}
static Dos createDosView(WindowsPath file, boolean followLinks) {
return new Dos(file, followLinks);
}

View File

@@ -108,69 +108,10 @@ class WindowsFileAttributes
private static final short OFFSETOF_FIND_DATA_SIZELOW = 32;
private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36;
// used to adjust values between Windows and java epochs
private static final long WINDOWS_EPOCH_IN_MICROS = -11644473600000000L;
private static final long WINDOWS_EPOCH_IN_100NS = -116444736000000000L;
/**
* typedef struct _FILE_ID_FULL_DIR_INFORMATION {
* ULONG NextEntryOffset; // offset = 0
* ULONG FileIndex; // offset = 4
* LARGE_INTEGER CreationTime; // offset = 8
* LARGE_INTEGER LastAccessTime; // offset = 16
* LARGE_INTEGER LastWriteTime; // offset = 24
* LARGE_INTEGER ChangeTime; // offset = 32
* LARGE_INTEGER EndOfFile; // offset = 40
* LARGE_INTEGER AllocationSize; // offset = 48
* ULONG FileAttributes; // offset = 56
* ULONG FileNameLength; // offset = 60
* ULONG EaSize; // offset = 64
* LARGE_INTEGER FileId; // offset = 72
* WCHAR FileName[1]; // offset = 80
* } FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
*/
private static final int OFFSETOF_FULL_DIR_INFO_NEXT_ENTRY_OFFSET = 0;
private static final int OFFSETOF_FULL_DIR_INFO_CREATION_TIME = 8;
private static final int OFFSETOF_FULL_DIR_INFO_LAST_ACCESS_TIME = 16;
private static final int OFFSETOF_FULL_DIR_INFO_LAST_WRITE_TIME = 24;
private static final int OFFSETOF_FULL_DIR_INFO_END_OF_FILE = 40;
private static final int OFFSETOF_FULL_DIR_INFO_FILE_ATTRIBUTES = 56;
private static final int OFFSETOF_FULL_DIR_INFO_FILENAME_LENGTH = 60;
private static final int OFFSETOF_FULL_DIR_INFO_EA_SIZE = 64;
private static final int OFFSETOF_FULL_DIR_INFO_FILE_ID = 72;
private static final int OFFSETOF_FULL_DIR_INFO_FILENAME = 80;
/**
* struct _FILE_DIRECTORY_INFORMATION {
* ULONG NextEntryOffset; // offset = 0
* ULONG FileIndex; // offset = 4
* LARGE_INTEGER CreationTime; // offset = 8
* LARGE_INTEGER LastAccessTime; // offset = 16
* LARGE_INTEGER LastWriteTime; // offset = 24
* LARGE_INTEGER ChangeTime; // offset = 32
* LARGE_INTEGER EndOfFile; // offset = 40
* LARGE_INTEGER AllocationSize; // offset = 48
* ULONG FileAttributes; // offset = 56
* ULONG FileNameLength; // offset = 60
* WCHAR FileName[1]; // offset = 64
* }
*/
private static final int OFFSETOF_DIR_INFO_NEXT_ENTRY_OFFSET = 0;
private static final int OFFSETOF_DIR_INFO_CREATION_TIME = 8;
private static final int OFFSETOF_DIR_INFO_LAST_ACCESS_TIME = 16;
private static final int OFFSETOF_DIR_INFO_LAST_WRITE_TIME = 24;
private static final int OFFSETOF_DIR_INFO_END_OF_FILE = 40;
private static final int OFFSETOF_DIR_INFO_FILE_ATTRIBUTES = 56;
private static final int OFFSETOF_DIR_INFO_FILENAME_LENGTH = 60;
private static final int OFFSETOF_DIR_INFO_FILENAME = 64;
// Minimum sane size of either _FILE_DIRECTORY_INFORMATION or _FILE_ID_FULL_DIR_INFORMATION
public static final int SIZEOF_FILE_DIRECTORY_INFORMATION = 65;
// used to adjust values between Windows and java epoch
private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
// indicates if accurate metadata is required (interesting on NTFS only)
private static final boolean ensureAccurateMetadata;
static {
@@ -192,9 +133,6 @@ class WindowsFileAttributes
private final int fileIndexHigh;
private final int fileIndexLow;
// created lazily
private volatile WindowsFileKey key;
/**
* Convert 64-bit value representing the number of 100-nanosecond intervals
* since January 1, 1601 to a FileTime.
@@ -319,83 +257,6 @@ class WindowsFileAttributes
0); // fileIndexLow
}
/**
* Create a WindowsFileAttributes from either a FILE_ID_FULL_DIR_INFORMATION
* or FILE_DIRECTORY_INFORMATION structure depending on the value of
* QueryDirectoryInformation.supportsFullIdInfo().
*/
static WindowsFileAttributes fromFileDirInformation(QueryDirectoryInformation info, long address) {
if (info.supportsFullIdInfo()) { // address points to struct FILE_ID_FULL_DIR_INFORMATION
int fileAttrs = unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_FILE_ATTRIBUTES);
long creationTime = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_CREATION_TIME);
long lastAccessTime = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_LAST_ACCESS_TIME);
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_LAST_WRITE_TIME);
long size = unsafe.getLong(address + OFFSETOF_FULL_DIR_INFO_END_OF_FILE);
int reparseTag = isReparsePoint(fileAttrs) ?
unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_EA_SIZE) : 0;
int volSerialNumber = info.volSerialNumber();
int fileIndexLow = unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_FILE_ID);
int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FULL_DIR_INFO_FILE_ID + 4);
return new WindowsFileAttributes(fileAttrs,
creationTime,
lastAccessTime,
lastWriteTime,
size,
reparseTag,
volSerialNumber,
fileIndexHigh, // fileIndexHigh
fileIndexLow); // fileIndexLow
} else { // address points to FILE_DIRECTORY_INFORMATION
int fileAttrs = unsafe.getInt(address + OFFSETOF_DIR_INFO_FILE_ATTRIBUTES);
long creationTime = unsafe.getLong(address + OFFSETOF_DIR_INFO_CREATION_TIME);
long lastAccessTime = unsafe.getLong(address + OFFSETOF_DIR_INFO_LAST_ACCESS_TIME);
long lastWriteTime = unsafe.getLong(address + OFFSETOF_DIR_INFO_LAST_WRITE_TIME);
long size = unsafe.getLong(address + OFFSETOF_DIR_INFO_END_OF_FILE);
int reparseTag = 0;
// Don't provide the real serial number as the reset of the code assumes that presence of
// the volume serial means that the file id is also valid, which isn't the case here.
// This will make comparing Path's for equality slower as the file id serves as
// a unique file key (@see fileKey()).
int volSerialNumber = 0;
int fileIndexLow = 0;
int fileIndexHigh = 0;
return new WindowsFileAttributes(fileAttrs,
creationTime,
lastAccessTime,
lastWriteTime,
size,
reparseTag,
volSerialNumber,
fileIndexHigh,
fileIndexLow);
}
}
static int getNextOffsetFromFileDirInformation(QueryDirectoryInformation info, long address) {
return unsafe.getInt(address
+ (info.supportsFullIdInfo() ? OFFSETOF_FULL_DIR_INFO_NEXT_ENTRY_OFFSET
: OFFSETOF_DIR_INFO_NEXT_ENTRY_OFFSET));
}
static String getFileNameFromFileDirInformation(QueryDirectoryInformation info, long address) {
// copy the name
int nameLengthInBytes = unsafe.getInt(address
+ (info.supportsFullIdInfo() ? OFFSETOF_FULL_DIR_INFO_FILENAME_LENGTH
: OFFSETOF_DIR_INFO_FILENAME_LENGTH));
if ((nameLengthInBytes % 2) != 0) {
throw new AssertionError("FileNameLength is not a multiple of 2");
}
char[] nameAsArray = new char[nameLengthInBytes/2];
unsafe.copyMemory(null,
address + (info.supportsFullIdInfo() ? OFFSETOF_FULL_DIR_INFO_FILENAME
: OFFSETOF_DIR_INFO_FILENAME),
nameAsArray,
Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes);
return new String(nameAsArray);
}
/**
* Reads the attributes of an open file
*/
@@ -473,15 +334,6 @@ class WindowsFileAttributes
}
// file is reparse point so need to open file to get attributes
return getWithFileKey(path, followLinks);
}
/**
* Returns attributes of given file.
*/
static WindowsFileAttributes getWithFileKey(WindowsPath path, boolean followLinks)
throws WindowsException
{
long handle = path.openForReadAttributeAccess(followLinks);
try {
return readAttributes(handle);
@@ -549,17 +401,7 @@ class WindowsFileAttributes
@Override
public Object fileKey() {
if (volSerialNumber == 0) {
return null;
}
if (key == null) {
synchronized (this) {
if (key == null) {
key = new WindowsFileKey(volSerialNumber, ((long)fileIndexHigh << 32) + fileIndexLow);
}
}
}
return key;
return null;
}
// package private

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2008, 2009, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.fs;
/**
* Container for volume/file id to uniquely identify file.
*/
class WindowsFileKey {
private final int volSerialNumber;
private final long fileId;
WindowsFileKey(int volSerialNumber, long fileId) {
this.volSerialNumber = volSerialNumber;
this.fileId = fileId;
}
@Override
public int hashCode() {
return (volSerialNumber ^ (volSerialNumber >>> 16)) +
(int)(fileId ^ (fileId >>> 32));
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof WindowsFileKey))
return false;
WindowsFileKey other = (WindowsFileKey)obj;
return (this.volSerialNumber == other.volSerialNumber) && (this.fileId == other.fileId);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("(volId=")
.append(Integer.toHexString(volSerialNumber))
.append(",fileId=")
.append(Long.toHexString(fileId))
.append(')');
return sb.toString();
}
}

View File

@@ -166,8 +166,6 @@ class WindowsFileSystemProvider
boolean followLinks = Util.followLinks(options);
if (view == BasicFileAttributeView.class)
return (V) WindowsFileAttributeViews.createBasicView(file, followLinks);
if (view == BasicWithKeyFileAttributeView.class)
return (V) WindowsFileAttributeViews.createBasicWithKeyView(file, followLinks);
if (view == DosFileAttributeView.class)
return (V) WindowsFileAttributeViews.createDosView(file, followLinks);
if (view == AclFileAttributeView.class)
@@ -205,8 +203,6 @@ class WindowsFileSystemProvider
boolean followLinks = Util.followLinks(options);
if (name.equals("basic"))
return WindowsFileAttributeViews.createBasicView(file, followLinks);
if (name.equals("basicwithkey"))
return WindowsFileAttributeViews.createBasicWithKeyView(file, followLinks);
if (name.equals("dos"))
return WindowsFileAttributeViews.createDosView(file, followLinks);
if (name.equals("acl"))

View File

@@ -316,52 +316,6 @@ class WindowsNativeDispatcher {
*/
static native void FindClose(long handle) throws WindowsException;
static QueryDirectoryInformation OpenNtQueryDirectoryInformation(String path, NativeBuffer buffer) throws WindowsException {
try (NativeBuffer pathBuffer = asNativeBuffer(path)) {
long comp = Blocker.begin();
try {
QueryDirectoryInformation data = new QueryDirectoryInformation();
OpenNtQueryDirectoryInformation0(pathBuffer.address(), buffer.address(), buffer.size(), data);
return data;
} finally {
Blocker.end(comp);
}
}
}
static class QueryDirectoryInformation {
private long handle;
private int volSerialNumber;
/**
* Set by OpenNtQueryDirectoryInformation0() to
* true if dealing with struct FILE_ID_FULL_DIR_INFORMATION
* and to false if it's struct FILE_DIRECTORY_INFORMATION.
*/
private boolean supportsFullIdInfo;
private QueryDirectoryInformation() { }
public long handle() { return handle; }
public int volSerialNumber() { return volSerialNumber; }
public boolean supportsFullIdInfo() { return supportsFullIdInfo; }
}
private static native void OpenNtQueryDirectoryInformation0(long lpFileName, long buffer, int bufferSize, QueryDirectoryInformation obj)
throws WindowsException;
static boolean NextNtQueryDirectoryInformation(QueryDirectoryInformation data, NativeBuffer buffer) throws WindowsException {
long comp = Blocker.begin();
try {
return NextNtQueryDirectoryInformation0(data.handle(), data.supportsFullIdInfo(), buffer.address(), buffer.size());
} finally {
Blocker.end(comp);
}
}
private static native boolean NextNtQueryDirectoryInformation0(long handle, boolean supportsFullIdInfo, long buffer, int bufferSize)
throws WindowsException;
static void CloseNtQueryDirectoryInformation(QueryDirectoryInformation data) throws WindowsException {
CloseHandle(data.handle);
}
/**
* GetFileInformationByHandle(
* HANDLE hFile,

View File

@@ -38,8 +38,6 @@
#include "jni_util.h"
#include "jlong.h"
#include "ntifs_min.h"
#include "sun_nio_fs_WindowsNativeDispatcher.h"
/**
@@ -52,10 +50,6 @@ static jfieldID findFirst_attributes;
static jfieldID findStream_handle;
static jfieldID findStream_name;
static jfieldID queryDirectoryInformation_handle;
static jfieldID queryDirectoryInformation_volSerialNumber;
static jfieldID queryDirectoryInformation_supportsFullIdInfo;
static jfieldID volumeInfo_fsName;
static jfieldID volumeInfo_volName;
static jfieldID volumeInfo_volSN;
@@ -77,13 +71,6 @@ static jfieldID completionStatus_error;
static jfieldID completionStatus_bytesTransferred;
static jfieldID completionStatus_completionKey;
typedef NTSYSCALLAPI NTSTATUS(NTAPI* NtQueryDirectoryFile_Proc) (HANDLE, HANDLE, PIO_APC_ROUTINE,
PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN);
typedef ULONG(NTAPI* RtlNtStatusToDosError_Proc) (NTSTATUS);
static NtQueryDirectoryFile_Proc NtQueryDirectoryFile_func;
static RtlNtStatusToDosError_Proc RtlNtStatusToDosError_func;
static void throwWindowsException(JNIEnv* env, DWORD lastError) {
jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException",
"(I)V", lastError);
@@ -100,7 +87,6 @@ JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
{
jclass clazz;
HMODULE h;
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile");
CHECK_NULL(clazz);
@@ -118,15 +104,6 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
CHECK_NULL(findStream_name);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$QueryDirectoryInformation");
CHECK_NULL(clazz);
queryDirectoryInformation_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
CHECK_NULL(queryDirectoryInformation_handle);
queryDirectoryInformation_volSerialNumber = (*env)->GetFieldID(env, clazz, "volSerialNumber", "I");
CHECK_NULL(queryDirectoryInformation_volSerialNumber);
queryDirectoryInformation_supportsFullIdInfo = (*env)->GetFieldID(env, clazz, "supportsFullIdInfo", "Z");
CHECK_NULL(queryDirectoryInformation_supportsFullIdInfo);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation");
CHECK_NULL(clazz);
volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;");
@@ -171,16 +148,6 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
CHECK_NULL(completionStatus_bytesTransferred);
completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J");
CHECK_NULL(completionStatus_completionKey);
// get handle to ntdll
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
L"ntdll.dll", &h) != 0)
{
NtQueryDirectoryFile_func =
(NtQueryDirectoryFile_Proc)GetProcAddress(h, "NtQueryDirectoryFile");
RtlNtStatusToDosError_func =
(RtlNtStatusToDosError_Proc)GetProcAddress(h, "RtlNtStatusToDosError");
}
}
JNIEXPORT jlong JNICALL
@@ -460,148 +427,6 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindClose(JNIEnv* env, jclass this,
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_OpenNtQueryDirectoryInformation0(JNIEnv* env, jclass this,
jlong address, jlong bufferAddress, jint bufferSize, jobject obj)
{
LPCWSTR lpFileName = jlong_to_ptr(address);
BOOL ok;
BY_HANDLE_FILE_INFORMATION info;
HANDLE handle;
NTSTATUS status;
ULONG win32ErrorCode;
IO_STATUS_BLOCK ioStatusBlock;
if ((NtQueryDirectoryFile_func == NULL) || (RtlNtStatusToDosError_func == NULL)) {
JNU_ThrowInternalError(env, "Should not get here");
return;
}
handle = CreateFileW(lpFileName, FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (handle == INVALID_HANDLE_VALUE) {
throwWindowsException(env, GetLastError());
return;
}
jboolean supportsFullIdInfo = JNI_TRUE;
status = NtQueryDirectoryFile_func(
handle, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&ioStatusBlock, // IoStatusBlock
jlong_to_ptr(bufferAddress), // FileInformation
bufferSize, // Length
FileIdFullDirectoryInformation, // FileInformationClass
FALSE, // ReturnSingleEntry
NULL, // FileName
FALSE); // RestartScan
if (!NT_SUCCESS(status)) {
/*
* NtQueryDirectoryFile returns STATUS_INVALID_PARAMETER when
* asked to enumerate an invalid directory (ie it is a file
* instead of a directory). Verify that is the actual cause
* of the error.
*/
if (status == STATUS_INVALID_PARAMETER) {
DWORD attributes = GetFileAttributesW(lpFileName);
const jboolean areAttributesValid = (attributes != INVALID_FILE_ATTRIBUTES);
const jboolean isDirectory = areAttributesValid
&& (attributes & FILE_ATTRIBUTE_DIRECTORY);
if (!areAttributesValid || !isDirectory) {
if (areAttributesValid && !isDirectory) status = STATUS_NOT_A_DIRECTORY;
win32ErrorCode = RtlNtStatusToDosError_func(status);
throwWindowsException(env, win32ErrorCode);
CloseHandle(handle);
return;
}
/* If it's a directory, we can have another go by asking for
* less information with the FileDirectoryInformation
* information class. This works on a mounted Google Drive, for instance.
*/
status = NtQueryDirectoryFile_func(
handle, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&ioStatusBlock, // IoStatusBlock
jlong_to_ptr(bufferAddress), // FileInformation
bufferSize, // Length
FileDirectoryInformation, // FileInformationClass
FALSE, // ReturnSingleEntry
NULL, // FileName
FALSE); // RestartScan
if (!NT_SUCCESS(status)) {
win32ErrorCode = RtlNtStatusToDosError_func(status);
throwWindowsException(env, win32ErrorCode);
CloseHandle(handle);
return;
}
supportsFullIdInfo = JNI_FALSE;
}
}
// This call allows retrieving the volume ID of this directory (and all its entries)
ok = GetFileInformationByHandle(handle, &info);
if (!ok) {
throwWindowsException(env, GetLastError());
CloseHandle(handle);
return;
}
(*env)->SetLongField(env, obj, queryDirectoryInformation_handle, ptr_to_jlong(handle));
(*env)->SetIntField(env, obj, queryDirectoryInformation_volSerialNumber, info.dwVolumeSerialNumber);
(*env)->SetBooleanField(env, obj, queryDirectoryInformation_supportsFullIdInfo, supportsFullIdInfo);
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_NextNtQueryDirectoryInformation0(JNIEnv* env, jclass this,
jlong handle, jboolean supportsFullIdInfo, jlong address, jint size)
{
HANDLE h = (HANDLE)jlong_to_ptr(handle);
ULONG win32ErrorCode;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
if ((NtQueryDirectoryFile_func == NULL) || (RtlNtStatusToDosError_func == NULL)) {
JNU_ThrowInternalError(env, "Should not get here");
return JNI_FALSE;
}
status = NtQueryDirectoryFile_func(
h, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&ioStatusBlock, // IoStatusBlock
jlong_to_ptr(address), // FileInformation
size, // Length
supportsFullIdInfo ? FileIdFullDirectoryInformation
: FileDirectoryInformation, // FileInformationClass
FALSE, // ReturnSingleEntry
NULL, // FileName
FALSE); // RestartScan
if (NT_SUCCESS(status)) {
return JNI_TRUE;
}
// Normal completion: no more files in directory
if (status == STATUS_NO_MORE_FILES) {
return JNI_FALSE;
}
win32ErrorCode = RtlNtStatusToDosError_func(status);
throwWindowsException(env, win32ErrorCode);
return JNI_FALSE;
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByHandle0(JNIEnv* env, jclass this,
jlong handle, jlong address)

View File

@@ -1,160 +0,0 @@
/*
* Copyright (c) 2008, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _NTIFS_MIN_
#define _NTIFS_MIN_
/*
* Copy necessary structures and definitions out of the Windows DDK
* to enable calling NtQueryDirectoryFile()
*/
typedef LONG NTSTATUS;
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWCH Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileFullEaInformation,
FileModeInformation,
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileObjectIdInformation,
FileCompletionInformation,
FileMoveClusterInformation,
FileQuotaInformation,
FileReparsePointInformation,
FileNetworkOpenInformation,
FileAttributeTagInformation,
FileTrackingInformation,
FileIdBothDirectoryInformation,
FileIdFullDirectoryInformation,
FileValidDataLengthInformation,
FileShortNameInformation,
FileIoCompletionNotificationInformation,
FileIoStatusBlockRangeInformation,
FileIoPriorityHintInformation,
FileSfioReserveInformation,
FileSfioVolumeInformation,
FileHardLinkInformation,
FileProcessIdsUsingFileInformation,
FileNormalizedNameInformation,
FileNetworkPhysicalNameInformation,
FileIdGlobalTxDirectoryInformation,
FileIsRemoteDeviceInformation,
FileAttributeCacheInformation,
FileNumaNodeInformation,
FileStandardLinkInformation,
FileRemoteProtocolInformation,
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _FILE_ID_FULL_DIR_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
LARGE_INTEGER FileId;
WCHAR FileName[1];
} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} u;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef VOID
(NTAPI *PIO_APC_ROUTINE)(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryDirectoryFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_ PVOID FileInformation,
_In_ ULONG Length,
_In_ FILE_INFORMATION_CLASS FileInformationClass,
_In_ BOOLEAN ReturnSingleEntry,
_In_opt_ PUNICODE_STRING FileName,
_In_ BOOLEAN RestartScan
);
ULONG
NTAPI
RtlNtStatusToDosError(
NTSTATUS Status
);
#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L)
#define STATUS_NOT_A_DIRECTORY ((NTSTATUS)0xC0000103L)
#endif // _NTIFS_MIN_

View File

@@ -1,109 +0,0 @@
/*
* Copyright 2022 JetBrains s.r.o.
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @summary Verifies that DirectoryStream's iterator works correctly in
* a multi-threaded environment.
* @library ..
* @run main/timeout=240 ParallelHeavy
*/
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.DirectoryIteratorException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ParallelHeavy {
static final int RETRIES = 42;
static final int COUNT_TASKS = 7;
static final int COUNT_FILES = 1024;
static final int COUNT_DIRECTORIES = 1024;
public static void main(String args[]) throws Exception {
final Path testDir = Paths.get(System.getProperty("test.dir", "."));
final Path dir = Files.createTempDirectory(testDir, "ParallelHeavy");
populateDir(dir);
for (int i = 0; i < RETRIES; i++) {
runTest(dir, COUNT_DIRECTORIES + COUNT_FILES - i);
}
}
static void advanceIteratorThenCancel(final DirectoryStream<Path> stream, final Iterator<Path> iterator, int closeAfterReading) {
while (closeAfterReading-- > 0) {
try {
iterator.next();
} catch (NoSuchElementException e) {
System.out.println("NoSuchElementException, stream may have been closed, remaining to read "
+ closeAfterReading + ", thread " + Thread.currentThread().getId());
break;
}
Thread.yield();
}
try {
stream.close();
} catch (IOException ignored) {}
}
static void runTest(final Path dir, int closeAfterReading) throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
final Iterator<Path> streamIterator = stream.iterator();
final ExecutorService pool = Executors.newCachedThreadPool();
try {
for (int i = 0; i < COUNT_TASKS - 1; i++) {
pool.submit(() -> advanceIteratorThenCancel(stream, streamIterator, closeAfterReading));
}
pool.submit(() -> advanceIteratorThenCancel(stream, streamIterator, COUNT_FILES));
try {
pool.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException ignored) {}
} finally {
pool.shutdown();
}
} catch (DirectoryIteratorException ex) {
throw ex.getCause();
}
}
static void populateDir(final Path root) throws IOException {
for (int i = 0; i < COUNT_DIRECTORIES; i++) {
final Path newDir = root.resolve("directory-number-" + i);
Files.createDirectory(newDir);
}
for (int i = 0; i < COUNT_FILES; i++) {
final Path newFile = root.resolve("longer-file-name-number-" + i);
Files.createFile(newFile);
}
}
}

View File

@@ -42,8 +42,6 @@ import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.nio.file.spi.FileSystemProvider;
import java.util.Iterator;
@@ -325,44 +323,12 @@ class FaultyFileSystem extends FileSystem {
return Files.readAttributes(unwrap(file), attributes, options);
}
private class FaultyBasicFileAttributeView implements BasicFileAttributeView {
private final Path file;
private final LinkOption[] options;
public FaultyBasicFileAttributeView(final Path file, final LinkOption... options) {
this.file = file;
this.options = options;
}
@Override
public String name() {
return "faulty";
}
@Override
public BasicFileAttributes readAttributes() throws IOException {
triggerEx(file, "readAttributes");
return Files.readAttributes(file, BasicFileAttributes.class, options);
}
@Override
public void setTimes(FileTime lastModifiedTime,
FileTime lastAccessTime,
FileTime createTime) throws IOException {
triggerEx(file, "setTimes");
}
}
@Override
public <V extends FileAttributeView> V getFileAttributeView(Path file,
Class<V> type,
LinkOption... options)
{
if (type != BasicFileAttributeView.class) {
return null;
}
return (V)new FaultyBasicFileAttributeView(unwrap(file), options);
return Files.getFileAttributeView(unwrap(file), type, options);
}
@Override

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2021 JetBrains s.r.o.
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
* @test
*
* @requires (os.family == "windows")
*
* @summary Verifies that listing a mounted Google Drive doesn't throw.
*
* @run main GDriveTest
*/
public class GDriveTest {
public static void main(String[] args) throws Exception {
final Path gdrivePath = Path.of("G:\\");
if (Files.exists(gdrivePath)) {
try (Stream<Path> stream = Files.list(gdrivePath)) {
System.out.println(stream.collect(Collectors.toList()));
}
}
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, JetBrains s.r.o.. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary Tests that walkFileTree can find files in a directory with
* non-latin characters in the name (including ones from
* the supplementary plane)
* @library /test/lib
*/
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.FileVisitOption;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.FileVisitResult;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Vector;
import java.util.HashSet;
import jdk.test.lib.Asserts;
public class NonLatin {
// Use non-Latin characters from basic (\u1889) and supplementary (\uD844\uDDD9) Unicode planes
private static final String NON_LATIN_PATH_NAME = "ka-\u1889-supp-\uD844\uDDD9";
public static void main(String args[]) throws Exception {
final Path currentDirPath = Paths.get(".").toAbsolutePath();
Path nonLatinPath = null;
try {
nonLatinPath = currentDirPath.resolve(NON_LATIN_PATH_NAME);
Files.createDirectory(nonLatinPath);
final Path underNonLatinPath = nonLatinPath.resolve("dir");
Files.createDirectory(underNonLatinPath);
} catch (java.nio.file.InvalidPathException e) {
System.out.println("Cannot create the directory with the right name. Test is considered passed");
return;
}
final Vector<String> visitedDirs = new Vector<String>();
Files.walkFileTree(nonLatinPath, new HashSet<FileVisitOption>(), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
visitedDirs.add(dir.toString());
return FileVisitResult.CONTINUE;
}
});
boolean found = false;
for (final String dirName : visitedDirs) {
System.out.println("Found: " + dirName);
found |= dirName.contains(NON_LATIN_PATH_NAME);
}
Asserts.assertTrue(found);
}
}