mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
6808647: (file) Paths.get("C:").newDirectoryStream() iterates over Path elements with additional slash [win]
6808648: (file) Files.walkFileTree should obtain file attributes during iteration [win] Reviewed-by: sherman
This commit is contained in:
parent
5efe4b020a
commit
6d59271ca9
10 changed files with 316 additions and 46 deletions
|
@ -252,6 +252,7 @@ FILES_src = \
|
||||||
sun/nio/fs/AbstractUserDefinedFileAttributeView.java \
|
sun/nio/fs/AbstractUserDefinedFileAttributeView.java \
|
||||||
sun/nio/fs/AbstractWatchKey.java \
|
sun/nio/fs/AbstractWatchKey.java \
|
||||||
sun/nio/fs/AbstractWatchService.java \
|
sun/nio/fs/AbstractWatchService.java \
|
||||||
|
sun/nio/fs/BasicFileAttributesHolder.java \
|
||||||
sun/nio/fs/Cancellable.java \
|
sun/nio/fs/Cancellable.java \
|
||||||
sun/nio/fs/DefaultFileSystemProvider.java \
|
sun/nio/fs/DefaultFileSystemProvider.java \
|
||||||
sun/nio/fs/DefaultFileTypeDetector.java \
|
sun/nio/fs/DefaultFileTypeDetector.java \
|
||||||
|
|
|
@ -28,6 +28,7 @@ package java.nio.file;
|
||||||
import java.nio.file.attribute.*;
|
import java.nio.file.attribute.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import sun.nio.fs.BasicFileAttributesHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple file tree walker that works in a similar manner to nftw(3C).
|
* Simple file tree walker that works in a similar manner to nftw(3C).
|
||||||
|
@ -65,6 +66,10 @@ class FileTreeWalker {
|
||||||
* Walk file tree starting at the given file
|
* Walk file tree starting at the given file
|
||||||
*/
|
*/
|
||||||
void walk(Path start, int maxDepth) {
|
void walk(Path start, int maxDepth) {
|
||||||
|
// don't use attributes of starting file as they may be stale
|
||||||
|
if (start instanceof BasicFileAttributesHolder) {
|
||||||
|
((BasicFileAttributesHolder)start).invalidate();
|
||||||
|
}
|
||||||
FileVisitResult result = walk(start,
|
FileVisitResult result = walk(start,
|
||||||
maxDepth,
|
maxDepth,
|
||||||
new ArrayList<AncestorDirectory>());
|
new ArrayList<AncestorDirectory>());
|
||||||
|
@ -75,11 +80,9 @@ class FileTreeWalker {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param file
|
* @param file
|
||||||
* The directory to visit
|
* the directory to visit
|
||||||
* @param path
|
|
||||||
* list of directories that is relative path from starting file
|
|
||||||
* @param depth
|
* @param depth
|
||||||
* Depth remaining
|
* depth remaining
|
||||||
* @param ancestors
|
* @param ancestors
|
||||||
* use when cycle detection is enabled
|
* use when cycle detection is enabled
|
||||||
*/
|
*/
|
||||||
|
@ -91,11 +94,18 @@ class FileTreeWalker {
|
||||||
if (depth-- < 0)
|
if (depth-- < 0)
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
|
|
||||||
|
// if attributes are cached then use them if possible
|
||||||
BasicFileAttributes attrs = null;
|
BasicFileAttributes attrs = null;
|
||||||
|
if (file instanceof BasicFileAttributesHolder) {
|
||||||
|
BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
|
||||||
|
if (!followLinks || !cached.isSymbolicLink())
|
||||||
|
attrs = cached;
|
||||||
|
}
|
||||||
IOException exc = null;
|
IOException exc = null;
|
||||||
|
|
||||||
// attempt to get attributes of file. If fails and we are following
|
// attempt to get attributes of file. If fails and we are following
|
||||||
// links then a link target might not exist so get attributes of link
|
// links then a link target might not exist so get attributes of link
|
||||||
|
if (attrs == null) {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
attrs = Attributes.readBasicFileAttributes(file, linkOptions);
|
attrs = Attributes.readBasicFileAttributes(file, linkOptions);
|
||||||
|
@ -114,6 +124,7 @@ class FileTreeWalker {
|
||||||
} catch (SecurityException x) {
|
} catch (SecurityException x) {
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// unable to get attributes of file
|
// unable to get attributes of file
|
||||||
if (exc != null) {
|
if (exc != null) {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008-2009 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. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun 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 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.nio.fs;
|
||||||
|
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemented by objects that may hold or cache the attributes of a file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface BasicFileAttributesHolder {
|
||||||
|
/**
|
||||||
|
* Returns cached attributes (may be null). If file is a symbolic link then
|
||||||
|
* the attributes are the link attributes and not the final target of the
|
||||||
|
* file.
|
||||||
|
*/
|
||||||
|
BasicFileAttributes get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates cached attributes
|
||||||
|
*/
|
||||||
|
void invalidate();
|
||||||
|
}
|
|
@ -26,6 +26,7 @@
|
||||||
package sun.nio.fs;
|
package sun.nio.fs;
|
||||||
|
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
@ -49,6 +50,9 @@ class WindowsDirectoryStream
|
||||||
// first entry in the directory
|
// first entry in the directory
|
||||||
private final String firstName;
|
private final String firstName;
|
||||||
|
|
||||||
|
// buffer for WIN32_FIND_DATA structure that receives information about file
|
||||||
|
private final NativeBuffer findDataBuffer;
|
||||||
|
|
||||||
private final Object closeLock = new Object();
|
private final Object closeLock = new Object();
|
||||||
|
|
||||||
// need closeLock to access these
|
// need closeLock to access these
|
||||||
|
@ -75,6 +79,7 @@ class WindowsDirectoryStream
|
||||||
FirstFile first = FindFirstFile(search);
|
FirstFile first = FindFirstFile(search);
|
||||||
this.handle = first.handle();
|
this.handle = first.handle();
|
||||||
this.firstName = first.name();
|
this.firstName = first.name();
|
||||||
|
this.findDataBuffer = WindowsFileAttributes.getBufferForFindData();
|
||||||
} catch (WindowsException x) {
|
} catch (WindowsException x) {
|
||||||
if (x.lastError() == ERROR_DIRECTORY) {
|
if (x.lastError() == ERROR_DIRECTORY) {
|
||||||
throw new NotDirectoryException(dir.getPathForExceptionMessage());
|
throw new NotDirectoryException(dir.getPathForExceptionMessage());
|
||||||
|
@ -95,6 +100,7 @@ class WindowsDirectoryStream
|
||||||
return;
|
return;
|
||||||
isOpen = false;
|
isOpen = false;
|
||||||
}
|
}
|
||||||
|
findDataBuffer.release();
|
||||||
try {
|
try {
|
||||||
FindClose(handle);
|
FindClose(handle);
|
||||||
} catch (WindowsException x) {
|
} catch (WindowsException x) {
|
||||||
|
@ -133,11 +139,19 @@ class WindowsDirectoryStream
|
||||||
}
|
}
|
||||||
|
|
||||||
// applies filter and also ignores "." and ".."
|
// applies filter and also ignores "." and ".."
|
||||||
private Path acceptEntry(String s) {
|
private Path acceptEntry(String s, BasicFileAttributes attrs) {
|
||||||
if (s.equals(".") || s.equals(".."))
|
if (s.equals(".") || s.equals(".."))
|
||||||
return null;
|
return null;
|
||||||
|
if (dir.needsSlashWhenResolving()) {
|
||||||
|
StringBuilder sb = new StringBuilder(dir.toString());
|
||||||
|
sb.append('\\');
|
||||||
|
sb.append(s);
|
||||||
|
s = sb.toString();
|
||||||
|
} else {
|
||||||
|
s = dir + s;
|
||||||
|
}
|
||||||
Path entry = WindowsPath
|
Path entry = WindowsPath
|
||||||
.createFromNormalizedPath(dir.getFileSystem(), dir + "\\" + s);
|
.createFromNormalizedPath(dir.getFileSystem(), s, attrs);
|
||||||
if (filter.accept(entry)) {
|
if (filter.accept(entry)) {
|
||||||
return entry;
|
return entry;
|
||||||
} else {
|
} else {
|
||||||
|
@ -149,21 +163,27 @@ class WindowsDirectoryStream
|
||||||
private Path readNextEntry() {
|
private Path readNextEntry() {
|
||||||
// handle first element returned by search
|
// handle first element returned by search
|
||||||
if (first != null) {
|
if (first != null) {
|
||||||
nextEntry = acceptEntry(first);
|
nextEntry = acceptEntry(first, null);
|
||||||
first = null;
|
first = null;
|
||||||
if (nextEntry != null)
|
if (nextEntry != null)
|
||||||
return nextEntry;
|
return nextEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = null;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
String name = null;
|
||||||
|
WindowsFileAttributes attrs;
|
||||||
|
|
||||||
// synchronize on closeLock to prevent close while reading
|
// synchronize on closeLock to prevent close while reading
|
||||||
synchronized (closeLock) {
|
synchronized (closeLock) {
|
||||||
if (!isOpen)
|
if (!isOpen)
|
||||||
throwAsConcurrentModificationException(new
|
throwAsConcurrentModificationException(new
|
||||||
IllegalStateException("Directory stream is closed"));
|
IllegalStateException("Directory stream is closed"));
|
||||||
try {
|
try {
|
||||||
name = FindNextFile(handle);
|
name = FindNextFile(handle, findDataBuffer.address());
|
||||||
|
if (name == null) {
|
||||||
|
// NO_MORE_FILES
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} catch (WindowsException x) {
|
} catch (WindowsException x) {
|
||||||
try {
|
try {
|
||||||
x.rethrowAsIOException(dir);
|
x.rethrowAsIOException(dir);
|
||||||
|
@ -171,13 +191,16 @@ class WindowsDirectoryStream
|
||||||
throwAsConcurrentModificationException(ioe);
|
throwAsConcurrentModificationException(ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// return entry if accepted by filter
|
||||||
if (name == null)
|
Path entry = acceptEntry(name, attrs);
|
||||||
return null;
|
|
||||||
|
|
||||||
Path entry = acceptEntry(name);
|
|
||||||
if (entry != null)
|
if (entry != null)
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,29 @@ class WindowsFileAttributes
|
||||||
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH = 28;
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH = 28;
|
||||||
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW = 32;
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* typedef struct _WIN32_FIND_DATA {
|
||||||
|
* DWORD dwFileAttributes;
|
||||||
|
* FILETIME ftCreationTime;
|
||||||
|
* FILETIME ftLastAccessTime;
|
||||||
|
* FILETIME ftLastWriteTime;
|
||||||
|
* DWORD nFileSizeHigh;
|
||||||
|
* DWORD nFileSizeLow;
|
||||||
|
* DWORD dwReserved0;
|
||||||
|
* DWORD dwReserved1;
|
||||||
|
* TCHAR cFileName[MAX_PATH];
|
||||||
|
* TCHAR cAlternateFileName[14];
|
||||||
|
* } WIN32_FIND_DATA;
|
||||||
|
*/
|
||||||
|
private static final short SIZEOF_FIND_DATA = 592;
|
||||||
|
private static final short OFFSETOF_FIND_DATA_ATTRIBUTES = 0;
|
||||||
|
private static final short OFFSETOF_FIND_DATA_CREATETIME = 4;
|
||||||
|
private static final short OFFSETOF_FIND_DATA_LASTACCESSTIME = 12;
|
||||||
|
private static final short OFFSETOF_FIND_DATA_LASTWRITETIME = 20;
|
||||||
|
private static final short OFFSETOF_FIND_DATA_SIZEHIGH = 28;
|
||||||
|
private static final short OFFSETOF_FIND_DATA_SIZELOW = 32;
|
||||||
|
private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36;
|
||||||
|
|
||||||
// indicates if accurate metadata is required (interesting on NTFS only)
|
// indicates if accurate metadata is required (interesting on NTFS only)
|
||||||
private static final boolean ensureAccurateMetadata;
|
private static final boolean ensureAccurateMetadata;
|
||||||
static {
|
static {
|
||||||
|
@ -210,6 +233,41 @@ class WindowsFileAttributes
|
||||||
0); // fileIndexLow
|
0); // fileIndexLow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a native buffer for a WIN32_FIND_DATA structure
|
||||||
|
*/
|
||||||
|
static NativeBuffer getBufferForFindData() {
|
||||||
|
return NativeBuffers.getNativeBuffer(SIZEOF_FIND_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a WindowsFileAttributes from a WIN32_FIND_DATA structure
|
||||||
|
*/
|
||||||
|
static WindowsFileAttributes fromFindData(long address) {
|
||||||
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_FIND_DATA_ATTRIBUTES);
|
||||||
|
long creationTime =
|
||||||
|
toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME));
|
||||||
|
long lastAccessTime =
|
||||||
|
toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME));
|
||||||
|
long lastWriteTime =
|
||||||
|
toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME));
|
||||||
|
long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32)
|
||||||
|
+ (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL);
|
||||||
|
int reparseTag = ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ?
|
||||||
|
+ unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0;
|
||||||
|
return new WindowsFileAttributes(fileAttrs,
|
||||||
|
creationTime,
|
||||||
|
lastAccessTime,
|
||||||
|
lastWriteTime,
|
||||||
|
size,
|
||||||
|
reparseTag,
|
||||||
|
1, // linkCount
|
||||||
|
0, // volSerialNumber
|
||||||
|
0, // fileIndexHigh
|
||||||
|
0); // fileIndexLow
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the attributes of an open file
|
* Reads the attributes of an open file
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -236,11 +236,9 @@ class WindowsFileSystem
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path getPath(String path) {
|
public Path getPath(String path) {
|
||||||
WindowsPathParser.Result result = WindowsPathParser.parse(path);
|
return WindowsPath.parse(this, path);
|
||||||
return new WindowsPath(this, result.type(), result.root(), result.path());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserPrincipalLookupService getUserPrincipalLookupService() {
|
public UserPrincipalLookupService getUserPrincipalLookupService() {
|
||||||
return theLookupService;
|
return theLookupService;
|
||||||
|
|
|
@ -211,9 +211,10 @@ class WindowsNativeDispatcher {
|
||||||
* LPWIN32_FIND_DATA lpFindFileData
|
* LPWIN32_FIND_DATA lpFindFileData
|
||||||
* )
|
* )
|
||||||
*
|
*
|
||||||
* @return lpFindFileData->cFileName
|
* @return lpFindFileData->cFileName or null
|
||||||
*/
|
*/
|
||||||
static native String FindNextFile(long handle) throws WindowsException;
|
static native String FindNextFile(long handle, long address)
|
||||||
|
throws WindowsException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HANDLE FindFirstStreamW(
|
* HANDLE FindFirstStreamW(
|
||||||
|
|
|
@ -83,7 +83,7 @@ class WindowsPath extends AbstractPath {
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of this class.
|
* Initializes a new instance of this class.
|
||||||
*/
|
*/
|
||||||
WindowsPath(WindowsFileSystem fs,
|
private WindowsPath(WindowsFileSystem fs,
|
||||||
WindowsPathType type,
|
WindowsPathType type,
|
||||||
String root,
|
String root,
|
||||||
String path)
|
String path)
|
||||||
|
@ -95,7 +95,7 @@ class WindowsPath extends AbstractPath {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a WindowsPath by parsing the given path.
|
* Creates a Path by parsing the given path.
|
||||||
*/
|
*/
|
||||||
static WindowsPath parse(WindowsFileSystem fs, String path) {
|
static WindowsPath parse(WindowsFileSystem fs, String path) {
|
||||||
WindowsPathParser.Result result = WindowsPathParser.parse(path);
|
WindowsPathParser.Result result = WindowsPathParser.parse(path);
|
||||||
|
@ -103,18 +103,71 @@ class WindowsPath extends AbstractPath {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a WindowsPath from a given path that is known to be normalized.
|
* Creates a Path from a given path that is known to be normalized.
|
||||||
*/
|
*/
|
||||||
static WindowsPath createFromNormalizedPath(WindowsFileSystem fs, String path) {
|
static WindowsPath createFromNormalizedPath(WindowsFileSystem fs,
|
||||||
|
String path,
|
||||||
|
BasicFileAttributes attrs)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
WindowsPathParser.Result result =
|
WindowsPathParser.Result result =
|
||||||
WindowsPathParser.parseNormalizedPath(path);
|
WindowsPathParser.parseNormalizedPath(path);
|
||||||
return new WindowsPath(fs, result.type(), result.root(), result.path());
|
if (attrs == null) {
|
||||||
|
return new WindowsPath(fs,
|
||||||
|
result.type(),
|
||||||
|
result.root(),
|
||||||
|
result.path());
|
||||||
|
} else {
|
||||||
|
return new WindowsPathWithAttributes(fs,
|
||||||
|
result.type(),
|
||||||
|
result.root(),
|
||||||
|
result.path(),
|
||||||
|
attrs);
|
||||||
|
}
|
||||||
} catch (InvalidPathException x) {
|
} catch (InvalidPathException x) {
|
||||||
throw new AssertionError(x.getMessage());
|
throw new AssertionError(x.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a WindowsPath from a given path that is known to be normalized.
|
||||||
|
*/
|
||||||
|
static WindowsPath createFromNormalizedPath(WindowsFileSystem fs,
|
||||||
|
String path)
|
||||||
|
{
|
||||||
|
return createFromNormalizedPath(fs, path, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special implementation with attached/cached attributes (used to quicken
|
||||||
|
* file tree traveral)
|
||||||
|
*/
|
||||||
|
private static class WindowsPathWithAttributes
|
||||||
|
extends WindowsPath implements BasicFileAttributesHolder
|
||||||
|
{
|
||||||
|
final WeakReference<BasicFileAttributes> ref;
|
||||||
|
|
||||||
|
WindowsPathWithAttributes(WindowsFileSystem fs,
|
||||||
|
WindowsPathType type,
|
||||||
|
String root,
|
||||||
|
String path,
|
||||||
|
BasicFileAttributes attrs)
|
||||||
|
{
|
||||||
|
super(fs, type, root, path);
|
||||||
|
ref = new WeakReference<BasicFileAttributes>(attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicFileAttributes get() {
|
||||||
|
return ref.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate() {
|
||||||
|
ref.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// use this message when throwing exceptions
|
// use this message when throwing exceptions
|
||||||
String getPathForExceptionMessage() {
|
String getPathForExceptionMessage() {
|
||||||
return path;
|
return path;
|
||||||
|
@ -290,6 +343,12 @@ class WindowsPath extends AbstractPath {
|
||||||
return type == WindowsPathType.UNC;
|
return type == WindowsPathType.UNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean needsSlashWhenResolving() {
|
||||||
|
if (path.endsWith("\\"))
|
||||||
|
return false;
|
||||||
|
return path.length() > root.length();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAbsolute() {
|
public boolean isAbsolute() {
|
||||||
return type == WindowsPathType.ABSOLUTE || type == WindowsPathType.UNC;
|
return type == WindowsPathType.ABSOLUTE || type == WindowsPathType.UNC;
|
||||||
|
|
|
@ -392,13 +392,13 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile1(JNIEnv* env, jclass this,
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL
|
JNIEXPORT jstring JNICALL
|
||||||
Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this,
|
Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this,
|
||||||
jlong handle)
|
jlong handle, jlong dataAddress)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAW data;
|
|
||||||
HANDLE h = (HANDLE)jlong_to_ptr(handle);
|
HANDLE h = (HANDLE)jlong_to_ptr(handle);
|
||||||
|
WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress);
|
||||||
|
|
||||||
if (FindNextFileW(h, &data) != 0) {
|
if (FindNextFileW(h, data) != 0) {
|
||||||
return (*env)->NewString(env, data.cFileName, wcslen(data.cFileName));
|
return (*env)->NewString(env, data->cFileName, wcslen(data->cFileName));
|
||||||
} else {
|
} else {
|
||||||
if (GetLastError() != ERROR_NO_MORE_FILES)
|
if (GetLastError() != ERROR_NO_MORE_FILES)
|
||||||
throwWindowsException(env, GetLastError());
|
throwWindowsException(env, GetLastError());
|
||||||
|
|
73
jdk/test/java/nio/file/DirectoryStream/DriveLetter.java
Normal file
73
jdk/test/java/nio/file/DirectoryStream/DriveLetter.java
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008-2009 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 6808647
|
||||||
|
* @summary Checks that a DirectoryStream's iterator returns the expected
|
||||||
|
* path when opening a directory by specifying only the drive letter.
|
||||||
|
* @library ..
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DriveLetter {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
String os = System.getProperty("os.name");
|
||||||
|
if (!os.startsWith("Windows")) {
|
||||||
|
System.out.println("This is Windows specific test");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String here = System.getProperty("user.dir");
|
||||||
|
if (here.length() < 2 || here.charAt(1) != ':')
|
||||||
|
throw new RuntimeException("Unable to determine drive letter");
|
||||||
|
|
||||||
|
// create temporary file in current directory
|
||||||
|
File tempFile = File.createTempFile("foo", "tmp", new File(here));
|
||||||
|
try {
|
||||||
|
// we should expect C:foo.tmp to be returned by iterator
|
||||||
|
String drive = here.substring(0, 2);
|
||||||
|
Path expected = Paths.get(drive).resolve(tempFile.getName());
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
DirectoryStream<Path> stream = Paths.get(drive).newDirectoryStream();
|
||||||
|
try {
|
||||||
|
for (Path file : stream) {
|
||||||
|
if (file.equals(expected)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
throw new RuntimeException("Temporary file not found???");
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
tempFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue